Python OpenCv实现实时人脸识别和人脸距离测量
Python OpenCv实现实时人脸识别和人脸测距
准备
在开发面部测距之前,首先在你的 Python 中安装四个库,分别是 cvzone 库、mediapipe 库、tensorflow 库和 tensorflow GPU 库。安装 cvzone 库和 mediapipe 库更快。直接使用下面的语句就可以快速安装
点安装 cvzone
点安装媒体管道
在安装tensorflow库和tensorflow GPU库时,由于库文件较大,常规的安装方法经常会下载到一半失败。这里推荐使用以下命令。我自己测试过,可以快速安装。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tensorflow
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tensorflow-gpu
确保以上四个库都安装成功后,就可以开始写代码了。
原则
OpenCv主要利用相似三角形原理实现人脸测距,如下图

参数说明:
(1)相机的焦距f是固定的;
(2) W是相机成像后人眼的像素距离。通过findFaceMesh()识别人脸网格后可以测量人眼的像素距离w;
(3) W是现实中左眼和右眼之间的距离。男性的平均瞳距为 64 毫米,女性为 62 毫米。本项目开发取中间值63mm;
(4) d 是您想要获取的从实际人到相机的距离。通过相似三角形原理,将公式变换后可以计算出人到相机的距离公式:du003d(f*W)/w
笔记:
不同的相机有不同的焦距。如果您知道相机本身的参数是最好的,您可以直接替换它们进行精确计算。如果不知道相机参数,需要多次手动校正确定焦距f。手动校正需要多测量几个数据,然后计算平均值以保证焦距f的准确性,从而提高测距精度。手动校正,先固定眼睛到相机的距离,比如50cm,用卷尺准确测量,多测几次,找到焦距F。测量焦距f的具体代码如下图:
导入 cv2
导入 cvzone
from cvzone.FaceMeshModule import FaceMeshDetector #导入检测器
##这里是导入相机
上限 u003d cv2.VideoCapture(0)
detector u003d FaceMeshDetector(maxFaces u003d 1) #检测人脸,只检测一张人脸。最后1表示最多只能检测到一张人脸
当真:
成功,img u003d cap.read()
img,faces u003ddetector.findFaceMesh(img,draw u003d False) #找到人脸后,返回人脸u003dfalse
if faces: #如果面孔可用
##通过下面的语句找到左眼和右眼的两个点
face u003d faces[0] #第一阶段
pointLeft u003d face[145] #左边的值基本是145
pointRight u003d face[374] #右边的值基本都是374
###以下是寻找焦距的过程
##以像素为单位查找距离
w,_ u003ddetector.findDistance(pointLeft,pointRight) #将左眼点位置到右眼点位置的距离赋值给w,w后面的下划线忽略其他值
W u003d 6.3 #这是人眼左右眼的距离,即63mm。取中间值,男性为64mm,女性为62mm
d u003d 50 #距离假设为50cm
f u003d (w * d) / W #将焦距公式代入
打印(女)
cv2.imshow("图像",img)
cv2.waitKey(1)
通过上面的代码多次测量焦距f,求平均值。我使用的相机焦距是300,所以后面我的代码中f u003d 300。在这里,根据我的实际焦距代替测量。接下来将焦距f代入测量公式d u003d (f*W) / w,具体代码如下图:
导入 cv2
导入 cvzone
from cvzone.FaceMeshModule import FaceMeshDetector #导入检测器
##这里是导入相机
上限 u003d cv2.VideoCapture(0)
detector u003d FaceMeshDetector(maxFaces u003d 1) #人脸检测
当真:
成功,img u003d cap.read()
img,faces u003ddetector.findFaceMesh(img,draw u003d False) #做一个检测器,找到人脸网格,返回图片(img)和我们的人脸。画u003d假。有了这句话,我们就看不到网格了
if faces: #如果面孔可用
##通过下面的语句找到左眼和右眼的两个点
face u003d faces[0] #第一阶段
pointLeft u003d face[145] #左边的值基本是145
pointRight u003d face[374] #右边的值基本都是374
##这里是眼睛两点之间的距离
cv2.line(img, pointLeft, pointRight, (0, 200, 0), 3) # 在眼睛的两点之间画一条线。起点是pointLeft,终点是pointRight。线条颜色为绿色,线条宽度为3
cv2.circle(img,pointLeft,5,(255,0,255),cv2.FILLED) #在img图像上画一个圆。中心点为pointLeft,半径为5,颜色为紫色。最终运行结果可以在成像仪左眼标记紫点
cv2.circle(img,pointRight,5,(255,0,255),cv2.FILLED) #在img图像上画一个圆。中心点为pointRighe,半径为5,颜色为紫色。最终运行结果可以在成像仪右眼标出紫点
w, _ u003ddetector.findDistance(pointLeft, pointRight) # 赋值左眼点位置到右眼点位置到w的距离,w后面的下划线忽略其他值
W u003d 6.3 #这是人眼左右眼的距离,即63mm。取中间值,男性为64mm,女性为62mm
###查找距离
##根据上式f u003d (w * d) / W,可以粗略测出,人眼距离相机50cm时,相机焦距约为300
##然后将找到的焦距代入距离计算公式,即可计算出距离
f u003d 300
d u003d (W * f) / w
打印(d)
##下面是距离的文字,跟随着人脸,在额头位置输出
cvzone.putTextRect(img,f'深度:{int(d)}cm',(面[10][0]-95,面[10][1]-5), scale u003d 1.8) #距离文字以字符串的形式显示在图像上,单位为cm。文字值的位置随着人脸的移动显示在额头上(额头上的id为10,即人脸[10],下面的人脸[10][0]表示第一个元素,face[10][1] 表示第二个元素),
上面的##scale u003d 2表示图片上输出文本框的大小
##face[10][0]左右改变,face[10][1]改变显示高度
cv2.imshow("图像",img)
cv2.waitKey(1)
最终测试结果如下:

