书接上回,硬件完了就是代码了,最开始我导儿让我用c++写,最后又让我用python写,学习了很多东西。

二、代码方面

我还建议,先带着你的目的去看官方的说明文档,真的,很有用。

因为本人代码能力巨垃圾,所有代码大家看个乐就是了,主要分享一下我做的流程和遇到的各种问题的解决办法。

先python吧。

然是Linux,就得弄一个虚拟机,我用的是ubantu,vmware,这些教程很多,自己搜一下,找一个合适的就是。

我建议虚拟机的内存弄大一点,我开始40g,但是下载一些东西后就会卡在开机哪儿,巨不好弄,后面调到100g就好多了,然后下载个conda,因为大恒的那个api很坑壁,有时候会报莫名其妙的错误,实测python3.8很合适(但是不是最合适我就不知道了),这个时候你就得去学习一下怎么创建环境啊,怎么用conda啊巴拉巴拉的。

还有就是pyqt5的使用,实名推荐b站的王铭东up的那个课,超级棒!

接着就是代码,我的代码在这儿,ui文件super and very简单,看着代码都能自己编出来,我就不放出来了。

import gxipy as gx
# from PIL import Image
import os
import cv2
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow, QMessageBox, QLabel,QComboBox
from PyQt5 import uic
from threading import Thread
from PyQt5.QtCore import pyqtSignal, QTimer,Qt,QEvent
from mainwindow import Ui_MainWindow

device_manager = gx.DeviceManager()
dev_num, dev_info_list = device_manager.update_device_list()
thstop = False
extime = None
exmodel = None

def capture_callback(data):  # 回调函数
    image_data = data.get_numpy_array()
    image_id = data.get_frame_id()
    image_width = image_data.shape[1]
    image_height = image_data.shape[0]

    # 打印图像信息
    print(f"Captured image ID: {image_id}")
    file_path = fr"D:\wulian_labor\captured_image_{image_id}.jpg"
    cv2.imwrite(file_path, image_data)
    print(f"Image saved to {file_path}")

class MyWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyWindow,self).__init__(parent)
        #显示图像
        self.label = QLabel(self)
        self.setupUi(self)
        self.label.setGeometry(50, 50, 200, 200)  # 设置标签的大小
        # self.cb = QComboBox(self)
        extime = self.exposure_lineEdit.text()

        #  切记槽函数得写这儿,不能用designer自己生成的那个,不然会报莫名其妙的错误
        self.opendevice.clicked.connect(self.opencamera) # type: ignore
        self.startcap.clicked.connect(self.startgather) # type: ignore
        self.stopcap.clicked.connect(self.stopgather) # type: ignore
        self.closedevice.clicked.connect(self.closecamera) # type: ignore
        self.model_comboBox.currentTextChanged.connect(self.exposuremodel)
        # self.model_comboBox.currentIndexChanged[str].connect(self.exposuremodel)
        self.comboBox_2.currentIndexChanged[str].connect(self.exposuremodel)
        self.exposure_lineEdit.textChanged.connect(self.exposuretime)
        # self.cb.currentIndexChanged[str].connect(self.exposuremodel)
        self.label.installEventFilter(self)

    def eventFilter(self, obj, event):
        if event.type() == QEvent.Resize and obj is self.label:
            self.updateImage(0)
        return super().eventFilter(obj, event)

    def updateImage(self, image_id):
        filename = f"D:\\wulian_labor\\captured_image_{image_id}.jpg"
        if os.path.exists(filename):
            pixmap = QPixmap(filename)
            if not pixmap.isNull():
                print("采集图像尺寸:", pixmap.size())
                # 调整图像大小为标签的大小
                pixmap = pixmap.scaled(self.label.size(), Qt.KeepAspectRatio)
                self.label.setPixmap(pixmap)
                print("调整后图像尺寸:", pixmap.size())
                lb = QLabel(self)
                lb.setPixmap(pixmap)

    def opencamera(self):
        if dev_num == 0:
            # print("没有可用设备")
            QMessageBox.about(self, "提示", "没有可用设备")
        else:
            sn = dev_info_list[0].get("sn")
            self.cam = device_manager.open_device_by_sn(sn)  # 将相机实例化为对象属性 MER-131-210U3M
            QMessageBox.about(self,"提示","相机打开成功")

    # def getSelectedValue(self):
    #     return self.cb.currentIndexChanged
    def exposuremodel(self,model):
        if model == "OFF":
            self.cam.TriggerMode.set(gx.GxSwitchEntry.OFF)
        elif model == "ON":
            self.cam.TriggerMode.set(gx.GxSwitchEntry.ON)

    def triggersource(self,index):
        try:
            if index == "software":
                self.cam.TriggerSource.set(gx.GxTriggerSourceEntry.SOFTWARE)
            elif index == "line0":
                self.cam.TriggerSource.set(gx.GxTriggerSourceEntry.LINE0)
            elif index == "line1":
                self.cam.TriggerSource.set(gx.GxTriggerSourceEntry.LINE1)
            elif index == "line2":
                self.cam.TriggerSource.set(gx.GxTriggerSourceEntry.LINE2)
            elif index == "line3":
                self.cam.TriggerSource.set(gx.GxTriggerSourceEntry.LINE3)
            else:
                QMessageBox.about(self,"提示","未知的触发源")
        except Exception as e:
            print("触发源异常", e)

    # def exposuretime(self):
    #     if extime is None:
    #         self.cam.ExposureAuto.set(gx.GxAutoEntry.CONTINUOUS)
    #     else:
    #         self.cam.ExposureTime.set(extime)
    def exposuretime(self):

        extime = self.exposure_lineEdit.text()
        if extime:
            try:
                extime_float = float(extime)
                self.cam.ExposureTime.set(extime_float)
            except ValueError:
                print("曝光时间必须是一个数字")
            else:
                print("请输入曝光时间")

    def startgather(self, img):
        if dev_num == 0:
            QMessageBox.about(self,"提示","无法开始采集,因为没有检测到设备")
        else:
            self.cam.data_stream[0].register_capture_callback(capture_callback)
            self.cam.stream_on()
            # 参数0代表系统第一个摄像头,第二就用1 以此类推
            cap = cv2.VideoCapture(0)
            # 设置显示分辨率和FPS ,不设置的话会非常卡
            cap.set(cv2.CAP_PROP_FRAME_WIDTH, 800)
            cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 600)
            cap.set(cv2.CAP_PROP_FPS, 20)
            while cap.isOpened():
                if thstop:
                    return
                ret, frame = cap.read()
                if ret == False:
                    continue
                # 水平翻转,很有必要
                frame = cv2.flip(frame, 1)
                # opencv 默认图像格式是rgb qimage要使用BRG,这里进行格式转换,不用这个的话,图像就变色了,困扰了半天,翻了一堆资料
                frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
                # mat-->qimage
                a = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
                self.SetPic(a)  # 这里调用自定义的SetPic方法
    def stopgather(self):
        self.cam.stream_off()

    def closecamera(self):
        self.cam.close_device()

# 显示图像
    def update_image(self):
        global index
        if index < len(image_files):
            # 从文件名中提取image_id
            image_id = int(image_files[index].split("_")[2].split(".")[0])
            self.updateImage(image_id)
            index += 1
        else:
            # 文件遍历完成后重新开始
            index = 0
        # 每隔一段时间刷新一次
        QTimer.singleShot(1000, self.update_image)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()

    image_files = [file for file in os.listdir("D:\\wulian_labor") if file.startswith("captured_image_")]

    global index
    index = 0

    # 初始调用一次update_image
    w.update_image()
    sys.exit(app.exec())

我这个代码里,偶尔label不显示图像,不知道为什么,有大佬可以指出来一下。

但是我着重是为了保存那个图片方便后续的重构,所有显示不是黑重要,我就没去深究了。

最好就是第二个,Linux下检测不到相机,你先去看一下自己的相机是什么口,usb还是网口,网口的巨坑,我找了很久的资料和方法都没解决;usb的你需要在虚拟机-设置-usb控制器里把兼容性调到3.1,如下图。

小tips:如果和我差不多的新手,建议在windows里下载个qt designer,只编辑界面文件(.ui文件),pyuic转.py文件。槽函数留在setUI下面去编辑,像我的代码里那样,然后下载个xftp把文件发给虚拟机;如果要显示视频的话,建议使用多线程。

注:投影仪的代码是c++的,还在想办法转换

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