OpenCV-Python入门教程7-PyQt编写GUI界面

前面一直都是使用命令行运行代码,不够人性化。这篇用Python编写一个GUI界面,使用PyQt5编写图像处理程序。包括:打开、关闭摄像头,捕获图片,读取本地图片,灰度化和Otsu自动阈值分割的功能。

使用Qt Designer来设计界面。而anaconda里自带了designer.exe,我使用的就是这个。designer.exe的路径:D:\ProgramData\Anaconda3\Library\bin\,如果是普通的Python环境,则需要自行安装

pip install pyqt5-tools

安装完成后,designer.exe应该在Python的安装目录下:xxx\Lib\site-packages\pyqt5_tools\

生成一个简单的界面,后面还会用到

import sys
from PyQt5.QtWidgets import QApplication, QWidgetif __name__ == '__main__':app = QApplication(sys.argv)window = QWidget()window.setWindowTitle('Hello World!')window.show()sys.exit(app.exec_())

一、界面设计

在D:\ProgramData\Anaconda3\Library\bin\下打开designer.exe,会弹出创建新窗体的窗口,我们直接点击"创建"(英文版是create)

界面左侧是Qt的常用控件"Widget Box",右侧有一个控件属性窗口"Property Editor"。本例中我们只用到了"Push Button"控件和"Label"控件,可以在属性窗口调整它的大小150x150(可以根据自己的需求适当调大或者缩小):

控件上显示的文字"text"属性和控件的名字"objectName"属性需要修改,便于显示和代码调用,可以按照下面的表格命名:

控件显示内容text控件名objectName
PushButton打开摄像头btnOpenCamera
PushButton捕获图片btnCapture
PushButton打开图片btnReadImage
PushButton灰度化btnGray
PushButton阈值分割btnThreshold
Label摄像头labelCamera
Label捕获图labelCapture
Label结果图labelResult

前面设计好了界面,接下来就是实现"打开摄像头"到"阈值分割"这五个按钮的功能,也就是给每个按钮指定一个函数,逻辑代码写在这个函数里面。这个函数就称事件,Qt中称为槽连接

点击Designer工具栏的Edit Signals/Slots按钮,进入槽函数编辑界面,点击旁边的"Edit Widgets"可以恢复正常视图:

在弹出的配置窗口中,可以看到左侧是按钮的常用事件,我们选择点击事件”clicked()”,然后添加一个名为”btnOpenCamera_Clicked()”的槽函数:

重复上面的步骤,给五个按钮添加五个槽函数,最终结果如下:

Ctrl + S保存.ui文件。我们需要将ui转py代码。

打开cmd命令行,切换到ui文件的保存目录。Windows下有个小技巧,可以在目录的地址栏输入cmd,一步切换到当前目录:

执行这条指令

pyuic5 -o mainForm.py using_pyqt_create_ui.ui

生成mainForm.py文件,里面包含一个名为”Ui_MainWindow”的类。

二、编写逻辑代码

mainForm.py是根据ui文件生成的,也就是说,一旦ui文件有所改变,需要重新生成覆盖原来的文件。

新建一个mainEntry.py存放逻辑代码,代码虽然很长,但是很简单并不难懂。有些部分有所重复,并没有将其封装成一个函数(博主能力有限),感兴趣的可以试一下

