任务
在Windows10系统下,用python,在jupyter notebook 结合cv2、dlib、face_recognition、matplotlib.pyplot等库进行摄像头实时捕获人脸、简单的AI换脸。
目录
Ⅰ仅依赖cv2实现摄像头实时人脸捕获
Ⅱ 依赖于cv2、dlib实现摄像头实时人脸捕获
Ⅲ 用PIL、face_recognition、matplotlib.pyplot等实现简单的AI换脸
导入cv2,打开摄像头。
cv2.VideoCapture()参数0表示打开笔记本内置摄像头。
object的参数、用法等可以用dir或导入inspect进行查看。
import cv2
cap=cv2.VideoCapture(0)
定义函数,输入图片,选择cv2中能进行特定筛选的级联分类器(如此出选了正脸),并画出人脸矩形框,返回添加上矩形框的图片。
def detect(img):
face_cascade=cv2.CascadeClassifier(r'F:\Python-3.8.2\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')
#face_cascade=cv2.CascadeClassifier("F:\Python-3.8.2\Lib\site-packages\cv2\data\haarcascade_eye.xml")
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces=face_cascade.detectMultiScale(gray,1.1,5)
#print(len(faces))
for (x,y,w,h) in faces:
img=cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
return img
cap.read()返回两个值:一个布尔值 true/false,用来判断读取视频是否成功/是否到视频末尾;另一个是图像对象,图像的三维矩阵q
waitKey(delay) :不断刷新图像 , 频率时间为delay , 单位为ms ,返回值为当前键盘按键值的ASCII码,如ESC为27
0x表示16进制,16进制中的F等于2进制中4位:1111,也等于十进制的15,FF转化为2进制即1111 1111
按位与运算符(&). 参加运算的两个数据,按二进制位进行“与”运算,同位中两者皆为1是返回1,否则为0。负数用起二进制补码进行运算。一个负数按照绝对值大小转换成的二进制数,然后最高位补1。
由于键盘按键的ASCII码不一定都是8位2进制数,可能有超过8位的,当其与0xFF进行&运算时,超过8位的那些都成了0,没超过的都返回原值
If语句:当按下键盘中的ESC键时,结束while循环,结束人脸捕获。
cap.release() 停止捕获视频(release注意拼写,不要写成ralease)
cv2.destroyAllWindows() 关闭相应的显示窗口
while True:
_,frame=cap.read()
frame=detect(frame)
cv2.imshow("video",frame)
if cv2.waitKey(1000)&0xFF==27:
break
cap.release()
cv2.destroyAllWindows()
完整代码:
import cv2
cap=cv2.VideoCapture(0)
def detect(img):
face_cascade=cv2.CascadeClassifier(r'F:\Python-3.8.2\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')
#face_cascade=cv2.CascadeClassifier("F:\Python-3.8.2\Lib\site-packages\cv2\data\haarcascade_eye.xml")
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces=face_cascade.detectMultiScale(gray,1.1,5)
for (x,y,w,h) in faces:
img=cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
return img
while True:
_,frame=cap.read()
frame=detect(frame)
cv2.imshow("video",frame)
if cv2.waitKey(1000)&0xFF==27:
break
cap.release()
cv2.destroyAllWindows()
detector识别人脸,并用矩形框定人脸区域。
predictor指定区域内给人脸关键部位打点。
dlib.get_frontal_face_detector():有参数,括号不能漏掉。
detector(frame,1):frame表示图像,1表示采样次数,返回图像中所有包含人脸的矩形框。
cv2.circle():参数依次是图像、圆心、半径、颜色、厚度。其中厚度:正数表示边框粗细,负数表示绘制实心圆。
import cv2
import dlib
cap=cv2.VideoCapture(0)
predictor=dlib.shape_predictor(r"F:\Python-3.8.2\Lib\site-packages\face_recognition_models\models\shape_predictor_68_face_landmarks.dat")
detector=dlib.get_frontal_face_detector()
while True:
_,frame=cap.read()
dets=detector(frame,1)
if len(dets)!=0:
for i in range(len(dets)):
shape=predictor(frame,dets[0])
for p in shape.parts():
cv2.circle(frame,(p.x,p.y),3,(0,0,0),-1)
cv2.imshow("video1",frame)
if cv2.waitKey(1) & 0xFF==27:
break
cap.release()
cv2.destroyAllWindows()
PIL:Python Imaging Library,用于图像处理,但PIL仅支持到Python 2.7,又年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了许多新特性,因此直接安装使用Pillow。
安装Python时已经把pip3也备好了,可以直接使用pip3安装PIL
cmd调出命令提示符,输入命令行:pip3 install pillow
导入所需各库。
from PIL import Image
import face_recognition
import matplotlib.pyplot as plt
定义函数,用face_recognition识别人脸,并返回人脸位置矩形框。该人脸位置矩形框呈现(上,右,下,左)四元组形式。
后面PIL的裁剪、粘贴时的位置大小,识别的是(左,上,右,下)四元组的格式,因而在识别结束后进行顺序替换,以便后续操作。
detect函数,输入图片,返回人脸矩形框位置。
def detect(filename):
image=face_recognition.load_image_file(filename)
face_locations=face_recognition.face_locations(image)
face_num=len(face_locations)
for i in range(0,face_num):
a=face_locations[i][0]
b=face_locations[i][1]
c=face_locations[i][2]
d=face_locations[i][3]
box=(d,a,b,c)
return box
对两张目标图片进行函数调用,获得人脸大小及位置。
Image.open(filename):打开图片
img.convert():参数为“L”转换为灰度图像,“P”转换为8位彩色图像,“RGBA”转换为32位彩色图像
img.crop(box):按大小位置裁剪,box为一个(左,上,右,下)四元组
img.resize(size):重新定义图片大小,size为(横,竖)二元组。
img.paste(filename,box):在img上指定位置粘贴filename图片,box大小与filename完全一致
box1=detect("zel1.jpg")
box2=detect("zel2.jpg")
img1=Image.open("zel1.jpg").convert("L").crop(box1)
img2=Image.open("zel2.jpg").convert("L")
size2=(box2[2]-box2[0],box2[3]-box2[1])
img1new=img1.resize(size2)
img2.paste(img1new,box2)
plt.imshow(img2)
plt.axis("off")
plt.show()
完整代码:
from PIL import Image
import face_recognition
import matplotlib.pyplot as plt
def detect(filename):
image=face_recognition.load_image_file(filename)
face_locations=face_recognition.face_locations(image)
face_num=len(face_locations)
for i in range(0,face_num):
a=face_locations[i][0]
b=face_locations[i][1]
c=face_locations[i][2]
d=face_locations[i][3]
box=(d,a,b,c)
return box
box1=detect("zel1.jpg")
box2=detect("zel2.jpg")
img1=Image.open("zel1.jpg").convert("L").crop(box1)
img2=Image.open("zel2.jpg").convert("L")
print(type(img2))
size2=(box2[2]-box2[0],box2[3]-box2[1])
img1new=img1.resize(size2)
img2.paste(img1new,box2)
plt.imshow(img2)
plt.axis("off")
plt.show()