大恒相机 - Python 多线程拍摄

大恒相机Python Pyside6/PyQt Qthread多线程开发调试记录


文章目录

  • 大恒相机Python Pyside6/PyQt Qthread多线程开发调试记录
  • 前言
  • 一、上位机运行效果
  • 二、代码说明
    • 1.总体代码
      • 1.1 导入 Python 包
      • 1.2 定义回调函数
      • 1.3 定义线程类
      • 1.4 定义 UI 窗口界面
      • 1.5 主函数
    • 2.代码说明
  • 总结


前言

前一篇记录了如何使用大恒相机的Python SDK采集图像,这一篇根据Pyside6官方示例OpenCV人脸识别开发上位机。


一、上位机运行效果

上位机效果图

二、代码说明

1.总体代码

代码如下:

1.1 导入 Python 包

import os
import sys
import time
import gxipy as gx
from PIL import Image

import cv2
from PySide6.QtCore import Qt, QThread, Signal, Slot
from PySide6.QtGui import QAction, QImage, QKeySequence, QPixmap
from PySide6.QtWidgets import (QApplication, QComboBox, QGroupBox,
                               QHBoxLayout, QLabel, QMainWindow, QPushButton,
                               QSizePolicy, QVBoxLayout, QWidget)
from PySide6 import QtWidgets
rgb_image = None
numpy_image = None
gray_frame = None

1.2 定义回调函数

def capture_callback_color(raw_image):
    global rgb_image, numpy_image, gray_frame
    print("Frame ID: %d   Height: %d   Width: %d"
          % (raw_image.get_frame_id(), raw_image.get_height(), raw_image.get_width()))

    # get RGB image from raw image
    # 设置图片参数
    rgb_image = raw_image.convert("RGB")
    rgb_image.brightness(75)
    rgb_image.contrast(-25)
    if rgb_image is None:
        print('Failed to convert RawImage to RGBImage')
        return

    # create numpy array with data from rgb image
    numpy_image = rgb_image.get_numpy_array()
    if numpy_image is None:
        print('Failed to get numpy array from RGBImage')
        return

    gray_frame = cv2.cvtColor(numpy_image, cv2.COLOR_RGB2GRAY)

1.3 定义线程类

该类继承自 Thread()

class Thread(QThread):
    updateFrame = Signal(QImage)

    def __init__(self, parent=None):
        QThread.__init__(self, parent)
        self.img = None
        self.scaled_img = None
        self.dev_info_list = None
        self.dev_num = None
        self.device_manager = None
        self.cam = None
        self.trained_file = None
        self.status = True
        self.cap = True

    def set_file(self, fname):
        self.trained_file = os.path.join(cv2.data.haarcascades, fname)

    def run(self):
        self.device_manager = gx.DeviceManager()
        self.dev_num, self.dev_info_list = self.device_manager.update_device_list()
        if self.dev_num == 0:
            print("Number of enumerated devices is 0")
            return
        self.cam = self.device_manager.open_device_by_index(1)
        self.cam.GainAuto = 1
        self.cam.BalanceWhiteAuto = 1
        self.cam.DeviceLinkThroughputLimitMode = 0
        self.cam.ExposureAuto = 1
        self.cam.AutoExposureTimeMax = 10000
        self.cam.UserSetSelector = 1
        self.data_stream = self.cam.data_stream[0]
        self.data_stream.register_capture_callback(capture_callback_color)
        self.cam.stream_on()
        time.sleep(0.1)
        while self.status:
            cascade = cv2.CascadeClassifier(self.trained_file)

            detections = cascade.detectMultiScale(gray_frame, scaleFactor=1.1,
                                                  minNeighbors=5, minSize=(30, 30))

            # Drawing green rectangle around the pattern
            for (x, y, w, h) in detections:
                pos_ori = (x, y)
                pos_end = (x + w, y + h)
                color = (0, 255, 0)
                cv2.rectangle(numpy_image, pos_ori, pos_end, color, 2)

            # Reading the image in RGB to display it
            color_frame = numpy_image
            # Creating and scaling QImage
            h, w, ch = color_frame.shape
            self.img = QImage(color_frame.data, w, h, ch * w, QImage.Format_RGB888)
            self.scaled_img = self.img.scaled(640, 480, Qt.KeepAspectRatio)

            # Emit signal
            self.updateFrame.emit(self.scaled_img)
            time.sleep(0.05)
        sys.exit(-1)

1.4 定义 UI 窗口界面

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        # Title and dimensions
        self.setWindowTitle("Patterns detection")
        self.setGeometry(0, 0, 800, 500)

        # Main menu bar
        self.menu = self.menuBar()
        self.menu_file = self.menu.addMenu("File")
        exit = QAction("Exit", self, triggered=qApp.quit)
        self.menu_file.addAction(exit)

        self.menu_about = self.menu.addMenu("&About")
        about = QAction("About Qt", self, shortcut=QKeySequence(QKeySequence.HelpContents),
                        triggered=qApp.aboutQt)
        self.menu_about.addAction(about)

        # Create a label for the display camera
        self.label = QLabel(self)
        self.label.setFixedSize(640, 480)

        # Model group
        self.group_model = QGroupBox("Trained model")
        self.group_model.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        model_layout = QHBoxLayout()

        self.combobox = QComboBox()
        for xml_file in os.listdir(cv2.data.haarcascades):
            if xml_file.endswith(".xml"):
                self.combobox.addItem(xml_file)

        model_layout.addWidget(QLabel("File:"), 10)
        model_layout.addWidget(self.combobox, 90)
        self.group_model.setLayout(model_layout)

        # Buttons layout
        buttons_layout = QHBoxLayout()
        self.button1 = QPushButton("Start")
        self.button2 = QPushButton("Stop/Close")
        self.button1.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        self.button2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        buttons_layout.addWidget(self.button2)
        buttons_layout.addWidget(self.button1)

        right_layout = QHBoxLayout()
        right_layout.addWidget(self.group_model, 1)
        right_layout.addLayout(buttons_layout, 1)

        # Main layout
        layout = QVBoxLayout()
        layout.addWidget(self.label)
        layout.addLayout(right_layout)

        # Central widget
        widget = QWidget(self)
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        # Connections
        self.button1.clicked.connect(self.start)
        self.button2.clicked.connect(self.kill_thread)
        self.button2.setEnabled(False)
        self.combobox.currentTextChanged.connect(self.set_model)

    @Slot()
    def set_model(self, text):
        self.th.set_file(text)

    @Slot()
    def kill_thread(self):
        print("Finishing...")
        self.button2.setEnabled(False)
        self.button1.setEnabled(True)
        self.status = False
        self.th.scaled_img.save("img.jpg")
        self.th.cam.stream_off()
        self.th.cam.data_stream[0].unregister_capture_callback()
        self.th.cam.close_device()
        self.th.quit()
        self.button2.setEnabled(True)
        print("over")

    @Slot()
    def start(self):
        print("Starting...")
        self.button2.setEnabled(True)
        self.button1.setEnabled(False)
        self.th = Thread(self)
        self.th.finished.connect(self.close)
        self.th.updateFrame.connect(self.setImage)
        self.th.set_file(self.combobox.currentText())
        self.th.start()

    @Slot(QImage)
    def setImage(self, image):
        self.label.setPixmap(QPixmap.fromImage(image))

1.5 主函数

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = Window()
    w.show()
    print("正在运行")
    sys.exit(app.exec())

2.代码说明

相机线程代码中,run()函数下即为用户需要在子线程中执行的程序,我这里主要是采集图像并且将图像作为型号发送,另外需要注意的是相机捕获图像线程的对象不能在主函数中创建,否则相机线程停止将导致窗口关闭,主程序结束,对象要在槽函数中创建,这样相机才能重复启停。


总结

可根据此示例编写自定义程序。


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值