PyQT5+OpenCV多线程协作演示

引言
    学习多线程最典型的问题就是如何在多个线程之间传递消息与写作,pyqt5的线程支持在不同线程之间传递信号触发事件,实现多个线程之间的协助,完成诸如生产者-消费者这样经典的多线程协作。本文将通过qthread与信号槽机制构建一个生产者-消费者模型,演示多个线程之间的协作。
应用程序概述
这里演示了一个从图像采集(用本地图像数据集替代)到图像分析处理(简单二值化+形态学处理)、到主界面更新的应用程序。主界面是ui线程、图像采集跟图像分析分别在两个不同的工作线程中,通过信号与槽机制协作工作,相互配合实现图像采集到分析到结果更新到界面线程。
多线程协作信号触发示意图
代码实现
这样实现了三个类
imagefetchthread // 图像采集imageanalysisthread // 图像分析contentpanel // 界面显示与更新  
这三个类的代码分别,模拟图像采集线程
1class imagefetchthread(qtcore.qthread): 2    fire_stats_signal = qtcore.pyqtsignal(dict) 3 4    def __init__(self, images_dir): 5        super(imagefetchthread, self).__init__() 6        self.images_dir = images_dir 7        self.read_next = true 8 9    def request_image(self):10        self.read_next = true1112    def run(self):13        if len(self.images_dir) == 0:14            return15        files = os.listdir(self.images_dir)16        idx = 017        while true:18            if idx == len(files):19                break20            if self.read_next is true:21                print(grab one image...)22                image = cv.imread(os.path.join(self.images_dir, files[idx]))23                gray = cv.cvtcolor(image, cv.color_bgr2gray)24                idx += 125                self.read_next = false26                self.fire_stats_signal.emit({im_data: gray})27        self.fire_stats_signal.emit({done: done})28        return  
处理图像线程
1class imageanalysisthread(qtcore.qthread): 2    request_image_signal = qtcore.pyqtsignal() 3    update_result_signal = qtcore.pyqtsignal(dict) 4 5    def __init__(self): 6        super(imageanalysisthread, self).__init__() 7        self.image_data = none 8        self.stop = false 910    def process_im(self, results):11        self.image_data = results.get(im_data)12        if results.get(done) is not none:13            self.stop = true1415    def run(self):16        while true:17            if self.stop is true:18                break19            if self.image_data is none:20                continue21            print(started to process one image...)22            # ret, binary = cv.threshold(self.image_data, 0, 255, cv.thresh_binary | cv.thresh_otsu)23            binary = cv.adaptivethreshold(self.image_data, 255, cv.adaptive_thresh_gaussian_c,24                                          cv.thresh_binary_inv, 25, 10)25            se = cv.getstructuringelement(cv.morph_rect, (7, 7))26            resutl = cv.morphologyex(binary, cv.morph_dilate, se)27            self.request_image_signal.emit()28            self.update_result_signal.emit({im_data: resutl})29            self.image_data = none30        self.update_result_signal.emit({done: done})31        return  
界面线程
1class contentpanel(qtwidgets.qwidget): 2    def __init__(self, parent=none): 3        super().__init__(parent) 4        filebtn = qtwidgets.qpushbutton(目录...) 5        self.image_files_dir= qtwidgets.qlineedit() 6        self.image_files_dir.setminimumwidth(100) 7        self.image_files_dir.setenabled(false) 8        self.processbtn = qtwidgets.qpushbutton(开始处理) 9        hbox_layout = qtwidgets.qhboxlayout()10        hbox_layout.addwidget(filebtn)11        hbox_layout.addwidget(self.image_files_dir)12        hbox_layout.addwidget(self.processbtn)13        panel1 = qtwidgets.qgroupbox(目录选择)14        panel1.setlayout(hbox_layout)1516        # 图像标签17        self.imglabel = qtwidgets.qlabel()18        self.imglabel.setminimumsize(800, 600)19        self.imglabel.setstylesheet(background-color:black; color: deeppink)20        self.imglabel.setalignment(qtcore.qt.aligncenter)2122        # 添加到布局管理器中23        vbox_layout = qtwidgets.qvboxlayout()24        vbox_layout.addwidget(panel1)25        vbox_layout.addwidget(self.imglabel)26        vbox_layout.addstretch(1)2728        # 面板容器29        self.setlayout(vbox_layout)3031        # setup listener32        filebtn.clicked.connect(self.on_select_image_dir)33        self.processbtn.clicked.connect(self.on_process)3435        self.fetch_thread = none36        self.analysis_thread = none3738    def on_select_image_dir(self):39        img_dir = qtwidgets.qfiledialog.getexistingdirectory(self, 图像文件夹, .)40        self.image_files_dir.settext(img_dir)  
演示部分


PLC能取代运动控制器吗?
关于半导体FAB厂的技术100个问题汇总
惠普打造的移动网络经常出现故障遭到了俄罗斯移动运营商的起诉
UHF频段无线收发信机前端设计
国产AIoT SoC芯片龙头初现 MCU变革已来
PyQT5+OpenCV多线程协作演示
魅族科技宣布将于4月23日在珠海举办新品发布会
触摸式报警器
单双张检测超声波传感器的功能特点
采用全数字中频技术的DSA1030A频谱分析仪的设计
天宫二号是干什么的 五个问题让您快速了解
安谋科技吴雄昂:核芯动力XPU,定义全新的融合计算架构
三星Galaxy Note10发布会正式召开, 8GB+256GB版本售价6599元
3月15日直播预告|Vector-CSM测量技术产品方案介绍
如何在全生命周期中满足不断提高流量需求
LED嵌入式绷带可通过蓝光来治愈慢性创面
在选择板对板连接器时可从这几个方面入手
五招帮你排除解决投影机偏色故障
芯片制程技术从3nm走向了2nm
pcb电路板制有什么方法和技巧