opencv+face_recognition+tkinter: 实现简单的视频人脸识别工具(完整代码)

实现效果:写一个图形界面,实现输入一个视频,对视频中的人脸进行捕捉并输出。
在这里插入图片描述

技术基础

本文技术基础将分为三个部分介绍:

用途
opencv 视频处理模块
face_recognition 人脸识别模块
tkinter 窗口视窗设计模块

1.face_recognition

face_recognition是一个强大、简单、易上手的人脸识别开源项目,输入一张图像就可以确定人脸的位置。关于face_recognition的更多内容可以了解https://github.com/ageitgey/face_recognition

下载

以下是我亲自尝试过的face_recognition库下载方法,都成功安装了:

  • win10:最开始直接import face_recognition报错,发现Building wheel for dlib报错,也就是dlib的问题。然后pip install dlib仍然报错。发现和我的3.6版本有冲突。于是找到Windows系统安装dlib可直接在网站https://pypi.org/simple/dlib/ 下载3.6版本对应的whl文件,用pip安装。就是下载这个xxx.whl到一个目录,然后cd/d 该目录,pip install xxx.whl安装成功。再次pip install face_recognition即可。
  • linux: 首先安装cmake
sudo wget  https://cmake.org/files/v3.9/cmake-3.9.0-rc5.tar.gz -O cmake.tar.gz
sudo tar -xvf cmake.tar.gz
cd cmake-3.9.0-rc5/
sudo chmod +x bootstrap
sudo ./bootstrap
sudo make
sudo make install

安装好cmake后,输入

cmake -version

查看cmake版本是否安装成功。然后安装git来手动安装dlib

 git clone https://github.com/davisking/dlib.git
 cd dlib
mkdir build
cd build
cmake ..

最后安装face_recognition。

2.Opencv

Python的cv2库是一个在计算机视觉领域应用非常广泛的库,Python对于视频的读取、处理很多使用cv2库实现。

了解、安装cv2库可以参考Py之cv2:cv2库(OpenCV,opencv-python)的简介、安装、使用方法(常见函数、方法等)最强详细攻略。在处理图像方面,cv2和其他几种常见的库例如PIL的用法很不一样,可以查看我的另一篇文章可以上Python PIL、cv2、Dataloader、plt读取/显示图像数据集对比实例

v2使用有一些坑,例如三个通道的顺序是BGR而不是RGB,有时会报奇怪的错误其实就是图像路径没写对,等等。

3.tkinter

我们可以用GUI 实现很多直观的功能,比如想开发一个计算器,如果只是一个程序输入,输出窗口的话,是没用用户体验的。所有开发一个图像化的小窗口,就是必要的。

Tkinter 就是使用 python 进行窗口视窗设计的模块。Tkinter模块(“Tk 接口”)是Python的标准Tk GUI工具包的接口。

作为 python 特定的GUI界面,是一个图像的窗口,tkinter是python 自带的,不需要另外下载。
参考:Python GUI之tkinter窗口视窗教程大集合(看这篇就够了)

实现

以下给出本文的主要代码,完整代码见我的Github: GUI for video_face_recognition

视频处理部分

这一部分主要使用cv2库实现。
读取视频:

self.cap = cv2.VideoCapture(self.filename)  

读取fps每秒传输帧数、视频时长(帧总数)

self.fps = self.cap.get(cv2.CAP_PROP_FPS)
self.total = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))

设定从视频的第几帧开始读取

self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.start)

如果视频是竖着拍的,在cv2读取进去以后仍然是横向的,所以在人脸识别之前,需要旋转一下。(当然喵酱这些视频都是横着拍的就不用旋转了)
旋转图像代码:

##旋转图像
def rotate_bound(image,angle):
    #获取图像的尺寸
    #旋转中心
    (h,w) = image.shape[:2]
    (cx,cy) = (w/2,h/2)
    
    #设置旋转矩阵
    M = cv2.getRotationMatrix2D((cx,cy),-angle,1.0)
    cos = np.abs(M[0,0])
    sin = np.abs(M[0,1])
    
    # 计算图像旋转后的新边界
    nW = int((h*sin)+(w*cos))
    nH = int((h*cos)+(w*sin))
    
    # 调整旋转矩阵的移动距离(t_{x}, t_{y})
    M[0,2] += (nW/2) - cx
    M[1,2] += (nH/2) - cy
    
    return cv2.warpAffine(image,M,(nW,nH))

