Topic: 利用pyqt5編寫簡單界面
Env:win10 + Pycharm2018 + Python 3.6.8
Date: 2019/4/29 by hw_Chen2018 CSDN:https://blog.csdn.net/qq_34198088/article/details/97893081
基本功能:利用攝像頭采集使用者頭像,點擊“采集照片”,當前圖像會“暫存”並顯示在右邊,“暫存”數量3。然后依次填入姓名,選擇姓名,最后點擊“保存”,保存照片在固定路徑下。如果“暫存”圖像張數小於3、未填入姓名、選擇性別,會提示未進行相應操作。選擇“清空”,會清空當前“暫存”圖像和輸入姓名字符串,以便繼續錄入。( 因為我這里使用的雙目攝像頭,顯示的左右相機的輸出,如果接入正常單目USB攝像頭,則是正常的;與腳本同一級目錄下有個img文件夾。功能簡單,調用第三方庫少,轉載請注明出處!
界面如下圖:
from cap_info import * import cv2 as cv from PyQt5 import QtCore, QtGui, QtWidgets import sys import matplotlib matplotlib.rcParams['font.sans-serif'] = ['SimHei'] matplotlib.rcParams['font.family'] = 'sans-serif' matplotlib.rcParams['axes.unicode_minus'] = False if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) w = mywindow() w.photo_pb.clicked.connect(w.display_img) w.show() sys.exit(app.exec_())
腳本can_info.py如下:
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'cap_info.ui' # # Created by: PyQt5 UI code generator 5.11.3 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets import cv2 as cv import sys import os class Ui_Form(object): def setupUi(self, Form): Form.setObjectName("Form") Form.resize(480, 480) Form.setMinimumSize(QtCore.QSize(480, 480)) Form.setMaximumSize(QtCore.QSize(480, 480)) self.photo_pb = QtWidgets.QPushButton(Form) self.photo_pb.setGeometry(QtCore.QRect(190, 290, 81, 31)) self.photo_pb.setStyleSheet("font: 14pt \"華文行楷\";") self.photo_pb.setObjectName("photo_pb") self.save_pb = QtWidgets.QPushButton(Form) self.save_pb.setGeometry(QtCore.QRect(150, 440, 75, 31)) self.save_pb.setStyleSheet("font: 14pt \"華文行楷\";") self.save_pb.setObjectName("save_pb") self.photo_lbl = QtWidgets.QLabel(Form) self.photo_lbl.setGeometry(QtCore.QRect(70, 30, 321, 251)) self.photo_lbl.setMinimumSize(QtCore.QSize(321, 251)) self.photo_lbl.setMaximumSize(QtCore.QSize(321, 251)) self.photo_lbl.setFrameShape(QtWidgets.QFrame.Box) self.photo_lbl.setText("") self.photo_lbl.setObjectName("photo_lbl") self.label = QtWidgets.QLabel(Form) self.label.setGeometry(QtCore.QRect(120, 350, 51, 20)) self.label.setStyleSheet("font: 14pt \"華文行楷\";") self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(Form) self.label_2.setGeometry(QtCore.QRect(120, 390, 51, 20)) self.label_2.setStyleSheet("font: 14pt \"華文行楷\";") self.label_2.setObjectName("label_2") self.name = QtWidgets.QLineEdit(Form) self.name.setGeometry(QtCore.QRect(180, 350, 113, 20)) self.name.setObjectName("name") self.radioButton = QtWidgets.QRadioButton(Form) self.radioButton.setGeometry(QtCore.QRect(180, 390, 41, 16)) self.radioButton.setObjectName("radioButton") self.radioButton_2 = QtWidgets.QRadioButton(Form) self.radioButton_2.setGeometry(QtCore.QRect(240, 390, 41, 16)) self.radioButton_2.setObjectName("radioButton_2") self.photo1 = QtWidgets.QLabel(Form) self.photo1.setGeometry(QtCore.QRect(410, 30, 51, 71)) self.photo1.setMinimumSize(QtCore.QSize(51, 71)) self.photo1.setMaximumSize(QtCore.QSize(51, 71)) self.photo1.setFrameShape(QtWidgets.QFrame.Box) self.photo1.setObjectName("photo1") self.photo2 = QtWidgets.QLabel(Form) self.photo2.setGeometry(QtCore.QRect(410, 120, 51, 71)) self.photo2.setMinimumSize(QtCore.QSize(51, 71)) self.photo2.setMaximumSize(QtCore.QSize(51, 71)) self.photo2.setFrameShape(QtWidgets.QFrame.Box) self.photo2.setObjectName("photo2") self.photo3 = QtWidgets.QLabel(Form) self.photo3.setGeometry(QtCore.QRect(410, 210, 51, 71)) self.photo3.setMinimumSize(QtCore.QSize(51, 71)) self.photo3.setMaximumSize(QtCore.QSize(51, 71)) self.photo3.setFrameShape(QtWidgets.QFrame.Box) self.photo3.setObjectName("photo3") self.clear_pb = QtWidgets.QPushButton(Form) self.clear_pb.setGeometry(QtCore.QRect(250, 440, 71, 31)) self.clear_pb.setStyleSheet("font: 14pt \"華文行楷\";") self.clear_pb.setObjectName("clear_pb") self.label_3 = QtWidgets.QLabel(Form) self.label_3.setGeometry(QtCore.QRect(365, 300, 101, 21)) self.label_3.setStyleSheet("font: 75 9pt \"Adobe Arabic\";") self.label_3.setObjectName("label_3") self.photo_num = QtWidgets.QLabel(Form) self.photo_num.setGeometry(QtCore.QRect(430, 300, 21, 20)) self.photo_num.setText("") self.photo_num.setObjectName("photo_num") self.retranslateUi(Form) QtCore.QMetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "采集界面")) self.photo_pb.setText(_translate("Form", "采集照片")) self.save_pb.setText(_translate("Form", "保存")) self.label.setText(_translate("Form", "姓名:")) self.label_2.setText(_translate("Form", "性別:")) self.radioButton.setText(_translate("Form", "男")) self.radioButton_2.setText(_translate("Form", "女")) self.photo1.setText(_translate("Form", "照片1")) self.photo2.setText(_translate("Form", "照片2")) self.photo3.setText(_translate("Form", "照片3")) self.clear_pb.setText(_translate("Form", "清空")) self.label_3.setText(_translate("Form", "照片數量:")) class mywindow(Ui_Form, QtWidgets.QWidget): def __init__(self): super(mywindow, self).__init__() self.setupUi(self) self.cap = cv.VideoCapture(0) if not self.cap.isOpened(): QtWidgets.QMessageBox.warning(self, "警告", "未成功打開攝像頭!") self.video_timer = QtCore.QTimer() self.photo_pb.clicked.connect(self.video_play_slot) # 顯示每一幀圖像 self.captureImg_flag = False # 截圖控制符 self.captureImg_count = 0 # 截圖數目 self.img_list = [] # 保存截圖 self.captureImg_num = 0 # 截圖數量 self.save_pb.clicked.connect(self.save_info) # 保存信息 self.clear_pb.clicked.connect(self.clear_content) def video_play_slot(self): if not self.cap.isOpened(): QtWidgets.QMessageBox.warning(self, "警告", "未成功打開攝像頭!請關閉界面並重新打開!") else: if not self.video_timer.isActive(): self.video_timer.start(30) self.video_timer.timeout.connect(self.display_img) else: self.captureImg_flag = True def closeEvent(self, QCloseEvent): ''' 窗口關閉事件 :param QCloseEvent: :return: ''' reply = QtWidgets.QMessageBox.question(self, "確認", "確認退出嗎?", QtWidgets.QMessageBox.Yes|QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.Yes: self.video_timer.stop() self.cap.release() QCloseEvent.accept() else: QCloseEvent.ignore() def display_img(self): ''' 顯示每一幀圖像 :return: 無 ''' self.photo_num.setText(str(len(self.img_list))) # 顯示當前采集的照片數量 ret, frame = self.cap.read() if not ret: print("cannot receive this frame.") else: frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB) height, width, bytesPerComponent = frame.shape bytesPerLine = bytesPerComponent * width q_image = QtGui.QImage(frame.data, width, height, bytesPerLine, QtGui.QImage.Format_RGB888).scaled(self.photo_lbl.width(), self.photo_lbl.height()) self.photo_lbl.setPixmap(QtGui.QPixmap.fromImage(q_image)) if self.captureImg_flag: # if self.captureImg_count == 1: # QtWidgets.QMessageBox.information(self, "提醒", "請盡量保持所采集的照片人臉姿態多樣性!") if len(self.img_list) >= 3: self.img_list.pop(0) frame1 = frame.copy() temp = self.captureImg_count % 3 height, width, bytesPerComponent = frame1.shape bytesPerLine = bytesPerComponent * width q_image = QtGui.QImage(frame1.data, width, height, bytesPerLine,QtGui.QImage.Format_RGB888).scaled(self.photo1.width(), self.photo1.height()) if temp == 0: self.photo1.setPixmap(QtGui.QPixmap.fromImage(q_image)) self.img_list.append(frame1) # print(len(self.img_list)) elif temp == 1: self.photo2.setPixmap(QtGui.QPixmap.fromImage(q_image)) self.img_list.append(frame1) # print(len(self.img_list)) elif temp == 2: self.photo3.setPixmap(QtGui.QPixmap.fromImage(q_image)) self.img_list.append(frame1) # print(len(self.img_list)) self.captureImg_flag = False self.captureImg_count += 1 def save_info(self): flag1 = False flag2 = False flag3 = False if len(self.img_list) < 3: # 判斷照片數量 QtWidgets.QMessageBox.warning(self, "警告", "照片數量小於三張!") else: flag1 = True name_str = self.name.text() if len(name_str) == 0: # 判斷是否輸入姓名 QtWidgets.QMessageBox.warning(self, "警告", "姓名為空!") else: flag2 = True if self.radioButton.isChecked() == self.radioButton_2.isChecked(): # 判斷是否選擇性別 QtWidgets.QMessageBox.warning(self, "警告", "未選擇性別!") else: flag3 = True if flag2 and flag1 and flag3: dirname, filename = os.path.split((os.path.abspath(sys.argv[0]))) # 獲取當前主運行文件絕對地址 targetpath = dirname + os.path.sep + 'img' # 構造文件路徑 if not os.path.exists(targetpath): # 判斷路徑是否存在,不存在則創建 os.makedirs(targetpath) # os.chdir(targetpath) # 設置當前工作路徑 temp_info_text = open(dirname + os.path.sep + 'img' + os.path.sep + 'info.txt', 'x+') temp_info_text.close() os.chdir(targetpath) info_text = open('info.txt','a') for _num in range(3): imgname = name_str + '_' + str(_num) + '.jpg' tempimg = cv.cvtColor(self.img_list[(len(self.img_list) - _num - 1)],cv.COLOR_RGB2BGR) cv.imencode('.jpg', tempimg)[1].tofile(imgname) temppath = targetpath + os.path.sep + imgname + '#' info_text.write(temppath) # 保存照片路徑 if self.radioButton.isChecked(): gender = '男' + '#' elif self.radioButton_2.isChecked(): gender = '女' + '#' info_text.write(gender) # 寫入性別信息 info_text.write('\n') info_text.close() QtWidgets.QMessageBox.about(self, "保存", "保存成功!") def clear_content(self): reply = QtWidgets.QMessageBox.question(self, "清空", "確認清空所有嗎?", QtWidgets.QMessageBox.Yes|QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.Yes: self.photo1.clear() self.photo2.clear() self.photo3.clear() self.img_list.clear() self.name.clear() self.captureImg_count = 0 # self.radioButton.setChecked(False) # self.radioButton_2.setChecked(False)