本帖最后由 云天 于 2022-5-2 16:39 编辑
【项目背景】
4月份获得了试用树莓派5寸TFT电容式触摸屏的机会,到手后,因工作原因,一直没有去过。这两天有点时间,看了一下Mediapipe官网,发现了“MediaPipe Iris”功能,
可惜,MediaPipe SDK的 python版本是不支持虹膜检测。
这个难不住我。
【项目设计】
先通过MediaPipe的人脸landmark提供了468个点位的人脸点云数据,
根据编号,很容筛选出左眼与右眼所在的区域所有点,然后完成区域的截取。
再使用Opencv的cv2.findContours实现瞳孔识别与跟踪。
【程序代码】
1、加载Mediapipe和OpenCV库
- import cv2 as cv2
- import mediapipe as mp
- import numpy as np
复制代码
2、人脸landmark检测代码如下:
-
- # 导入可视化函数和可视化样式
- mp_drawing=mp.solutions.drawing_utils
- #mp_drawing_styles=mp.solutions.drawing_styles
- # 导入三维人脸关键点检测模型
- mp_face_mesh=mp.solutions.face_mesh
- drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
- cap = cv2.VideoCapture(0)
- with mp_face_mesh.FaceMesh(
- max_num_faces=4,
- min_detection_confidence=0.5,
- min_tracking_confidence=0.5) as face_mesh:
- while cap.isOpened():
- success, frame = cap.read()
- if not success:
- print("Ignoring empty camera frame.")
- # If loading a video, use 'break' instead of 'continue'.
- break
-
- h, w, c = frame.shape
- # image = cv2.resize(frame, (w //2, h//2))
- # frame = cv2.flip(frame, 1)
- image = np.copy(frame)
- h2, w2, c2 = image.shape
- # To improve performance, optionally mark the image as not writeable to
- # pass by reference.
- image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
- results = face_mesh.process(image)
-
- # Draw the face mesh annotations on the image.
- image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
- left_eyes = []
- right_eyes = []
- if results.multi_face_landmarks:
- for face_landmarks in results.multi_face_landmarks:
- for idx, landmark in enumerate(face_landmarks.landmark):
-
- if idx == 246 or idx == 159 or idx == 158 or idx == 145 or idx == 153 or idx == 190: # left
- #if idx == 53 or idx == 111: # left
- x1 = np.int(landmark.x * w2)
- y1 = np.int(landmark.y * h2)
- left_eyes.append((x1, y1))
- #cv2.circle(image, (x1, y1), 4, (255, 0, 255), 4, cv2.LINE_AA)
- if idx ==374 or idx == 380 or idx == 385 or idx == 386 or idx == 390 or idx == 414: # right
- #if idx == 276 or idx == 340: # right
- x1 = np.int(landmark.x * w2)
- y1 = np.int(landmark.y * h2)
- right_eyes.append((x1, y1))
- #cv2.circle(image, (x1, y1), 4, (0, 255, 255), 4, cv2.LINE_AA)
- if len(right_eyes)+len(left_eyes)==12:
- #矩形边框(Bounding Rectangle)是说,用一个最小的矩形,把找到的形状包起来。
- right_box = cv2.boundingRect(np.asarray(right_eyes))
-
- left_box = cv2.boundingRect(np.asarray(left_eyes))
-
- detect_iris(image, right_box, left_box)
- cv2.imshow('MediaPipe Face Mesh', image)
- if cv2.waitKey(5) & 0xFF == 27:
- cv2.imwrite("D:/iris_detect_result.png", image)
- break
- cap.release()
- cv2.waitKey(0)
- cv2.destroyAllWindows()
复制代码
3、虹膜l检测代码如下:
-
- def detect_iris(image, right_box, left_box):
-
- left_roi = image[left_box[1]:left_box[1] + left_box[3], left_box[0]:left_box[0] + left_box[2]]
- cv2.imshow('left_eye', left_roi)
- lh, lw, lc = left_roi.shape
- right_roi = image[right_box[1]:right_box[1]+right_box[3],right_box[0]:right_box[0]+right_box[2]]
- cv2.imshow('right_eye', right_roi)
- rh, rw, rc = right_roi.shape
- if rh>0 and lh>0:
- rows, cols, _ =right_roi.shape #保存视频尺寸以备用
- gray_roi = cv2.cvtColor(right_roi, cv2.COLOR_BGR2GRAY) #转灰度
- gray_roi = cv2.GaussianBlur(gray_roi, (7, 7), 0) #高斯滤波一次
- _, threshold = cv2.threshold(gray_roi, 30, 255, cv2.THRESH_BINARY_INV) #二值化,依据需要改变阈值
- contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #画连通域
- contours = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True)
-
- for cnt in contours:
- (x, y, w, h) = cv2.boundingRect(cnt)
- cv2.circle(right_roi, (x + int(w/2), y + int(h/2)), int(h/2), (0, 0, 255), 3)
- break
-
- rows, cols, _ =left_roi.shape #保存视频尺寸以备用
- gray_roi = cv2.cvtColor(left_roi, cv2.COLOR_BGR2GRAY) #转灰度
- gray_roi = cv2.GaussianBlur(gray_roi, (7, 7), 0) #高斯滤波一次
- _, threshold = cv2.threshold(gray_roi, 30, 255, cv2.THRESH_BINARY_INV) #二值化,依据需要改变阈值
- contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #画连通域
- contours = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True)
-
- for cnt in contours:
- (x, y, w, h) = cv2.boundingRect(cnt)
- cv2.circle(left_roi, (x + int(w/2), y + int(h/2)), int(h/2), (0, 0, 255), 3)
- break
复制代码
【硬件连接】
【测试图片】
【演示视频】
|