读取视频的每一帧图像:

ret, frame = self.cap.read()#frame(720, 1280, 3)BGR            
if not ret:##视频读取结束,退出
    break

## 旋转图片,否则是横过来的
if self.rotate == 1:
    frame = rotate_bound(frame,90)

由于喵酱的视频尺寸比较大,需要缩小尺寸。
然后转成RGB通道。在显示之前还要再转回BGR去。

## 缩放
frame = cv2.resize(frame, (1200, 800))
## BGR到RGB
frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)

然后是辅助功能:在图像上显示当前帧在整个视频上的时间进展

#计算当前时间进度
now_seconds=int(self.cnt/self.fps%60)
now_minutes=int(self.cnt/self.fps/60)
total_second=int(self.total /self.fps%60)
total_minutes=int(self.total/self.fps/60)
#   { <参数序号> : <填充> <对齐)> <宽度> <,> <.精度> <类型>}.
time_now_vs_total="Time:{:>3}:{:>02}|{:>3}:{:0>2}".format(now_minutes,now_seconds,total_minutes,total_second)
# 输出到画面上
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(img, time_now_vs_total, (10, 50), font, 1.0, (255, 255, 255), 1)

人脸识别部分

对于视频场景的人脸识别代码在github上是开源的https://github.com/ageitgey/face_recognition/blob/master/examples/facerec_from_webcam_faster.py,所以选择性的copy就可以了。

首先,对于一帧图像,找到脸的位置

face_locations = face_recognition.face_locations(frame)

然后用蓝色框标记出来就ok了

for (top,right,bottom,left) in face_locations:
    frame = cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)

窗口视窗设计部分

GUI功能:

  • 对竖着拍的视频,需要进行翻转
  • 对于尺寸过大的视频,需要缩小尺寸显示
  • 对于过长的视频,可以支持从任意一帧开始读取
  • 支持隔帧保存输出图像

使用:

  • 点击‘选择视频文件’选择视频文件
  • 设置相关参数
  • 点击‘播放’
  • 按q(英文输入法)退出

我们的窗口设计如下:

图形大小、标题

root = Tk()
root.geometry('250x150+200+200')
root.title('视频人脸识别 1.0')

Label:

Label(root,text = '当前播放:').grid(row = 0,sticky = W)
Label(root,text = '按q退出当前视频').grid(row = 6,column = 0,sticky = W)
Label(root,text = '按空格暂停').grid(row = 6,column = 1,sticky = W)

两个文本框:

Label(root,text = '保存帧间隔').grid(row = 3,column = 0) 
skip_entry = Entry(root)
skip_entry['width'] = 10
skip_entry.insert(0,10) ##每10次保存一张图像
skip_entry.grid(row = 3,column = 1)
 
Label(root,text = '从第几帧读取').grid(row = 4,column = 0) 
start_entry = Entry(root)
start_entry['width'] = 10
start_entry.insert(0,1) ##每10次保存一张图像
start_entry.grid(row = 4,column = 1)

两个Checkbutton:

v = IntVar()
v.set(1)
Checkbutton(root,text = '翻转',variable = v,onvalue=1,offvalue=0).grid(row = 5,column = 0) 

v2 = IntVar()
v2.set(1)
Checkbutton(root,text = '需要缩放尺寸',variable = v2,onvalue=1,offvalue=0).grid(row = 5,column = 1) 

三个Button

Button(root,text = '选择视频文件',command = selectpath).grid(row = 2,column = 0,sticky = W)
Button(root,text = '帮助',background = 'yellow',command = helpful).grid(row = 2,column = 1,sticky = E)
Button(root,text = '播放',background = 'red',command = thread).grid(row = 2,column = 1,sticky = W)

初次了解tkinter,欢迎各位指教。
参考:
https://www.cnblogs.com/mengd/p/7287119.html
Python Tkinter模块详解(后续持续补充)
【Python-opencv3.4】视频基本操作(帧率,总视频帧数、从第N帧开始播放、播放进度显示、按键控制视频)

猜你喜欢

转载自blog.csdn.net/qq_36937684/article/details/106506906
今日推荐