可视可交互!在全志H618上用OpenCV读取图像显示到PyQt5窗口上

2024-01-11 10:44

本文主要是介绍可视可交互!在全志H618上用OpenCV读取图像显示到PyQt5窗口上,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

OpenCV能够处理图像、视频、深度图像等各种类型的视觉数据,在某些情况下,尽管OpenCV可以显示窗口,但PyQt5可能更适合用于创建复杂的交互式应用程序,而自带GPU的H618就成为了这些图像显示的最佳载体。

这里分享一个代码,功能是使用图像处理库opencv从摄像头获取数据,缩放后从pyqt5的窗口中显示出来。

746beff04ec85b26fe404e0475d7bfb4237f765b_2_650x500.png

安装opencv

sudo pip3 install opencv-python

创建一个pyqt5窗口

1. 用Qt Designer画个窗口
这里我在电脑上使用designer软件,创建一个Main Window类型窗体。从左边组件栏中拖出一个label放到窗口中间。

点一下放在窗口中的label,在软件右下角的属性编辑器里可以设置很多东西,这里就不细介绍了。这里我是设置了QFrame启用了边框,QLabel中的texte属性控制显示的文本,QLabel中的alignment属性控制文本对齐方式。

然后保存为.ui结尾的文件

61ad9a89c29d3693824917f8ea700666c2c72e4c_2_501x375.png

2. 将designer绘制的ui文件转化为py文件

python3 -m PyQt5.uic.pyuic ui_main.ui -o ui_main.py

3. 编写main.py程序,调用刚刚画的窗口进行显示
先把刚刚的ui_main.py以及一些qt库给import进来

from  ui_main import Ui_MainWindowimport PyQt5
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *# 修正qt的plugin路径,因为某些程序(cv2)会将其改到其他路径
import os
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.dirname(PyQt5.__file__)

放入一点辅助代码,一个是为了实现从远程命令行运行qt程序显示到桌面上,一个是为了在命令行下可以按ctrl+c快捷键来强制退出qt程序

#【可选代码】允许远程运行
import os
os.environ["DISPLAY"] = ":0.0"#【建议代码】允许终端通过ctrl+c中断窗口,方便调试
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
timer = QtCore.QTimer()
timer.start(100)  # You may change this if you wish.
timer.timeout.connect(lambda: None)  # Let the interpreter run each 100 ms

定义窗口类,重写窗口的一些触发事件。这里我修改了鼠标点击后会被自动调用的mousePressEvent和窗口绘制时会被调用的paintEvent

class WINDOW(QtWidgets.QMainWindow):def mousePressEvent(self, event):# 被左键点击后退出本程序if event.button() == Qt.LeftButton:self.close()exit(-1)def paintEvent(self,event):# 修改label的大小和位置new_width = int(window.width()/10*8)new_height = int(window.height()/10*8)lab_x = int((window.width() - new_width) / 2)lab_y = int((window.height() - new_height) / 2)ui.label.setGeometry( lab_x, lab_y, new_width, new_height)

加上调用函数进行显示的部分,这个显示pyqt5窗口的基本程序就完成了

# 初始化窗口
import sys
app = QtWidgets.QApplication(sys.argv)
window = WINDOW()
ui = Ui_MainWindow()
ui.setupUi(window)
window.showFullScreen() #全屏显示
# window.show() #按绘制时的尺寸显示
sys.exit(app.exec_())

在核桃派lcd屏上的效果展示

ffe8ec8611e71a48fa612edcc571691d329523a2_2_690x422.png

opencv怎么读取摄像头

调用头文件,opencv的头文件只需要这一个

import cv2

打开摄像头,其中传入的参数1是摄像头编号,一般是从0开始往后排

cap = cv2.VideoCapture(1)

从摄像头读取一帧图像,ret是读取状态,frame是图像数据

ret, frame = cap.read()

怎么把opencv的图像数据显示到qt的label

cap.read函数读到的是bgr格式的,需要先转为rgb格式

rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

将图像转为Qt中用来表示图像的QImage

h, w, ch = rgbImage.shape
qtImage = QImage(rgbImage.data, h, w, ch*w, QtGui.QImage.Format_RGB888)

label的setPixmap方法可以图像数据覆盖label

label.setPixmap(QPixmap.fromImage(qtImage))

线程,信号与槽

我们这里使用qt自带的多线程功能,他的使用很简单,只需要创建一个类并继承自QThread, 然后将要运行的东西写到类里的run方法下面。实例化一个对象后,调用start方法即可创建新线程

class Work(QThread):def run(self):pass
work = Work()
work.start()

直接在线程内调用函数去修改qt窗口的内容,不能满足线程安全。

我们需要创建一个信号,把修改qt窗口的语句写到一个槽内,连接他们,在想修改窗口时发出信号,让qt内部去调度,防止跟其他qt内部的线程发生冲突。

因为我们这个线程类继承自QThread,所以可以在类内定义信号。只需要实例化一个pyqtSignal对象即可,调用时括号内的参数决定了槽函数必须有什么类型的参数,以及发送信号时需要传入什么参数。

```

signal_update_label = pyqtSignal( QPixmap)


槽函数就是随便定义一个函数,只要函数参数跟信号一样就行。```
label:QLabeldef sloat_update_label( self, pixmap:QPixmap):self.label.setPixmap(pixmap)

连接信号与槽,使用connect方法即可

self.signal_update_label.connect(self.sloat_update_label)

使用emit方法即可发送信号,qt内部会进行调度,将所有连接到本信号的函数都调出来运行,并将参数传给他们。这是qt实现线程安全的重要机制。

self.signal_update_label.emit(QPixmap.fromImage(qtImage))

最终代码

import cv2
from  ui_main import Ui_MainWindowimport PyQt5
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *# 修正qt的plugin路径,因为某些程序(cv2)会将其改到其他路径
import os
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.dirname(PyQt5.__file__)#【可选代码】允许Thonny远程运行
import os
os.environ["DISPLAY"] = ":0.0"#【建议代码】允许终端通过ctrl+c中断窗口,方便调试
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
timer = QTimer()
timer.start(100)  # You may change this if you wish.
timer.timeout.connect(lambda: None)  # Let the interpreter run each 100 ms# 线程类
class Work(QThread):signal_update_label = pyqtSignal(QPixmap)label:QLabeldef sloat_update_label( self, pixmap:QPixmap):self.label.setPixmap(pixmap)def run(self):print("label.width()=", self.label.width())print("label.height()=", self.label.height())self.signal_update_label.connect(self.sloat_update_label)cap = cv2.VideoCapture(1)while True:ret, frame = cap.read()if ret:# 颜色转换rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 按比例缩放h, w, ch = rgbImage.shapeaspect_ratio = w / hnew_width = self.label.width()new_height = int(new_width / aspect_ratio)if new_height > self.label.height():new_height = self.label.height()new_width = int(new_height * aspect_ratio)rgbImage = cv2.resize(rgbImage, (new_width, new_height))# 显示到labelbytesPerLine = ch * new_widthself.signal_update_label.emit(QPixmap.fromImage(QImage(rgbImage.data, new_width, new_height, bytesPerLine, QImage.Format_RGB888)))else :print("cap read error")returnclass WINDOW(QMainWindow):def mousePressEvent(self, event):if event.button() == Qt.LeftButton:self.close()def paintEvent(self,event):new_width = int(window.width()/10*8)new_height = int(window.height()/10*8)lab_x = int((window.width() - new_width) / 2)lab_y = int((window.height() - new_height) / 2)ui.label.setGeometry( lab_x, lab_y, new_width, new_height)import sys
app = QApplication(sys.argv)
window = WINDOW()
ui = Ui_MainWindow()
ui.setupUi(window)
window.showFullScreen() #全屏显示
# window.show() #按绘制时的尺寸显示# 创建读取摄像头并显示的线程
work = Work()
work.label = ui.label
work.start()sys.exit(app.exec_())

c547df99a7f823abfb33c4551ec009af853f6ea2_2_479x500.png

这篇关于可视可交互!在全志H618上用OpenCV读取图像显示到PyQt5窗口上的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/594118

相关文章

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但是本人给出一些暂时的解决办法: 问题1: 我在安装库命令行使用的是 .\vcpkg.exe install opencv 我的电脑是x64,vcpkg在这条命令后默认下载的也是opencv2:x6

据阿谱尔APO Research调研显示,2023年全球髓内钉市场销售额约为4.7亿美元

根据阿谱尔 (APO Research)的统计及预测,2023年全球髓内钉市场销售额约为4.7亿美元,预计在2024-2030年预测期内将以超过3.82%的CAGR(年复合增长率)增长。 髓内钉市场是指涉及髓内钉制造、分销和销售的行业。髓内钉是一种用于整形外科手术的医疗器械,用于稳定长骨骨折,特别是股骨、胫骨和肱骨。髓内钉通常由不銹钢或钛等材料制成,并插入骨的髓管中,以在愈合过程中提供结构支

移动硬盘盒:便携与交互的完美结合 PD 充电IC

在数字化时代的浪潮中,数据已成为我们生活中不可或缺的一部分。随着数据的不断增长,人们对于数据存储的需求也在不断增加。传统的存储设备如U盘、光盘等,虽然具有一定的便携性,但在容量和稳定性方面往往难以满足现代人的需求。而移动硬盘,以其大容量、高稳定性和可移动性,成为了数据存储的优选方案。然而,单纯的移动硬盘在携带和使用上仍存在诸多不便,于是,移动硬盘盒应运而生,以其独特的便携性和交互性,成为了数据存储

vue+elementUI下拉框联动显示

<el-row><el-col :span="12"><el-form-item label="主账号:" prop="partyAccountId" :rules="[ { required: true, message: '主账号不能为空'}]"><el-select v-model="detailForm.partyAccountId" filterable placeholder="

brew install opencv@2 时报错 Error: Can't create update lock in /usr/local/var/homebrew/locks!

解决方案,报错里已经说明了: 我的解决方案: sudo chown -R "$USER":admin /usr/local   stackoverflow上的答案 I was able to solve the problem by using chown on the folder: sudo chown -R "$USER":admin /usr/local Also you'

【Java算法】滑动窗口 下

​ ​    🔥个人主页: 中草药 🔥专栏:【算法工作坊】算法实战揭秘 🦌一.水果成篮 题目链接:904.水果成篮 ​ 算法原理 算法原理是使用“滑动窗口”(Sliding Window)策略,结合哈希表(Map)来高效地统计窗口内不同水果的种类数量。以下是详细分析: 初始化:创建一个空的哈希表 map 用来存储每种水果的数量,初始化左右指针 left

温湿度采集及OLED显示

目录 软件I2C和硬件I2C每隔2秒钟采集一次温湿度数据,显示到OLED上,同时通过串口发送到上位机的“串口助手”软件 软件I2C和硬件I2C "I2C"代表Inter-Integrated Circuit,是一种用于在数字电路之间进行通信的串行通信协议。软件I2C和硬件I2C是两种实现这种协议的方式。 软件I2C是通过软件来模拟I2C通信协议的实现方式。在这种情况下,微控制

《学习OpenCV》课后习题解答7

题目:(P105) 创建一个结构,结构中包含一个整数,一个CvPoint和一个 CvRect;称结构体为“my_struct”。 a. 写两个函数:void Write_my_strct(CvFileStorage* fs, const char * name, my_struct* ms) 和 void read_my_struct(CvFileStorage* fs, CvFileNode

OpenCV中的按钮问题

在HighGUI中,没有显示提供任何形式的按钮。一般有两种方法替代: 1.用只有两个状态的滑动条来替代按钮。开关(switch)事实上就是只有两个状态的滑动条,这两个状态是on和off。然后通过回调函数来实现相关的功能。 实例源码(使用滑动条实现一个开关功能) #include<cv.h>#include<highgui.h>int g_switch_value = 0;void swit