PyQt/人脸描点检测/OpencvWidget.py

114 lines
4.2 KiB
Python
Raw Normal View History

2018-01-29 22:08:38 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Created on 2018年1月29日
@author: Irony."[讽刺]
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
@email: 892768447@qq.com
@file: OpencvWidget
@description:
'''
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QLabel, QMessageBox, QApplication
import cv2 # @UnresolvedImport
import dlib
import numpy
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
__Version__ = "Version 1.0"
DOWNSCALE = 4
class OpencvWidget(QLabel):
def __init__(self, *args, **kwargs):
super(OpencvWidget, self).__init__(*args, **kwargs)
self.fps = 24
self.resize(800, 600)
self.setText("请稍候,正在初始化数据和摄像头。。。")
def start(self):
try:
# 检测相关
self.detector = dlib.get_frontal_face_detector()
self.predictor = dlib.shape_predictor(
"data/shape_predictor_68_face_landmarks.dat")
cascade_fn = "data/lbpcascades/lbpcascade_frontalface.xml"
self.cascade = cv2.CascadeClassifier(cascade_fn)
if not self.cascade:
return QMessageBox.critical(self, "错误", cascade_fn + " 无法找到")
self.cap = cv2.VideoCapture(0)
if not self.cap or not self.cap.isOpened():
return QMessageBox.critical(self, "错误", "打开摄像头失败")
# 开启定时器定时捕获
self.timer = QTimer(self, timeout=self.onCapture)
self.timer.start(1000 / self.fps)
except Exception as e:
QMessageBox.critical(self, "错误", str(e))
def closeEvent(self, event):
if hasattr(self, "timer"):
self.timer.stop()
self.timer.deleteLater()
self.cap.release()
del self.predictor, self.detector, self.cascade, self.cap
super(OpencvWidget, self).closeEvent(event)
self.deleteLater()
def onCapture(self):
_, frame = self.cap.read()
minisize = (
int(frame.shape[1] / DOWNSCALE), int(frame.shape[0] / DOWNSCALE))
tmpframe = cv2.resize(frame, minisize)
tmpframe = cv2.cvtColor(tmpframe, cv2.COLOR_BGR2GRAY) # 做灰度处理
tmpframe = cv2.equalizeHist(tmpframe)
# minNeighbors表示每一个目标至少要被检测到5次
faces = self.cascade.detectMultiScale(tmpframe, minNeighbors=5)
del tmpframe
if len(faces) < 1: # 没有检测到脸
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = QImage(
frame.data, frame.shape[1], frame.shape[0], frame.shape[1] * 3, QImage.Format_RGB888)
del frame
return self.setPixmap(QPixmap.fromImage(img))
# 特征点检测描绘
for x, y, w, h in faces:
x, y, w, h = x * DOWNSCALE, y * DOWNSCALE, w * DOWNSCALE, h * DOWNSCALE
# 画脸矩形
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0))
# 截取的人脸部分
tmpframe = frame[y:y + h, x:x + w]
# 进行特征点描绘
rects = self.detector(tmpframe, 1)
if len(rects) > 0:
landmarks = numpy.matrix(
[[p.x, p.y] for p in self.predictor(tmpframe, rects[0]).parts()])
for _, point in enumerate(landmarks):
pos = (point[0, 0] + x, point[0, 1] + y)
# 在原来画面上画点
cv2.circle(frame, pos, 3, color=(0, 255, 0))
# 转成Qt能显示的
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = QImage(
frame.data, frame.shape[1], frame.shape[0], frame.shape[1] * 3, QImage.Format_RGB888)
del frame
self.setPixmap(QPixmap.fromImage(img))
if __name__ == "__main__":
app = QApplication(sys.argv)
w = OpencvWidget()
w.show()
# 5秒后启动
QTimer.singleShot(5000, w.start)
sys.exit(app.exec_())