IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 大恒相机Python版Qt界面(一) -> 正文阅读

[Python知识库]大恒相机Python版Qt界面(一)

? ? ? ? 首先,很抱歉之前写的Qt、C++的UI界面鸽了。。。这次的大恒相机界面python版一定坚持写完。

? ? ? ? 在大恒相机给的Python示例中找不到完整界面的示例代码,且示例很不完善。由于示例中未使用到多线程的概念(threading),因此也无法直接从示例中修改代码,做一个有效界面。因此,我仿照大恒相机linux系统下的C代码示例,写了这个大恒相机UI界面。由于功能众多,长期更新中。

? ? ? ? 本节内容:实现大恒相机采图与UI中显示功能。

? ? ? ? 目前功能有:1、更新相机列表;2、打开/关闭相机;3、开始/停止采集;4、界面中显示采集图片及放大缩小功能;

? ? ? ? 注:1、大恒相机的开发文档其实很详细,因此环境搭建等问题这里不再叙述。

? ? ? ? ? ? ? ? 2、PyQt用法不再叙述。

1、项目结构:

? ? ? ? 其中,gxipy为大恒提供的库文件,UI中存放了UI界面,DahengCamera.py是自己写的相机控制类(相机采集使用了回调函数方式),mian.py为主界面函数。

2、UI界面:

? ? ? ? UI界面如下:

? ? ? ? 这里有个注意事项:在本UI界面中,相机的实时显示图像选择了QGraphicsView控件而非QLabel控制,主要原因是因为前者非常容易实现图像显示的放大、缩小功能。

?3、大恒相机控制函数代码如下:

import gxipy as gx
import time
import threading

rawImageUpdateList = []
rawImageUpdate = None
num = 0


def capture_callback(raw_image):
    if raw_image.get_status() == gx.GxFrameStatusList.INCOMPLETE:
        print("incomplete frame")
    else:
        global rawImageUpdateList, num, rawImageUpdate
        rawImageUpdate = raw_image.get_numpy_array()
        if len(rawImageUpdateList) == 0:
            rawImageUpdateList.append(rawImageUpdate)
        else:
            rawImageUpdateList.pop()
            rawImageUpdateList.append(rawImageUpdate)
        num += 1


class DahengCamera:
    def __init__(self):
        self.cam = None             #   相机对象
        self.dev_num = None
        self.dev_info_list = None
        self.device_manager = gx.DeviceManager()
        self.AcquisitionThread = None
        self.AcquisitionThreadNeedBeStop = False
        self.IsCameraOpened = False
        self.IsCameraStartAcq = False

    def UpdateCameraList(self):
        self.dev_num, self.dev_info_list = self.device_manager.update_device_list()
        if self.dev_num == 0:
            return False, '0'
        else:
            CameraNameList = []
            for info in self.dev_info_list:
                name = info['model_name']
                CameraNameList.append(name)
            return True, CameraNameList

    def OpenCamera(self, Index):
        if self.dev_num == 0:
            return False
        elif self.IsCameraOpened:
            return True
        else:
            self.cam = self.device_manager.open_device_by_index(Index)

        self.AcquisitionThread = threading.Thread(target=self.AcquisitionThreadFunc_CallBack, args=(), daemon=True)
        self.AcquisitionThread.start()
        self.IsCameraOpened = True

        return True

    def AcquisitionThreadFunc_CallBack(self):
        self.cam.data_stream[0].register_capture_callback(capture_callback)

        while not self.AcquisitionThreadNeedBeStop:
            time.sleep(1)

    def CloseCamera(self, Index):
        if not self.IsCameraOpened:
            return

        self.AcquisitionThreadNeedBeStop = True
        self.StopAcquisition()
        time.sleep(1)
        self.cam.data_stream[0].unregister_capture_callback()
        self.cam.close_device()

        self.IsCameraOpened = False

    def StartAcquisition(self):
        if self.IsCameraOpened and not self.IsCameraStartAcq:
            self.cam.stream_on()
            self.IsCameraStartAcq = True
        else:
            return

    def StopAcquisition(self):
        if self.IsCameraOpened and self.IsCameraStartAcq:
            self.cam.stream_off()
            self.IsCameraStartAcq = False
        else:
            return

? ? ? ? 相机控制类的主要思路为:当每次调用OpenCamera时,会开启一个新的线程,在新线程中,进行相机回调函数的注册。随后,该线程将一直负责进行回调函数的运行工作,直到CloseCamera函数被调用。通过开辟一个新线程,可以有效的将界面显示跟相机回调分开,避免了画面的卡顿以及图像丢帧等问题。

? ? ? ? 针对图像丢帧问题,有一点非常重要,即:不要在回调函数中进行任何复杂的数值计算或图像存储等工作。回调函数的主要工作机制是每当相机采集到一张图像,回调函数便会自动运行一次。而回调函数的整个运行时间取决于回调函数中进行的操作数量。若相机采集帧率非常高,而一次回调函数的处理时间跟不上采集帧率,很显然就会出现丢帧情况。因此,若要进行图像存储会其他处理操作,建议申请一个list变量,将采集到的图像保存在list中,随后在主线程中进行相应操作。(该部分内容后续随缘更新)

