当前位置 博文首页 > cungudafa的博客:Python+OpenCV4虹膜识别
一次拿到SANSUNG手机解锁发现自带一个黑科技:虹膜解锁(虹膜就是眼睛黑黑的那部分);想起以前看过的未来科技大片里面的片段:搜捕罪犯通过黑匣子识别人们的眼球,只要摄像头扫描到过你的眼睛,你的身份即被确定;哇喔,很炫酷的样子。
日前大火的人脸识别技术因为疫情大家都带上了口罩,为了减少直接触碰的风险,指纹识别也在暗淡,虹膜识别正好互补。虽然识别对于戴眼镜尤其是墨镜不太友好,但各识别方法各有利弊吧。
查阅信息的时候发现虹膜包含的信息还对应身体健康知识,博大精深,又是一种很好的发展方向,nice。
话题扯远了,直接上思路和代码
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_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识别结果:
识别到眼睛部分,截取眼睛部分图像,并做干扰处理
这里读取的图片为全脸图片,如果是纯眼部图,效果会更好!或许还有更优解,欢迎讨论。
霍夫梯度法检测圆(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,(