pyqt制作简单的摄像头监控界面
文章目录
- 前言
- 正文
- 1.界面设计
- 2.界面开发进阶
- 3.在线程中不能直接更新界面
- 4.pyqt播放音频
- 5.dialog弹窗
- 小结
前言
由于原生的python不能做出漂亮的界面,发现很多人都选择使用qt.
参考资料:
pyqt 教程 http://code.py40.com/pyqt5/16.html
pyqt进阶教程 https://blog.csdn.net/la_vie_est_belle/category_9279128.html
网络案例 https://blog.csdn.net/DerrickRose25/article/details/86744787
发现一个好用的查询 api的工具 代码中编辑help(xxx)
正文
1.界面设计
通过网络案例,我们得到一个初始框架.同时知道了opencv读出的帧如何绘制在pyqt控件上.
# 核心代码-绘制def show_camera(self):flag, self.image = self.cap.read()show = cv2.resize(self.image, (640, 480))show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)self.label_show_camera.setPixmap(QtGui.QPixmap.fromImage(showImage))# 核心代码-更新 (利用定时器重复绘制)self.timer_camera = QtCore.QTimer() # 初始化定时器self.timer_camera.timeout.connect(self.show_camera)
由于界面不是重点,相关功能简单实现,没有单页跳转,没有动画.
第一个界面,左边是4个小的视频通道预览,右边是检测出的人脸列表,列表可以上下滚动
点击其中一个视频通道,进入第二个界面,左边是1个大的视频预览,右边是检测出的人脸列表,列表可以上下滚动
问题1:让界面适配屏幕
#获取屏幕宽高,screenGeometry(0)就是主屏幕,1的话是分屏1,以此类推
self._screen_width = int(QApplication.desktop().screenGeometry(0).width())
self._screen_height = int(QApplication.desktop().screenGeometry(0).height())#设置window
# move()方法是移动窗口在屏幕上的位置
self.resize(box_s[0], box_s[1])
self.move(self._screen_offset, self._screen_offset)#设置layout
#设置widget
label_show_camera = QtWidgets.QLabel()
label_show_camera.setFixedSize(page1_preview_s[0], page1_preview_s[1])
label_show_camera.setAutoFillBackground(False)
2.界面开发进阶
pycharm + Qt Designer
参考:https://blog.csdn.net/crazy696/article/details/88721688
问题1:如何调整gridLayout
https://blog.csdn.net/yxy244/article/details/96278255
先打破,然后摆放,然后再组合
问题2: listview如何添加item
1)简单文本列表
item_list = ['item %s' % i for i in range(660)]model = QtCore.QStringListModel(self)model.setStringList(item_list)self.listView.setModel(model)
2)复杂布局列表
实现方法大概有这么三种:
1)如果使用QListWidget的话,我们直接调用 setItemWidget 即可。
void setItemWidget(QListWidgetItem *item, QWidget *widget)2)QListWidget和QListView都可以通过调用 setIndexWidget 实现。但是该方法只适合做静态数据的显示,不适合做一些插入、更新、删除操作的数据显示。
void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget)3)我们针对QListView实现自己的ItemDelegate。重写ItemDelegate的paint函数。
首先了解下view/model 参考:https://www.cnblogs.com/hangxin1940/archive/2012/04/23/2806444.html
知道什么是Delegate后,参考这位大哥的c++写法
https://blog.csdn.net/a844651990/article/details/84324560
改了一个python版本
# 重新定义数据结构
class ListData(object):def __init__(self, name, image):self.name = nameself.image= imageclass MyDelegate(QStyledItemDelegate):"""自定义的委托用来在Model获取后,view显示前,再将数据渲染一次"""def paint(self, painter, option, index):if index.isValid():painter.save()# 首先,从索引获取数据,这里获取当前索引角色为DisplayRole的数据item_var = index.data(QtCore.Qt.DisplayRole) # [QVariant]if not item_var:return# item区域rect = QRectF()rect.setCoords(option.rect.x(),option.rect.y(),option.rect.x()+option.rect.width(),option.rect.y()+option.rect.height())# 图像区域imageRect = QRect(rect.x()+10,rect.y()+10, 80, 80)# 绘制图像show = cv2.cvtColor(item_var.image, cv2.COLOR_BGR2RGB)showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)painter.drawImage(imageRect,showImage)# 文本区域nameRect = QRect(imageRect.right()+10,imageRect.top(), rect.width()-10-imageRect.width(), 40)painter.setPen(QtGui.QPen(QtCore.Qt.black))painter.setFont(QFont("Microsoft Yahei",12))painter.drawText(nameRect, 0, "视频源:%s" % item_var.name)painter.restore()# 需要指定item宽高def sizeHint(self, option: 'QStyleOptionViewItem', index: QtCore.QModelIndex) -> QtCore.QSize:return QSize(option.rect.width(), 100);
最后再外部调用,这里好像并不用实现model,用QStandardItemModel就好了
# 初始化列表数据self.list_model = QtGui.QStandardItemModel()self.listView.setModel(self.list_model)# 新建一个委托(Delagate)delegate = MyDelegate()# 设置view的delegateself.listView.setItemDelegate(delegate)
当数据更新,需要刷新界面时
for d in list_data:item = QtGui.QStandardItem()item.setData(d, QtCore.Qt.DisplayRole)self.list_model.appendRow(item)self.listView.update()self.listView.scrollToBottom()
这样,一个简单的界面就差不多了
3.在线程中不能直接更新界面
需要配合QThread, 内置信号,通过信号让主线程更新界面.否则会出现界面不更新的奇景,这bug我调了大半天,一直以为是视频解码出错,结果…(泪奔)
# 1)定义线程
class decodeThread(QtCore.QThread):# 通过类成员对象定义信号对象,传递要刷新的图像signal = QtCore.pyqtSignal(QtGui.QPixmap)def __init__(self):super(decodeThread, self).__init__()def run(self):...self.signal.emit(pixmap)# 2)调用线程
self.thread = decodeThread(target=self._init_camera)
#指定收到信号后要执行的方法
self.thread.signal.connect(self._refresh_pic)
self.thread.start()
ps:这里注意thread不能是临时变量,否则会出现另一个神bug
4.pyqt播放音频
pyqt5的QtMultimedia模块找不到,为了不影响系统,这里用pygame
安装pip install pygame
import pygameclass MyPlayer(object):def __init__(self):pygame.mixer.init() # 初始化def play(self, filename):if not pygame.mixer.music.get_busy():pygame.mixer.music.load(filename) # 加载音乐pygame.mixer.music.play() # 播放audioPlayer = MyPlayer()
ps: 结果我的程序跑到半路挂掉了.折腾了1小时发现pygame.mixer.music.load这个方法只能放在主线程中调用,放到多线程中调用会报错:PyEval_SaveThread: NULL tstate
另外,该方法同一时刻仅能播放一个音频
5.dialog弹窗
点击按钮弹出窗口,怎么写.
1)先用qt designer 新建dialog . 一样往里面写控件,然后一样的ui转py,生成Ui_Dialog类
2)实现dialog子类继承该Ui_Dialog类
class childWindow(QDialog,ui_dialog_mask.Ui_Dialog):def __init__(self):QDialog.__init__(self)self.set_ui()def set_ui(self):self.setupUi(self)
3)主窗口调用
App = QApplication(sys.argv)win = Ui_MainWindow()child = childWindow()# 通过toolButton将两个窗体关联btn = win.pushButtonbtn.clicked.connect(child.show)win.show()sys.exit(App.exec_())
小结
1)Qt Designer制作界面生成.ui文件
2)QtUIC将.ui文件转换为.py文件
3)继承该.py文件
class Ui_MainWindow(QtWidgets.QMainWindow, Ui_Page1Window):
则可以通过self访问其中的控件
这一套下来有点像当年开发android了.确实美观便捷
一些问题:
1)pyqt使用png图片时有时会失真,改用jpg
pyqt制作简单的摄像头监控界面相关推荐
- php简单网页制作代码,用HTML和CSS以及JS制作简单的网页菜单界面的代码
这篇文章主要介绍了使用HTML+CSS+JS制作简单的网页菜单界面,这个ABROAD项目所使用的JavaScript部分代码非常简单,需要的朋友可以参考下 写ABROAD项目用到了标签这个东东,其实标 ...
- 【python/qt】Python+Qt实现简单的视频监控界面
DATE: 2018.12.9 1.前言 这个界面是之前读研时候学习QT时写的一个简单的界面,主要实现了人脸检测部分的功能,比较简单. 从今年3月份就开始写这个视频监控的功能,一直拖到了11月份.找工 ...
- php开发路由器界面,PHP制作简单仿路由器登录界面
在php中,可以使用Header函数用户验证: Header('WWW-Authenticate: Basic realm="USER LOGIN"'); Header('HTTP ...
- PHP制作简单仿路由器登录界面
在php中,可以使用Header函数用户验证: Header('WWW-Authenticate: Basic realm="USER LOGIN"'); Header('HTTP ...
- js怎么制作html的主题,用HTML和CSS以及JS制作简单的网页菜单界面的代码
写ABROAD项目用到了标签这个东东,其实标签在WEB上到处可见,图中就依次显示了DCC文章发布器.ABROAD后台添加数据.百度图片搜索.sf发布博客文章时贴标签的样式--标签就像浏览器里原生的ch ...
- android页面布局计算机,Android Studio制作简单计算器App
Android Studio制作简单计算器App 计算机界面如图: 程序设计步骤: (1)在布局文件中声明编辑文件框EditText,按钮Button等组件. (2)在MainActivity中获取组 ...
- arduino摄像头监控_如何使用Arduino和Pusher制作实时光监控器
arduino摄像头监控 by Neo Ighodaro 由新Ighodaro 如何使用Arduino和Pusher制作实时光监控器 (How to make a realtime light mon ...
- android监控摄像头,监控其实很简单 给摄像头装个安卓系统
如果你认为家庭监控摄像机和马路上专门拍车牌的摄像机一样,那你就错了.尽管这两种产品都被叫做监控摄像机,其功能和效果上还是有很大区别.如何给家庭监控摄像机一个更清晰.直观的定义?今天笔者就来跟您聊一聊. ...
- [OpenCv]简单摄像头监控Demo
最近发现一篇报道,十分好玩,有兴趣的可以点击下面的链接 公安部门的摄像头每天都拍到了啥? 然后就写了这个小视频或者摄像头监控Demo玩玩. 1.主要使用OpenCv 2.帧差法与Cascade相结合 ...
最新文章
- MVVM开发模式MVVM Light Toolkit中使用事件和参数传递
- 工业相机参数之帧率相关知识详解
- c语言嵌入式开发单片机,嵌入式开发|单片机基础
- eclipse代码补全
- leetcode101. 对称二叉树(两种做法)
- Waymo自动驾驶数据集介绍与使用教程
- xsi:schemaLocation有何作用
- ajax 表格删除,jQuery AJAX删除只捕获第一个表格
- 获取登录域帐号信息方式之 —-IIS(VB)
- 【Python】基于Python的百度迁徙3——城内出行强度(附代码)
- 3DSMAX 中的CS 骨骼动画插件初探
- 电路分析第三章 电容与电感
- Linux AHCI驱动分析之块设备层
- 时间管理之-----《暗时间》-刘未鹏
- 打开.pos文件--ProcessOn
- tcp ip通讯协议测试软件6,实验6 TCPIP协议属性设置
- 上海计算机一级优秀率,数据 | 上海初中哪家强?2020四校八大预录数据告诉你!...
- 财税SaaS行业格局再变,慧算账为何能受资本“偏爱”?
- LED圆柱屏、波浪屏、飘带屏等异形屏是由柔性软模组构成的创意LED显示屏
- 谈谈事件委托的理解?