import sys
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QFileDialog, QMainWindow
from mainForm import Ui_MainWindowclass PyQtMainEntry(QMainWindow, Ui_MainWindow):def __init__(self):super().__init__()self.setupUi(self)self.camera = cv2.VideoCapture(0)self.is_camera_opened = False  # 摄像头有没有打开标记# 定时器:30ms捕获一帧self._timer = QtCore.QTimer(self)self._timer.timeout.connect(self._queryFrame)self._timer.setInterval(30)def btnOpenCamera_Clicked(self):'''打开和关闭摄像头'''self.is_camera_opened = ~self.is_camera_openedif self.is_camera_opened:self.btnOpenCamera.setText("关闭摄像头")self._timer.start()else:self.btnOpenCamera.setText("打开摄像头")self._timer.stop()def btnCapture_Clicked(self):'''捕获图片'''# 摄像头未打开,不执行任何操作if not self.is_camera_opened:returnself.captured = self.frame# 后面这几行代码几乎都一样,可以尝试封装成一个函数rows, cols, channels = self.captured.shapebytesPerLine = channels * cols# Qt显示图片时,需要先转换成QImgage类型QImg = QImage(self.captured.data, cols, rows, bytesPerLine, QImage.Format_RGB888)self.labelCapture.setPixmap(QPixmap.fromImage(QImg).scaled(self.labelCapture.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))def btnReadImage_Clicked(self):'''从本地读取图片 文件路径不能有中文'''# 打开文件选取对话框filename, _ = QFileDialog.getOpenFileName(self, '打开图片')if filename:self.captured = cv2.imread(str(filename))# OpenCV图像以BGR通道存储,显示时需要从BGR转到RGBself.captured = cv2.cvtColor(self.captured, cv2.COLOR_BGR2RGB)rows, cols, channels = self.captured.shapebytesPerLine = channels * colsQImg = QImage(self.captured.data, cols, rows, bytesPerLine, QImage.Format_RGB888)self.labelCapture.setPixmap(QPixmap.fromImage(QImg).scaled(self.labelCapture.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))def btnGray_Clicked(self):'''灰度化'''# 如果没有捕获图片,则不执行操作if not hasattr(self, "captured"):returnself.cpatured = cv2.cvtColor(self.captured, cv2.COLOR_RGB2GRAY)rows, columns = self.cpatured.shapebytesPerLine = columns# 灰度图是单通道,所以需要用Format_Indexed8QImg = QImage(self.cpatured.data, columns, rows, bytesPerLine, QImage.Format_Indexed8)self.labelResult.setPixmap(QPixmap.fromImage(QImg).scaled(self.labelResult.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))def btnThreshold_Clicked(self):'''Otsu自动阈值分割'''if not hasattr(self, "captured"):return_, self.cpatured = cv2.threshold(self.cpatured, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)rows, columns = self.cpatured.shapebytesPerLine = columns# 阈值分割图也是单通道,也需要用Format_Indexed8QImg = QImage(self.cpatured.data, columns, rows, bytesPerLine, QImage.Format_Indexed8)self.labelResult.setPixmap(QPixmap.fromImage(QImg).scaled(self.labelResult.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))@QtCore.pyqtSlot()def _queryFrame(self):'''循环捕获图片'''ret, self.frame = self.camera.read()img_rows, img_cols, channels = self.frame.shapebytesPerLine = channels * img_colscv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB, self.frame)QImg = QImage(self.frame.data, img_cols, img_rows, bytesPerLine, QImage.Format_RGB888)self.labelCamera.setPixmap(QPixmap.fromImage(QImg).scaled(self.labelCamera.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))if __name__ == "__main__":app = QtWidgets.QApplication(sys.argv)window = PyQtMainEntry()window.show()sys.exit(app.exec_())

 参考网址:https://tianchi.aliyun.com/course/courseConsole?courseId=40992&chapterIndex=1&sectionIndex=16

转载于:https://www.cnblogs.com/gezhuangzhuang/p/10289980.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/537059.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spark 广播变量大数据_大数据处理 | Spark集群搭建及基本使用

点击蓝字关注我前面用了一篇文章详细的介绍了集群HDFS文件系统的搭建,HDFS文件系统只是一个用于存储数据的系统,它主要是用来服务于大数据计算框架,例如MapReduce、Spark,本文就接着上一篇文章来详细介绍一下Spark集群的搭建及Spa…

如何将本地项目上传到gitee

*************************************优雅的分割线 ********************************** 分享一波:程序员赚外快-必看的巅峰干货 如果以上内容对你觉得有用,并想获取更多的赚钱方式和免费的技术教程 请关注微信公众号:HB荷包 一个能让你学习技术和赚钱方法的公众号,持续更…

oracle dg 备库未设置convert参数导致ORA-01111,ORA-01110

2019独角兽企业重金招聘Python工程师标准>>> 查看trace 文件: MRP0: Background Managed Standby Recovery process started (amls) started logmerger process Sun Jan 20 07:55:53 2019 Managed Standby Recovery starting Real Time Apply MRP0: Back…

git回退历史版本无法上传_Git系列教程(二):版本库中添加文件、版本回退

Git系列教程(一):简介、安装、配置我们学习了分布式和版本控制系统的概念、Git具有的8个功能以及如何在Windows上安装Git、进行相关配置并创建版本库。Git版本库中添加文件Git 的工作就是创建和保存你的项目的快照及与之后的快照进行对比。我们编写一个readme.txt文…

nginx反向代理配置如何去除前缀