多人同时测距见以下代码。我还没有优化它。多人同时测距时,会浮动,不稳定。
导入 cv2
导入 cvzone
from cvzone.FaceMeshModule import FaceMeshDetector #导入检测器
##这里是导入相机
上限 u003d cv2.VideoCapture(0)
检测器 u003d FaceMeshDetector(maxFacesu003d3)
当真:
成功,img u003d cap.read()
img,faces1 u003d 检测器.findFaceMesh(img)
img,faces2 u003d 检测器.findFaceMesh(img)
img,faces3 u003d 检测器.findFaceMesh(img)
W u003d 6.3 #这是人眼左右眼的距离,即63mm。取中间值,男性为64mm,女性为62mm
if faces1: #如果检测到人脸
面1 u003d 面1[0]
pointLeft1 u003d face1[145] #左眼的人脸值为145
pointRight1 u003d face1[374] #右眼的人脸值为374
##这里是两只眼睛的距离
cv2.line(img,pointLeft1,pointRight1,(0,200,0),3) #眼睛里
cv2.circle(img,pointLeft1,5,(255,0,255),cv2.FILLED) #在img图像上画一个圆,圆心为pointLeft,半径为5,颜色为紫色
#cv2.circle(img,pointRight1,5,(255,0,255),cv2.FILLED) #在img图像上画一个圆,中心点为pointRight,半径为5,颜色为紫色
w1, _ u003ddetector.findDistance(pointLeft1, pointRight1) # 将第一张脸的左眼到右眼的位置距离赋值给w1。 w1 后面的下划线表示忽略其他值
###查找距离
##根据上式f u003d (w * d) / W,可以粗略测出,人眼距离相机50cm时,相机焦距约为300
##然后将找到的焦距代入距离计算公式,即可计算出距离
f u003d 300
d1 u003d (W * f) / w1
cvzone.putTextRect(img, f'Depth:{int(d1)}cm', (face1[10][0] - 95, face1[10][1] - 5),比例 u003d 1.8)
if faces2: ##这表示当第一个面被测试时,如果第二个面再次出现,就会显示标记
面2 u003d 面2[0]
pointLeft2 u003d face2[145] # 左眼的人脸值为145
pointRight2 u003d face2[374] # 右眼的人脸值为374
#cv2.line(img, pointLeft2, pointRight2, (0, 200, 0), 3) # 眼睛里
cv2.circle(img, pointLeft2, 5, (255, 0, 255), cv2.FILLED) # 在img图像上画一个圆,中心点为pointLeft,半径为5,颜色为紫色
cv2.circle(img, pointRight2, 5, (255, 0, 255), cv2.FILLED) # 在img图像上画一个圆,中心点为pointRight,半径为5,颜色为紫色
w2,_ u003ddetector.findDistance(pointLeft2,pointRight2) #将第一张脸的左眼到右眼的位置距离赋值给w1。 w1 后面的下划线表示忽略其他值
###查找距离
##根据上式f u003d (w * d) / W,可以粗略测出,人眼距离相机50cm时,相机焦距约为300
##然后将找到的焦距代入距离计算公式,即可计算出距离
f u003d 300
d2 u003d (W * f) / w2
cvzone.putTextRect(img, f'Depth:{int(d2)}cm', (face2[10][0] - 95, face2[10][1] - 5),规模u003d1.8)
如果面临3:
面3 u003d 面3[0]
pointLeft3 u003d face3[145] #左眼的人脸值为145
pointRight3 u003d face3[374] # 右眼的人脸值为374
cv2.line(img, pointLeft3, pointRight3, (0, 200, 0), 3) # 眼睛里
cv2.circle(img, pointLeft3, 5, (255, 0, 255), cv2.FILLED) # 在img图像上画一个圆,中心点为pointLeft,半径为5,颜色为紫色
cv2.circle(img, pointRight3, 5, (255, 0, 255), cv2.FILLED) # 在img图像上画一个圆,中心点为pointRight,半径为5,颜色为紫色
w3, _ u003ddetector.findDistance(pointLeft3, pointRight3) # 将第一张脸的左眼到右眼的位置距离赋值给w1。 w1 后面的下划线表示忽略其他值
###查找距离
##根据上式f u003d (w * d) / W,可以粗略测出,人眼距离相机50cm时,相机焦距约为300
##然后将找到的焦距代入距离计算公式,即可计算出距离
f u003d 300
d3 u003d (W * f) / w2
cvzone.putTextRect(img, f'Depth:{int(d3)}cm', (face3[10][0] - 95, face3[10][1] - 5),规模u003d1.8)
cv2.imshow("img",img)
cv2.waitKey(1)
以上就是通过Python OpenCv实现人脸识别和人脸测距的过程。祝所有研究人员文章多,脱发少!
更多推荐

所有评论(0)