TensorFlow2+OpenCV实现⼈像采集与识别
TensorFlow2+OpenCV实现⼈像采集与识别
前⾔
本设计⽤python语⾔实现,这⾥罗列⼀下整个项⽬所需要的包(仅供参考)
h5py==2.9.0
Keras==2.3.1
scipy==1.5.2
numpy==1.19.5
scikit-learn==0.24.1
tensorflow==2.1.0
opencv-python==4.5.1.48
⼈脸识别四个步骤,分别为⼈脸图像检测和采集,图像预处理,⽹络搭建和模型训练,⼈脸图像匹配与识别。
1、检测⼀张图⽚中的所有⼈脸,初次使⽤需要采集⼈脸图像保存到本地供模型训练时使⽤。
2、对于采集的每⼀张⼈脸图像,其⼤⼩⼀般都不相同,需要对其处理成相同⼤⼩,并对每⼀张图⽚进⾏标注。
3、本项⽬使⽤卷积神经⽹络训练模型,所以⾸先搭建好⽹络框架,并使⽤预先处理好的数据训练模型。
4、输⼊⼀张⼈脸图像,使⽤训练好的模型识别图像中的⼈是谁。
1、图像检测和采集
OpenCV是⼀个基于BSD许可(开源)发⾏的跨平台计算机视觉和机器学习软件库,⽤C++语⾔编写,它提供了很多图像处理和计算机视觉⽅⾯的通⽤算法,本项⽬中⼈脸图像的检测和采集都是通过OpenCV实现的,但是这⾥你并不需要特意去学习OpenCV(其实我会的也不多☺),只需要调⽤其中的API函数就可以了。
⾸先是采集⼈脸图像构成数据集,建⽴pic_capture.py⽂件:
import cv2
def face_pic_capture(window_name, camera_id, catch_pic_num, path_name):
CreateFolder(path_name)#[1]
cv2.namedWindow(window_name)
image_set = cv2.VideoCapture(camera_id)#[2]
classifier = cv2.CascadeClassifier(r"D:\anaconda3\envs\tensorflow\Lib\site-packages\cv2\data\haarcascade_l")#[3]
num =1#⽤于对每张图⽚命名
while image_set.isOpened():#[4]
flag, frame = ad()#[5]
if not flag:
break
image_grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faceRect = classifier.detectMultiScale(image_grey, scaleFactor=1.2, minNeighbors=3, minSize=(32,32))#[6]
if len(faceRect)>0:# ⼤于0则检测到⼈脸
for facet in faceRect:#[7]
x, y, w, h = facet
if w >100:
img_name ='{}/{}.jpg'.format(path_name, num)
image = frame[y -10: y + h +10, x -5: x + w +5]
cv2.imwrite(img_name, image)#检测到有⼈脸的图像帧保存到本地
font = cv2.FONT_HERSHEY_SIMPLEX
# 显⽰当前保存了多少张图⽚,
cv2.putText(frame,"num:{}".format(num),(x +30, y -15), font,1,(0,250,250),4)#[9]
num +=1
if num > catch_pic_num:
break
if num > catch_pic_num:
break
# 显⽰图像,按"Q"键中断采集过程
cv2.imshow(window_name, frame)
if cv2.waitKey(200)&0xFF==ord('q'):
break
# 释放摄像头并关闭销毁所有窗⼝
lease()
cv2.destroyAllWindows()
⾸先导⼊opencv模块,cv2中的”2”并不表⽰OpenCV的版本号。我们知道,OpenCV是基于C/C++的,”cv”和”cv2”表⽰的是底层CAPI和C++API的区别,”cv2”表⽰使⽤的是C++API。
在函数定义中,括号内参数window_name, camera_id, catch_pic_num, path_name分别表⽰窗⼝名字,摄像头系列号,采集照⽚数量和图⽚存储路径,可以根据⾃⼰需要进⾏修改。咱们这⾥为了精度⾼⼀点,选择捕捉1000张脸部照⽚。由于精度的问题,在程序运⾏的过程中常常会采集到⾮脸部的照⽚,所以catch_pic_num设置⽐预期⼤些,从⽽清洗掉⾮脸部照⽚后数据集不⾄于太少。另外,在这⾥不只是采集⼀个⼈的⼈脸图⽚,所以将不同的⼈照⽚单独存储在⼀个⽂件夹下,不可弄混。数据保存结果截图如下:
[1] CreateFolder()函数⽤于检测传递过来的⽂件路径是否存在,如果路径不存在就创建该路径。
[2] cv2.VideoCapture()是OpenCV的⼀个API,参数camera_id为0,表⽰打开笔记本的内置摄像头,如果是视频⽂件路径则打开
本地视频,有的设为1表⽰打开外接摄像头。
[3] cv2.CascadeClassifier是Opencv中做⼈脸检测的时候的⼀个级联分类器,到这个路径并且复制到程序中(最好使⽤绝对路
径),这个东西的作⽤主要是实现对⼈脸识别的功能,该路径下还有其他功能的haarcascades API:
⼈脸检测器(默认):haarcascade_l
⼈脸检测器(快速Harr):haarcascade_l
⼈脸检测器(侧视):l
眼部检测器(左眼):haarcascade_l
眼部检测器(右眼):haarcascade_l
嘴部检测器:haarcascade_l
⿐⼦检测器:haarcascade_l
⾝体检测器:l
⼈脸检测器(快速LBP):l
[4] image_set.isOpened():判断视频对象是否成功读取,成功读取视频对象返回True。
[5] flag, frame = ad():按帧读取视频,返回值flag是布尔型,正确读取则返回True,读取失败或读取视频结尾则会返
回False;frame为每⼀帧的图像,为三维矩阵、BGR格式。
[6] classifier.detectMultiScale()是OpenCV2中的⼈脸检测函数,并将⼈脸⽤vector保存各个⼈脸的坐标、⼤⼩(⽤矩形表⽰),
函数由分类器对象调⽤。
函数原型:
void detectMultiScale(
> const Mat& image,
> CV_OUT vector<Rect>& objects,
> double scaleFactor =1.1,
>int minNeighbors =3,
>int flags =0,
> Size minSize = Size(),
> Size maxSize = Size()
>);
函数介绍:
参数1:image—输⼊图⽚,⼀般转换为灰度图像加快检测速度;
参数2:objects—被检测物体的矩形框向量组;
参数3:scaleFactor—图像缩放⽐例,表⽰在前后两次相继的扫描中,搜索窗⼝的⽐例系数。默认为1.1,即每次搜索窗⼝依次扩⼤10%。
参数4:minNeighbors—表⽰构成检测⽬标的相邻矩形的最⼩个数,默认为3(每⼀个特征匹配到的区域都是⼀个矩形框,只有多个矩形框同时存在的时候,才认为是匹配成功)。
参数5:flags—要么使⽤默认值0,要么取如下这些值:
1:CASCADE_DO_CANNY_PRUNING,利⽤canny边缘检测来排除⼀些边缘很少或者很多的图像区域
2:CASCADE_SCALE_IMAGE,正常⽐例检测
4:CASCADE_FIND_BIGGEST_OBJECT,只检测最⼤的物体
8:CASCADE_DO_ROUGH_SEARCH,初略的检测
参数6/7:minSize和maxSize⽤来限制得到的⽬标区域的范围。
[7] 对同⼀个画⾯有可能出现多张⼈脸,所以这⾥⽤⼀个for循环将所有检测到的⼈脸都读取出来,然后返回检测到的每张⼈脸在图像
rectangle函数opencv中的起始坐标(左上⾓,x、y)以及长、宽(h、w)。
[8] angle()完成画框的⼯作,这⾥外扩了⼏个像素以框出⽐⼈脸稍⼤⼀点的区域。函数的最后两个参数⼀个⽤于指定矩形边
框的颜⾊,⼀个⽤于指定矩形边框线条的粗细程度。
[9] cv2.putText(image, text, (5,50 ), cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0, 0, 255), 2)各参数依次表⽰:输出图⽚,要添
加的⽂字,⽂本左上⾓坐标,字体类型,字体⼤⼩,字体颜⾊,字体粗细。
运⾏结果:
到此,顺利检测到视频中的⼈脸,并构建了数据集,接下来开始对图像进⾏预处理!
2、图像预处理
这⼀部分代码实现将数据集内的图像裁剪成相同⼤⼩,并对每张图像标注。⾸先建⽴⼀个python⽂件,
命名data_process.py:
1. 定义⼀个risize_image()函数裁剪图像:
def resize_image(image, height=IMAGE_SIZE, width=IMAGE_SIZE):
top, bottom, left, right =(0,0,0,0)# 初始化图像尺⼨
h, w, _ = image.shape
longer_edge =max(h, w)
#计算短边需要增加多上像素宽度使其与长边等长
if h < longer_edge:
dh = longer_edge - h
top = dh //2
bottom = dh - top
elif w < longer_edge:
dw = longer_edge - w
left = dw //2
right = dw - left
else:
pass
adjusted_image = pyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=[120,120,220])#[1]
size(adjusted_image,(height, width))
IMAGE_SIZE是预先设置的图像像素⼤⼩,可以⾃⾏更改。
[1] pyMakeBorder()函数⽤于给图⽚添加边界,就像⼀个相框⼀样的东西。
参数解释:
src:源图像
top,bottem,left,right:分别表⽰四个边界⽅向上扩充像素数
borderType:边界的类型有以下⼏种:
BORDER_REFLICATE
BORDER_REFLECT
BORDER_REFLECT_101
BORDER_WRAP
BORDER_CONSTANT
value:边界类型为cv.BORDER_CONSTANT时的边界框颜⾊
resize_image()函数先判断图⽚是不是正⽅形,如果不是则增加短边的长度使之变成正⽅形。这样再调⽤size()函数就可以实现等⽐例缩放了,只有缩放之前图像为正⽅形才能确保图像不失真。例如:
这样明显不是正⽅形,程序运⾏之后要达到下图效果。
2. 接下来对图像进⾏标注,对每⼀张图像设置⼀个标签
def read_path(path_name, h=IMAGE_SIZE, w=IMAGE_SIZE):
for dir_item in os.listdir(path_name):
# 从初始路径开始叠加,合并成可识别的操作路径
full_path = os.path.abspath(os.path.join(path_name, dir_item))
if os.path.isdir(full_path):# 如果是⽂件夹,继续递归调⽤
read_path(full_path, h, w)
else:
if dswith('.jpg'):
image = cv2.imread(full_path)
image = resize_image(image, h, w)
images.append(image)
labels.append(path_name)
return images, labels
# 为每⼀类数据赋予唯⼀的标签值
def label_id(label, users, user_num):
for i in range(user_num):
dswith(users[i]):
return i
# 从指定位置读数据
def load_dataset(path_name):
users = os.listdir(path_name)# 返回指定的⽂件夹包含的⽂件或⽂件夹的名字的列表
user_num =len(users)
Image, Label = read_path(path_name)
images_np = np.array(Image)
labels_np = np.array([label_id(label, users, user_num)for label in Label])#[2]
return images_np, labels_np
[2] 这⾥每个图像数据集唯⼀的对应⼀个⼈,直接使⽤⽂件夹名称作为标签,简单⽅便,即上⾯将不同的⼈的图像集分别放置的⽬的。
3、⽹络搭建和模型训练
这⾥建⽴了⼀个包含4个卷积层的神经⽹络(CNN),程序利⽤这个⽹络训练我的⼈脸识别模型,并将最终训练结果保存到本地硬盘。如果对卷积神经⽹络不清楚建议⾃⾏百度!
新建⼀个python⽂件,命名为:face_train。添加如下代码:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论