使用nginx做反向代理的时候,可以简单的直接把请求原封不动的转发给下一个服务。设置proxy_pass请求只会替换域名,如果要根据不同的url后缀来访问不同的服务,则需要通过如下方法: 方法一:加"/"** server {l…

「作文素材详解」写作必知篇:语言优美不是作文第一要求

语言优美不是作文第一要求“教孩子写作文,老师家长应该先提升自己。”“语言优美不是作文的第一要求。”“如果教孩子写漂亮的违心话,会害了他一辈子。”日前,著名作家肖复兴来到体育东路小学,与广州的一线语文教师交流&#xff0…

华为安装gsm框架_华为nova5怎么下载安装谷歌服务助手,安装GMS框架教程

看到不少的华为nova5用户喜欢这个谷歌服务助手,也就是想安装这个GMS框架,可是一直不知道如何下载安装,这个谷歌服务框架是可以在系统软件里面可以删除的一个APK程序,但现在有很多的软件和游戏需要谷歌服务的支持,那咱们…

VMware安装虚拟机并使用NAT模式连接网络

*************************************优雅的分割线 ********************************** 分享一波:程序员赚外快-必看的巅峰干货 如果以上内容对你觉得有用,并想获取更多的赚钱方式和免费的技术教程 请关注微信公众号:HB荷包 一个能让你学习技术和赚钱方法的公众号,持续更…

PHPStudy下Apache SSL证书安装教程

一、安装SSL证书的环境 Apache安装目录:E:phpStudyPHPTutorialApache 以上为windows下测试SSL证书安装的目录,具体目录请根据自己的实际环境! 二、获取SSL证书 成功在沃通申请SSL证书后,会得到一个压缩包文件,解压后得到四个文件&…

laravel 集成采集_新版2020 Laravel采集网站程序

环境:php5.6数据库:mysql5.5集成环境软件:护卫神apache这套程序是520.ag 的网站很早的程序了是去年还是前年 应该是前年免费采集网站 但是经常挂 其实他网站挂和服务器没有多大关系 是程序没有作好优化这套程序可以大家做起来 自己用就可以了 放出去免费采集的话 网站容易死程…

详解模板方法设计模式

分享一波:程序员赚外快-必看的巅峰干货 概念 定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的重复代码全部在父类里面,不同业务的,使用抽象方法,抽取给子类进…

怎么从已有文件中挑选需要的文字重新生成新文件_CAD问题全面解答(几乎涵盖了CAD使用的全部问题)...

1.【CTrlN无效时之解决办法】众所周知CTRLN是新建命令但有时候CTRLN则出现选择面板这时只需到OP选项里调下设置操作:OP(选项)------系统-------右侧有一个启动(A显示启动对话框B不显示启动对话框)选择A则新建命令有效,反则无效2.【Ctrl键无效之解决办法】…

中国官方要求进一步加强中资商业银行境外机构合规管理

中新社北京1月22日电 (记者 王恩博)为推动在境外设有经营性机构的中资商业银行进一步优化集团合规管理体系,健全跨境合规管理机制,提高跨境合规管理有效性,实现境外机构安全稳健运行,中国银保监会22日发布《关于加强中资商业银行境…

详解:设计模式之-代理设计

分享一波:程序员赚外快-必看的巅峰干货 概念 通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用处理,或调用后处理(类似于AOP)。 代理设计模式应用场景:AOP、权限控制、事务 常见代理的分类有&am…

【实时+排重】摆脱渠道统计刷量作弊行为

如今的渠道统计不仅要看精准度,更要看数据的真实性。 对App的推广业务而言,渠道监测和统计是必不可少的环节,不论以什么形式开展推广,终究都要具体落实到App的安装量、激活量等指标上。但在如今数据刷量和作假行为横行的背景下&am…

python清空idle的内容_Python IDLE清空窗口的实例

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里技术人对外发布原创技术内容的最大平台&…

详解:设计模式之-单例设计模式

分享一波:程序员赚外快-必看的巅峰干货 前言 近期预计1-2周左右会更新设计模式专题文章。 单例设计模式:保证在一个JVM中,只能存在一个实例。 应用场景:Servlet,Spring IOC,线程池,连接池,S…

rabbitmq可靠性投递_阿里Java研发二面:了解RabbitMQ?说说RabbitMQ可靠性投递

上期写到高并发下RabbitMq消息中间件你应该介么玩今天给小伙伴说说!有自己看法的也可以在评论区留言探讨,也可以转发关注下我以后会长期分享!目录:确保消息发送到RabbitMQ服务器确保消息被正确的路由确保消息在队列正确地存储确保…

IBM发布Open Liberty 18.0.0.4,支持MicroProfile 2.1和反应性扩展框架

IBM在2018年第四季度发布的Open Liberty 18.0.0.4提供了对MicroProfile 2.1、反应性扩展框架和连接池指标的全面支持。根据发布说明:Open Liberty现在对JAX-RS 2.1进行了反应性扩展,这样你就可以使用来自Apache CXF和Jersey的提供程序。在ops方面&#x…

b700a怎么连蓝牙_233621蓝牙2.1无线音箱B700A小测

随着蓝牙技术的发展,使用蓝牙的相关产品也越来越多,各种蓝牙耳机、蓝牙键盘、蓝牙鼠标都让我们的外设摆脱了线材的束缚。小编之前也介绍过一款便携蓝牙音箱,也评测过一款蓝牙耳机,而今天拿到的是一款采用蓝牙2.1技术,造…