4、主界面代码如下:

import sys

from PyQt5 import QtWidgets, QtSerialPort, QtCore
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from UI.MainWindow import Ui_MainWindow
import cv2
import DahengCamera


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.Camera = DahengCamera.DahengCamera()
        self.TimerForShowImageInGraphicsView = QTimer()
        self.ImageWidthInGraphicsView = 500
        self.scene = QGraphicsScene()

        self.SlotInit()
        self.UpdateUI()

    """ 初始化槽信号函数"""
    def SlotInit(self):
        self.ui.pushButton_UpdateCameraList.clicked.connect(self.PB_UpdateCameraList_clicked)
        self.ui.pushButton_OpenCamera.clicked.connect(self.PB_OpenCamera_clicked)
        self.ui.pushButton_CloseCamera.clicked.connect(self.PB_CloseCamera_clicked)
        self.ui.pushButton_StartAcq.clicked.connect(self.PB_StartAcq_clicked)
        self.ui.pushButton_StopAcq.clicked.connect(self.PB_StopAcq_clicked)
        self.ui.pushButton_ZoomIn.clicked.connect(self.PB_ZoomIn_clicked)
        self.ui.pushButton_ZoomOut.clicked.connect(self.PB_ZoomOut_clicked)
        self.TimerForShowImageInGraphicsView.timeout.connect(self.SlotForShowImageInGraphicsView)

    """ 更新UI界面"""
    def UpdateUI(self):
        self.ui.pushButton_OpenCamera.setDisabled(self.Camera.IsCameraOpened)
        self.ui.pushButton_CloseCamera.setDisabled(not self.Camera.IsCameraOpened)
        self.ui.pushButton_StartAcq.setDisabled(not self.Camera.IsCameraOpened or self.Camera.IsCameraStartAcq)
        self.ui.pushButton_StopAcq.setDisabled(not self.Camera.IsCameraStartAcq)

    """ 点击UpdateCameraList"""
    def PB_UpdateCameraList_clicked(self):
        status, CameraNameList = self.Camera.UpdateCameraList()
        if status:
            for CameraName in CameraNameList:
                self.ui.comboBox_CameraList.addItem(CameraName)

    """ 点击OpenCamera"""
    def PB_OpenCamera_clicked(self):
        if self.ui.comboBox_CameraList.count() == 0:
            return
        self.Camera.OpenCamera(int(self.ui.comboBox_CameraList.currentIndex()) + 1)
        self.UpdateUI()

    """ 点击CloseCamera"""
    def PB_CloseCamera_clicked(self):
        self.Camera.CloseCamera(int(self.ui.comboBox_CameraList.currentIndex()) + 1)
        if self.TimerForShowImageInGraphicsView.isActive():
            self.TimerForShowImageInGraphicsView.stop()
        self.UpdateUI()

    """ 点击StartAcq"""
    def PB_StartAcq_clicked(self):
        self.Camera.StartAcquisition()
        self.TimerForShowImageInGraphicsView.start(33)
        self.UpdateUI()

    """ 点击StopAcq"""
    def PB_StopAcq_clicked(self):
        self.Camera.StopAcquisition()
        self.TimerForShowImageInGraphicsView.stop()
        self.UpdateUI()

    """ 点击ZoomIn"""
    def PB_ZoomIn_clicked(self):
        self.ImageWidthInGraphicsView += 100

    """ 点击ZoomOut"""
    def PB_ZoomOut_clicked(self):
        if self.ImageWidthInGraphicsView >= 200:
            self.ImageWidthInGraphicsView -= 100

    """ 图像显示回调函数"""
    def SlotForShowImageInGraphicsView(self):
        if DahengCamera.rawImageUpdate is None:
            return
        else:
            ImageShow = DahengCamera.rawImageUpdateList[0]
            ImageRatio = float(ImageShow.shape[0] / ImageShow.shape[1])
            image_width = self.ImageWidthInGraphicsView
            show = cv2.resize(ImageShow, (image_width, int(image_width * ImageRatio)))
            show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)  # 视频色彩转换回RGB,这样才是现实的颜色
            showImage = QImage(show.data, show.shape[1], show.shape[0],
                               QImage.Format_RGB888)  # 把读取到的视频数据变成QImage形式
            item = QGraphicsPixmapItem(QPixmap.fromImage(showImage))
            self.scene.clear()
            self.scene.addItem(item)
            self.scene.setSceneRect(0, 0, image_width + 1, image_width * ImageRatio + 1)
            self.ui.graphicsView.setScene(self.scene)
            self.ui.graphicsView.show()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()

    sys.exit(app.exec_())

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:24:34  更:2022-09-21 00:25:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 10:12:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码