一.PyQt5 GUI中的Opencv眼睛和人脸检测
①Qt designer
②loadandsave.ui -> loadandsave.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'loadandsave.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(824, 576)
self.imagelabel = QtWidgets.QLabel(Dialog)
self.imagelabel.setGeometry(QtCore.QRect(42, 120, 341, 431))
self.imagelabel.setObjectName("imagelabel")
self.processedlabel = QtWidgets.QLabel(Dialog)
self.processedlabel.setGeometry(QtCore.QRect(420, 120, 321, 431))
self.processedlabel.setObjectName("processedlabel")
self.hSlider = QtWidgets.QSlider(Dialog)
self.hSlider.setGeometry(QtCore.QRect(30, 80, 741, 22))
self.hSlider.setOrientation(QtCore.Qt.Horizontal)
self.hSlider.setTickInterval(10)
self.hSlider.setObjectName("hSlider")
self.widget = QtWidgets.QWidget(Dialog)
self.widget.setGeometry(QtCore.QRect(30, 10, 751, 30))
self.widget.setObjectName("widget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.loadButton = QtWidgets.QPushButton(self.widget)
self.loadButton.setObjectName("loadButton")
self.horizontalLayout.addWidget(self.loadButton)
self.saveButton = QtWidgets.QPushButton(self.widget)
self.saveButton.setObjectName("saveButton")
self.horizontalLayout.addWidget(self.saveButton)
self.detectButton = QtWidgets.QPushButton(self.widget)
self.detectButton.setObjectName("detectButton")
self.horizontalLayout.addWidget(self.detectButton)
self.widget1 = QtWidgets.QWidget(Dialog)
self.widget1.setGeometry(QtCore.QRect(520, 60, 261, 21))
self.widget1.setObjectName("widget1")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget1)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.checkface = QtWidgets.QCheckBox(self.widget1)
self.checkface.setObjectName("checkface")
self.horizontalLayout_2.addWidget(self.checkface)
self.checkeye = QtWidgets.QCheckBox(self.widget1)
self.checkeye.setObjectName("checkeye")
self.horizontalLayout_2.addWidget(self.checkeye)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.imagelabel.setText(_translate("Dialog", "imagelabel"))
self.processedlabel.setText(_translate("Dialog", "processedlabel"))
self.loadButton.setText(_translate("Dialog", "Load Image"))
self.saveButton.setText(_translate("Dialog", "Save Image"))
self.detectButton.setText(_translate("Dialog", "Detect"))
self.checkface.setText(_translate("Dialog", "Face"))
self.checkeye.setText(_translate("Dialog", "Eye"))
③ main_code
其中人脸检测和人眼检查模块,
https://pan.baidu.com/s/1k9k0rhzU_kE_ObYvnra7vQ
提取码:740z
import sys
import cv2
from PyQt5 import QtCore
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QImage,QPixmap
from PyQt5.QtWidgets import QDialog,QApplication,QFileDialog
from PyQt5.uic import loadUi
from loadandsave import Ui_Dialog
class Life2Coding(QDialog,Ui_Dialog):
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier("haarcascade_eye.xml")
def __init__(self, parent=None):
super(QDialog,self).__init__(parent)
self.setupUi(self)
self.image = None # 左边imagelabel控件上的图像image
self.processedImage = None #右边processedlabel控件上的图像processedImage
self.loadButton.clicked.connect(self.loadClicked) #按钮Load Image
self.saveButton.clicked.connect(self.saveClicked) #按钮Save Image
self.detectButton.clicked.connect(self.detectClicked) #按钮Canny
self.hSlider.valueChanged.connect(self.cannyDisplay)
@pyqtSlot()
def cannyDisplay(self):
gray = cv2.cvtColor(self.image,cv2.COLOR_BGR2GRAY) if len(self.image.shape) >=3 else self.image
self.processedImage = cv2.Canny(gray,self.hSlider.value(),self.hSlider.value()*3)
self.displayImage(2)
@pyqtSlot()
def detectClicked(self):
gray = cv2.cvtColor(self.image,cv2.COLOR_BGR2GRAY) if len(self.image.shape)>=3 else self.image
faces = self.face_cascade.detectMultiScale(gray,1.3,5)
for (x,y,w,h) in faces:
if self.checkface.isChecked():
cv2.rectangle(self.processedImage,(x,y),(x+w,y+h),(255,0,0),2)
else:
self.processedImage = self.image.copy()
roi_gray = gray[y:y+h,x:x+w]
roi_color = self.processedImage[y:y+h,x:x+w]
if self.checkeye.isChecked():
eyes = self.eye_cascade.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
else:
self.processedImage[y:y+h,x:x+w] = self.image[y:y+h,x:x+w].copy()
self.displayImage(2)
@pyqtSlot()
def loadClicked(self):
fname, filter = QFileDialog.getOpenFileName(self, "Open File", "E:\\youtu_image", "Image Files (*.jpg)")
if fname:
self.loadImage(fname)
else:
print("Invalid Image!!!Check!!!")
@pyqtSlot()
def saveClicked(self):
fname, filter = QFileDialog.getSaveFileName(self, "Save File", "E:\\youtu_image", "Image Files (*.jpg)")
if fname:
cv2.imwrite(fname, self.image)
else:
print("Error!!!")
def loadImage(self,fname):
# self.image = cv2.imread(fname)
self.image = cv2.imread(fname, cv2.IMREAD_COLOR) #图片彩色读取
# self.image = cv2.imread(fname,cv2.IMREAD_GRAYSCALE) #图片灰度读取
self.processedImage = self.image.copy()
self.displayImage(1)
def displayImage(self,window=1):
qformat = QImage.Format_Indexed8
if len(self.processedImage.shape) == 3: #rows->shape[0],cols_>shape[1],channels->shape[2]
if(self.processedImage.shape[2]) == 4:
qformat = QImage.Format_RGBA8888
else:
qformat = QImage.Format_RGB888
img = QImage(self.processedImage,self.processedImage.shape[1],self.processedImage.shape[0],self.processedImage.strides[0],qformat)
# BGR->RGB
img = img.rgbSwapped()
if window == 1:
self.imagelabel.setPixmap(QPixmap.fromImage(img))
self.imagelabel.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
if window == 2:
self.processedlabel.setPixmap(QPixmap.fromImage(img))
self.processedlabel.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
app = QApplication(sys.argv)
window = Life2Coding()
window.show()
sys.exit(app.exec_())
效果:
二.通过PyQt5界面编程旋转一个图片并将其保存
①Qt designer
②loadandsave.ui -> loadandsave.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'loadandsave.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(824, 576)
self.imagelabel = QtWidgets.QLabel(Dialog)
self.imagelabel.setGeometry(QtCore.QRect(42, 120, 341, 431))
self.imagelabel.setObjectName("imagelabel")
self.processedlabel = QtWidgets.QLabel(Dialog)
self.processedlabel.setGeometry(QtCore.QRect(420, 120, 321, 431))
self.processedlabel.setObjectName("processedlabel")
self.hSlider = QtWidgets.QSlider(Dialog)
self.hSlider.setGeometry(QtCore.QRect(30, 80, 231, 22))
self.hSlider.setOrientation(QtCore.Qt.Horizontal)
self.hSlider.setTickInterval(10)
self.hSlider.setObjectName("hSlider")
self.layoutWidget = QtWidgets.QWidget(Dialog)
self.layoutWidget.setGeometry(QtCore.QRect(30, 10, 751, 30))
self.layoutWidget.setObjectName("layoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.loadButton = QtWidgets.QPushButton(self.layoutWidget)
self.loadButton.setObjectName("loadButton")
self.horizontalLayout.addWidget(self.loadButton)
self.saveButton = QtWidgets.QPushButton(self.layoutWidget)
self.saveButton.setObjectName("saveButton")
self.horizontalLayout.addWidget(self.saveButton)
self.detectButton = QtWidgets.QPushButton(self.layoutWidget)
self.detectButton.setObjectName("detectButton")
self.horizontalLayout.addWidget(self.detectButton)
self.layoutWidget1 = QtWidgets.QWidget(Dialog)
self.layoutWidget1.setGeometry(QtCore.QRect(520, 60, 261, 21))
self.layoutWidget1.setObjectName("layoutWidget1")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.layoutWidget1)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.checkface = QtWidgets.QCheckBox(self.layoutWidget1)
self.checkface.setObjectName("checkface")
self.horizontalLayout_2.addWidget(self.checkface)
self.checkeye = QtWidgets.QCheckBox(self.layoutWidget1)
self.checkeye.setObjectName("checkeye")
self.horizontalLayout_2.addWidget(self.checkeye)
self.dialValue = QtWidgets.QDial(Dialog)
self.dialValue.setGeometry(QtCore.QRect(290, 60, 50, 64))
self.dialValue.setMaximum(360)
self.dialValue.setNotchesVisible(True)
self.dialValue.setObjectName("dialValue")
self.rotateValue = QtWidgets.QLineEdit(Dialog)
self.rotateValue.setGeometry(QtCore.QRect(360, 80, 113, 21))
self.rotateValue.setObjectName("rotateValue")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.imagelabel.setText(_translate("Dialog", "imagelabel"))
self.processedlabel.setText(_translate("Dialog", "processedlabel"))
self.loadButton.setText(_translate("Dialog", "Load Image"))
self.saveButton.setText(_translate("Dialog", "Save Image"))
self.detectButton.setText(_translate("Dialog", "Detect"))
self.checkface.setText(_translate("Dialog", "Face"))
self.checkeye.setText(_translate("Dialog", "Eye"))
③ main_code
# -*- coding: utf-8 -*-
import sys
import cv2
from PyQt5 import QtCore
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QImage,QPixmap
from PyQt5.QtWidgets import QDialog,QApplication,QFileDialog,QMessageBox
from PyQt5.uic import loadUi
from loadandsave import Ui_Dialog
import numpy as np
class Life2Coding(QDialog,Ui_Dialog):
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier("haarcascade_eye.xml")
def __init__(self, parent=None):
super(QDialog,self).__init__(parent)
self.setupUi(self)
self.image = None # 左边imagelabel控件上的图像image
self.processedImage = None # 右边processedlabel控件上的图像processedImage
self.loadButton.clicked.connect(self.loadClicked) #按钮Load Image
self.saveButton.clicked.connect(self.saveClicked) #按钮Save Image
self.detectButton.clicked.connect(self.detectClicked) #按钮Canny
self.hSlider.valueChanged.connect(self.cannyDisplay)
self.dialValue.valueChanged.connect(self.rotate_image) #控件Dial
self.rotateValue.returnPressed.connect(self.updateImage) #控件LineEdit
def updateImage(self):
angle = int(self.rotateValue.text())
self.loadButton.setDefault(False)
self.loadButton.setAutoDefault(False)
if angle >= 0 and angle <= 360:
self.rotate_image(angle)
self.dialValue.setValue(angle)
else:
QMessageBox.information(self,"Error!","Please Enter Between 0 to 360")
def rotate_image(self,angle,scale=1):
w = self.image.shape[1]
h = self.image.shape[0]
rangle = np.deg2rad(int(angle)) # 弧度角度转换
# 然后计算新的图片的宽度与高度
nw = (abs(np.sin(rangle) * h) + abs(np.cos(rangle) * w)) * scale
nh = (abs(np.cos(rangle) * h) + abs(np.sin(rangle) * w)) * scale
# 要求Opencv提供旋转矩阵
rot_mat = cv2.getRotationMatrix2D((nw * 0.5,nh * 0.5),angle,scale)
# 计算从原来的中心到新的中心的合并移动及旋转角度
rot_move = np.dot(rot_mat,np.array([(nw - w) * 0.5,(nh - h) * 0.5,0]))
# 移动只会影响角度,因此更新角度
rot_mat[0, 2] += rot_move[0]
rot_mat[1, 2] += rot_move[1]
self.processedImage = cv2.warpAffine(self.image,rot_mat,(int(np.math.ceil(nw)),int(np.math.ceil(nh))))
self.rotateValue.setText(str(angle))
self.displayImage(2)
@pyqtSlot()
def cannyDisplay(self):
gray = cv2.cvtColor(self.image,cv2.COLOR_BGR2GRAY) if len(self.image.shape) >=3 else self.image
self.processedImage = cv2.Canny(gray,self.hSlider.value(),self.hSlider.value()*3)
self.displayImage(2)
@pyqtSlot()
def detectClicked(self):
gray = cv2.cvtColor(self.image,cv2.COLOR_BGR2GRAY) if len(self.image.shape)>=3 else self.image
faces = self.face_cascade.detectMultiScale(gray,1.3,5)
for (x,y,w,h) in faces:
if self.checkface.isChecked():
cv2.rectangle(self.processedImage,(x,y),(x+w,y+h),(255,0,0),2)
else:
self.processedImage = self.image.copy()
roi_gray = gray[y:y+h,x:x+w]
roi_color = self.processedImage[y:y+h,x:x+w]
if self.checkeye.isChecked():
eyes = self.eye_cascade.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
else:
self.processedImage[y:y+h,x:x+w] = self.image[y:y+h,x:x+w].copy()
self.displayImage(2)
@pyqtSlot()
def loadClicked(self):
fname, filter = QFileDialog.getOpenFileName(self, "Open File", "E:\\youtu_image", "Image Files (*.jpg)")
if fname:
self.loadImage(fname)
else:
print("Invalid Image!!!Check!!!")
@pyqtSlot()
def saveClicked(self):
fname, filter = QFileDialog.getSaveFileName(self, "Save File", "E:\\youtu_image", "Image Files (*.jpg)")
if fname:
cv2.imwrite(fname, self.image)
else:
print("Error!!!")
def loadImage(self,fname):
# self.image = cv2.imread(fname)
self.image = cv2.imread(fname, cv2.IMREAD_COLOR) #图片彩色读取
# self.image = cv2.imread(fname,cv2.IMREAD_GRAYSCALE) #图片灰度读取
self.processedImage = self.image.copy()
self.displayImage(1)
def displayImage(self,window=1):
qformat = QImage.Format_Indexed8
if len(self.processedImage.shape) == 3: #rows->shape[0],cols_>shape[1],channels->shape[2]
if(self.processedImage.shape[2]) == 4:
qformat = QImage.Format_RGBA8888
else:
qformat = QImage.Format_RGB888
img = QImage(self.processedImage,self.processedImage.shape[1],self.processedImage.shape[0],self.processedImage.strides[0],qformat)
# BGR->RGB
img = img.rgbSwapped()
if window == 1:
self.imagelabel.setPixmap(QPixmap.fromImage(img))
self.imagelabel.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
if window == 2:
self.processedlabel.setPixmap(QPixmap.fromImage(img))
self.processedlabel.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
app = QApplication(sys.argv)
window = Life2Coding()
window.show()
sys.exit(app.exec_())
效果: