Python+OpenCV4虹膜识别
前言一次拿到SANSUNG手机解锁发现自带一个黑科技:虹膜解锁(虹膜就是眼睛黑黑的那部分);想起以前看过的未来科技大片里面的片段:搜捕罪犯通过黑匣子识别人们的眼球,只要摄像头扫描到过你的眼睛,你的身份即被确定;哇喔,很炫酷的样子。日前大火的人脸识别技术因为疫情大家都带上了口罩,为了减少直接触碰的风险,指纹识别也在暗淡,虹膜识别正好互补。虽然识别对于戴眼镜尤其是墨镜不太友好,但各识别方法各有利弊吧。
前言
一次拿到SANSUNG手机解锁发现自带一个黑科技:虹膜解锁(虹膜就是眼睛黑黑的那部分);想起以前看过的未来科技大片里面的片段:搜捕罪犯通过黑匣子识别人们的眼球,只要摄像头扫描到过你的眼睛,你的身份即被确定;哇喔,很炫酷的样子。
日前大火的人脸识别技术因为疫情大家都带上了口罩,为了减少直接触碰的风险,指纹识别也在暗淡,虹膜识别正好互补。虽然识别对于戴眼镜尤其是墨镜不太友好,但各识别方法各有利弊吧。
查阅信息的时候发现虹膜包含的信息还对应身体健康知识,博大精深,又是一种很好的发展方向,nice。
话题扯远了,直接上思路和代码
正文
一、思路
- 环境
这里还是采用最简单可上手的OpenCV,(别呛为什么不用YOLO等等标注识别,我像是有闲心搞学术的吗?不是)
环境:python3.9+jupyter notebook+opencv4.5.3 - 下载识别
opencv官网,下载识别用的配置文件https://github.com/opencv/opencv/tree/master/data/haarcascades
这里需要eye眼部检测,意外发现还有eyeglasses戴眼镜的配置文件,强呀强呀!
Tips:怎么快速下载–浏览器打开想要的xml文件,把地址中的
blob改为raw
再保存网页即可,github、gitee通用;
打开:https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_eye.xml
修改后:https://github.com/opencv/opencv/raw/master/data/haarcascades/haarcascade_eye.xml
转换并下载:https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_eye.xml
- haarcascade介绍
Haar分类器,如何训练及原理,可以查看一下这篇参考文章,比较详细。
训练集 | 识别范围 |
---|---|
haarcascade_lefteye_2splits.xml | 可用来检测睁开或闭着的眼睛 |
haarcascade_eye.xml | 仅可以检测睁开的眼睛 |
haarcascade_eye_tree_eyeglasses.xml | 仅在带被检测者戴眼镜时方可检测 |
二、眼睛定位
先识别人脸,在人脸范围内识别眼睛(这里用的opencv自带,可优化为其他方案dlib,yolo等)
import numpy as np
import cv2
from matplotlib import pyplot as plt
def findeyes(path):
face_cascade = cv2.CascadeClassifier('/Users/wangyu/Desktop/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('/Users/wangyu/Desktop/haarcascade_eye.xml')
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 灰度处理
# 人脸识别
face = face_cascade.detectMultiScale(gray, 2, 2) # 参数:1、灰度图片, 2、缩放比例, 3、阈值
print("这张图片中有%d张人脸" % len(face))
for (x, y, w, h) in face:
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 255, 0), 2) # 绘制人脸方框
face_gray = gray[y:y+h, x:x+w]# 在人脸的基础上识别眼睛
face_color = img[y:y+h, x:x+w]
# 眼睛识别
eyes = eye_cascade.detectMultiScale(face_gray)
print("在这张脸上有%d个眼睛" % len(eyes))
for (e_x, e_y, e_w, e_h) in eyes:
cv2.rectangle(face_color, (e_x, e_y), (e_x+e_w, e_y+e_h), (0, 255, 0), 2) # 绘制眼睛方框
roi_color = face_color[e_y:e_y+e_h, e_x:e_x+e_w] #裁剪眼睛框图
#getCircle(roi_color)
plt.figure(figsize=(10,10))
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()
# cv2.imshow('dst', img)
# cv2.waitKey(0)
if __name__=="__main__":
path = '/Users/wangyu/Desktop/lena.jpg'
findeyes(path)
opencv识别结果:
三、虹膜识别
1.图像去干扰
识别到眼睛部分,截取眼睛部分图像,并做干扰处理
- 高斯模糊
高斯矩阵的长与宽都是3,标准差取5;高斯矩阵的尺寸越大,标准差越大,处理过的图像模糊程度越大。 - 二值化
把图像的像素转变为0或者255,只有这两个像素值。0白色 1黑色 - 腐蚀
腐蚀操作 开运算:先腐蚀后膨胀,去除孤立的小点,毛刺 - 膨胀
膨胀操作 闭运算:先膨胀后腐蚀,填平小孔,弥合小裂缝
这里读取的图片为全脸图片,如果是纯眼部图,效果会更好!或许还有更优解,欢迎讨论。
2.检测虹膜
霍夫梯度法检测圆(Canny边缘检测的最大阈值,检测阶段圆心的累加器阈值,最小圆的半径,最大圆的半径)
原理参考
输入参数为(image,method,dp,min_dist,param1,param2,minRadius,maxRadius)
参数 | 描述 |
---|---|
image | 为需要进行霍夫变换的图像 |
method | 为检测方法,一般用CV_HOUGH_GRADIENT,即霍夫梯度法 |
dp | 为检测内侧圆心的累加器图像的分辨率与输入图像之比的倒数。若为1,即累加器和输入图像具有相同的分辨率;若为2,则累加器有输入图像一半的宽度和高度。 |
min_dist | 两个圆之间圆心的最小距离。防止重复画一个圆 |
param1 | 默认值100,为传递给canny边缘检测算子的高阈值,低阈值为其一半 |
param2 | 默认值100,表示在检测阶段圆心的累加器阈值,它越小,表示可以检测到更多不存在的圆,它越大,表示能检测出来的圆越完美 |
minRadius | 默认值0,圆半径的最小值 |
maxRadius | 默认值0,圆半径的最大值 |
完整代码:
import numpy as np
import cv2
from matplotlib import pyplot as plt
def findeyes(path):
face_cascade = cv2.CascadeClassifier('/Users/wangyu/Desktop/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('/Users/wangyu/Desktop/haarcascade_eye.xml')
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 灰度处理
# 人脸识别
face = face_cascade.detectMultiScale(gray, 2, 2) # 参数:1、灰度图片, 2、缩放比例, 3、阈值
print("这张图片中有%d张人脸" % len(face))
for (x, y, w, h) in face:
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 255, 0), 2) # 绘制人脸方框
face_gray = gray[y:y+h, x:x+w]# 在人脸的基础上识别眼睛
face_color = img[y:y+h, x:x+w]
# 眼睛识别
eyes = eye_cascade.detectMultiScale(face_gray)
print("在这张脸上有%d个眼睛" % len(eyes))
for (e_x, e_y, e_w, e_h) in eyes:
cv2.rectangle(face_color, (e_x, e_y), (e_x+e_w, e_y+e_h), (0, 255, 0), 2) # 绘制眼睛方框
roi_color = face_color[e_y:e_y+e_h, e_x:e_x+e_w] #裁剪眼睛框图
# 霍夫圆检测虹膜===
getHoughCircle(roi_color)
plt.figure(figsize=(10,10))
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()
# cv2.imshow('dst', img)
# cv2.waitKey(0)
def getHoughCircle(img):
plt.figure(figsize=(15,15))
plt.subplot(1,4,1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))#BGR转RGB
plt.xlabel(u'img')
blur = cv2.GaussianBlur(img, (3, 3), 5) # 高斯模糊,给出高斯模糊矩阵和标准差
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)# 灰度化
# 图像二值化,全局自适应阈值:对输入的单通道矩阵逐像素进行阈值分割
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE)
kernel = np.ones((3,3),np.uint8)# 设置卷积核3*3
erosion = cv2.erode(binary,kernel)# 图像的腐蚀,默认迭代次数
dst = cv2.dilate(erosion,kernel)# 图像的膨胀
plt.subplot(1,4,2)
plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB))
plt.xlabel(u'gray')
# 霍夫梯度法检测圆(Canny边缘检测的最大阈值,检测阶段圆心的累加器阈值,最小圆的半径,最大圆的半径)
circles = cv2.HoughCircles(dst,cv2.HOUGH_GRADIENT,1,50,param1=100,param2=10,
minRadius=0,maxRadius=200)
img2 = img
if circles is None:
print("未检测到霍夫圆")
else:
for i in circles[0:]:# 遍历矩阵每一行的数据
item = i[0]
# print(item)
# cv2.circle(img2,(int(i[0]),int(i[1])),i[2],(0,255,0),2)
cv2.circle(img2, (int(item[0]), int(item[1])), int(item[2]), (0, 255, 255), 2)
cv2.circle(img2,(int(item[0]),int(item[1])),2,(0,255,255),-1)
#plt.imshow(img[:,:,::-1])
#plt.show()
# 轮廓提取
binaryimg = cv2.Canny(dst, 50, 200) #canny检测轮廓
h = cv2.findContours(dst,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) #寻找轮廓
contours = h[0] #提取轮廓
ret = np.ones(dst.shape, np.uint8) #创建黑色幕布
cv2.drawContours(ret,contours,-1,(255,255,255),1) #绘制白色轮廓
plt.subplot(1,4,3)
plt.imshow(cv2.cvtColor(ret, cv2.COLOR_BGR2RGB))
plt.xlabel(u'line')
plt.subplot(1,4,4)
plt.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
plt.xlabel(u'img2')
plt.show()
if __name__=="__main__":
path = '/Users/wangyu/Desktop/lena.jpg'
findeyes(path)
戴眼镜:
总结
-
lena女神这张图片识别效果意外还挺好的,预期应该没有这么好,为什么没有这么好:a.opencv自带的眼睛识别定位是8 years ago的训练样本了,鲁棒性不够好,会把部分图片的嘴巴也识别为眼睛;如果在yolo标注训练,嘴巴要作为负样本训练。b.图像去干扰:如果不是纯眼部图,干扰会很大。c.没有好的二值化区域,霍夫梯度法类圆检测效果也不好。
a.类opencv误判,识别不到人脸或眼睛识别错误,不过派派的脸是真符合检测标准,检测正确的霍夫圆可以说是非常完美。
b.c.类,当眼型很圆时,霍夫圆的检测效果不太理想,或许可以用其他方法内接圆来判断,momo的笑眼,嘻!
-
其他很好的思路:参考思路1,这篇文章的思路也很好,不过对于眼部取样的要求还是很高,具体情况具体应用。
说了这么多,实现的效果普遍性不高,还有必要研究吗?有必要的,虹膜识别的应用性还是很广;对于戴眼镜的识别优化,虹膜信息提取等等。
图片均来源网络,仅学习使用
更多推荐
所有评论(0)