self.ui = QUiLoader().load('xx.ui') #动态载入ui文件
这个是最常见的载入ui文件的方法,还有一种利用pycharm将ui文件转成py文件的方法我没有用过,今天说的这种其实是个乌龙,因为在qtdesigner更新之后运行,发现运行的窗口没有变,是因为我之前把ui文件复制过一次,导致之后更改的ui文件不是我导入的这个文件,所以只要换一下qtdesigner中打开的ui文件就行了
这个真的找了我很久的时间,其大概思路是:
1,用OpenCV的imread()函数读取图片数据;
2,将读取出来的图像数据BGR格式或者BGRA格式转换为RGB格式,用cvtColor()函数转换;
3,将转换过的RGB格式图像数据转换成Qt中的QImage格式;
4,通过QLabel控件显示出来(即把图像设置成背景图片);
然后把代码附上:
from PySide2.QtGui import QImage,QPixmap
def r(self):
a = self.ui.camera
cap=cv2.VideoCapture(0,cv2.CAP_DSHOW)
while(cap.isOpened()): #人脸检测循环
ret, frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # RGB转BGR,不然直接显示会变蓝
frame = cv2.flip(frame, 1) #摄像头是和人对立的,将图像左右调换回来正常显示。
image = QImage(frame, frame.shape[1], frame.shape[0],
frame.strides[0], QImage.Format_RGB888) #Qlmage的参数(data, width, height, bytesPerLine, format )图像存储使用8-8-8 24位RGB格式
a.setPixmap(QPixmap.fromImage(image)) #把图像设置为背景
a.setSizePolicy(QSizePolicy.Ignored,QSizePolicy.Ignored) #按比例填充
a.setScaledContents(True)
key=cv2.waitKey(0) #更新的同时等待操作
if self.ui.close_.isChecked() is True:
break
cv2.destroyAllWindows() #相当于把图相框删掉
cap.release() #释放摄像头
self.ui.camera是指我的Qlabel控件,self.ui.close_则是指我的QcheckBox控件.这里很容易造成内容泄漏啥的,我调试到半夜一点多才弄好。
在opencv里面我们一般都是直接一个while循环实现帧数更新,但是在pyside2里面如果用while会及其不方便,不是组件无法使用,就是组件一直被触发,后来才发现大佬们们都是使用定时器来实现更新:
self.timer=QTimer() #设置定时器
self.timer.timeout.connect(self.show) # 这里调用不能有函数括号,不是单纯的运行函数
self.timer.start(10) #更新时间为每10秒
其中show方法在这里就是指图像显示在label上
一般我们都会直接:
self.cap.release() #释放摄像头
cv2.destroyAllWindows() #相当于把图相框删掉
但是我本来是想实现在子窗口调用opencv的摄像头,然后关掉,再重新回主界面调用摄像头的,结果一直报错:cv2.error: OpenCV(4.5.5) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'
找了很久并不是中文路径的问题,就是摄像头释放的问题,而我直接×掉子页面就不会报错,调用释放函数反而报错了,没办法了,而且我看大佬的代码好像也没有直接释放掉摄像头,那我也就不写这个函数了,直接让用户×掉吧。但是我也不知道这样会不会造成内存泄漏,目前调试的情况还行。
这里我推荐这篇博客
但有几个要注意的地方是每个类的init方法下一定要加
super().__init__()
此外这个博客是直接初始化里面调用了函数,而我的是还设置了属性,我照搬它的会报错没有show()这个方法,改成xx.ui.show()就可以了
self.ui = QUiLoader().load('1.ui') #动态载入ui文件
下面是我出错的代码,原因是因为pandas里的数字用values转化成列表之后变成了矩阵类型,而前者还是字符串类型,所以无法比较。值得一提的是pandas的非数字用values之后仍是字符串类型,所以只要强制输入到pandas里的不是数字就行了
if clerk_name in info['name'].values:
链接
好了,花了这么久系统终于搭好了,源码我会开源出来放在GitHub上:
获取源码(具体的上传步骤我也写了篇博客,大家有兴趣可以看看:博客)
然后已经用pyinstaller打包好了(没想到一次就成了),想要的小伙伴可以底下评论区留言一下。下面放几张运行截图(在寝室不太方便,就打码了):当然程序还有很多不足,包括人脸识别模型没有训练导致识别率较低,文件存储用csv格式安全度不高等等。。所以大家也就随便看看吧