树莓派电容式触摸屏试用——瞳孔跟踪

2022-05-027.7万
精华项目
AI 快速预览详细 收起
本文介绍了如何使用树莓派5寸TFT电容式触摸屏进行瞳孔跟踪。首先通过MediaPipe的人脸landmark数据获取468个点位的人脸点云数据,筛选出左眼与右眼所在的区域所有点,然后使用OpenCV的cv2.findContours方法实现瞳孔的识别与跟踪。文章提供了详细的程序代码和硬件连接方式,并附有测试图片和演示视频。


【项目背景】
4月份获得了试用树莓派5寸TFT电容式触摸屏的机会,到手后,因工作原因,一直没有去过。这两天有点时间,看了一下Mediapipe官网,发现了“MediaPipe Iris”功能,
树莓派电容式触摸屏试用——瞳孔跟踪图1

可惜,MediaPipe SDK的 python版本是不支持虹膜检测。
这个难不住我。


【项目设计】
先通过MediaPipe的人脸landmark提供了468个点位的人脸点云数据,
树莓派电容式触摸屏试用——瞳孔跟踪图2
根据编号,很容筛选出左眼与右眼所在的区域所有点,然后完成区域的截取。

树莓派电容式触摸屏试用——瞳孔跟踪图3
再使用Opencv的cv2.findContours实现瞳孔识别与跟踪。

【程序代码】
1、加载Mediapipe和OpenCV库
  1. import cv2 as cv2
  2. import  mediapipe as mp
  3. import numpy as np
复制代码
2、人脸landmark检测代码如下:
  1. # 导入可视化函数和可视化样式
  2. mp_drawing=mp.solutions.drawing_utils
  3. #mp_drawing_styles=mp.solutions.drawing_styles
  4. # 导入三维人脸关键点检测模型
  5. mp_face_mesh=mp.solutions.face_mesh
  6. drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
  7. cap = cv2.VideoCapture(0)
  8. with mp_face_mesh.FaceMesh(
  9.     max_num_faces=4,
  10.     min_detection_confidence=0.5,
  11.     min_tracking_confidence=0.5) as face_mesh:
  12.   while cap.isOpened():
  13.     success, frame = cap.read()
  14.     if not success:
  15.       print("Ignoring empty camera frame.")
  16.       # If loading a video, use 'break' instead of 'continue'.
  17.       break
  18.     h, w, c = frame.shape
  19.     # image = cv2.resize(frame, (w //2, h//2))
  20.     # frame = cv2.flip(frame, 1)
  21.     image = np.copy(frame)
  22.     h2, w2, c2 = image.shape
  23.     # To improve performance, optionally mark the image as not writeable to
  24.     # pass by reference.
  25.     image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  26.     results = face_mesh.process(image)
  27.     # Draw the face mesh annotations on the image.
  28.     image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
  29.     left_eyes = []
  30.     right_eyes = []
  31.     if results.multi_face_landmarks:
  32.       for face_landmarks in results.multi_face_landmarks:
  33.         for idx, landmark in enumerate(face_landmarks.landmark):
  34.          
  35.           if idx == 246 or idx == 159 or idx == 158  or idx == 145 or idx == 153 or idx == 190:  # left
  36.           #if idx == 53 or idx == 111:  # left
  37.             x1 = np.int(landmark.x * w2)
  38.             y1 = np.int(landmark.y * h2)
  39.             left_eyes.append((x1, y1))
  40.             #cv2.circle(image, (x1, y1), 4, (255, 0, 255), 4, cv2.LINE_AA)
  41.           if idx ==374 or idx == 380  or idx == 385 or idx == 386 or idx == 390  or idx == 414: # right
  42.           #if idx == 276 or idx == 340: # right
  43.             x1 = np.int(landmark.x * w2)
  44.             y1 = np.int(landmark.y * h2)
  45.             right_eyes.append((x1, y1))
  46.             #cv2.circle(image, (x1, y1), 4, (0, 255, 255), 4, cv2.LINE_AA)
  47.         if len(right_eyes)+len(left_eyes)==12:
  48.          #矩形边框(Bounding Rectangle)是说,用一个最小的矩形,把找到的形状包起来。  
  49.          right_box = cv2.boundingRect(np.asarray(right_eyes))
  50.         
  51.          left_box = cv2.boundingRect(np.asarray(left_eyes))
  52.          
  53.          detect_iris(image, right_box, left_box)
  54.     cv2.imshow('MediaPipe Face Mesh', image)
  55.     if cv2.waitKey(5) & 0xFF == 27:
  56.       cv2.imwrite("D:/iris_detect_result.png", image)
  57.       break
  58. cap.release()
  59. cv2.waitKey(0)
  60. cv2.destroyAllWindows()
复制代码


3、虹膜l检测代码如下:
  1. def detect_iris(image, right_box, left_box):
  2.    
  3.   left_roi = image[left_box[1]:left_box[1] + left_box[3], left_box[0]:left_box[0] + left_box[2]]
  4.   cv2.imshow('left_eye', left_roi)
  5.   lh, lw, lc = left_roi.shape
  6.   right_roi = image[right_box[1]:right_box[1]+right_box[3],right_box[0]:right_box[0]+right_box[2]]
  7.   cv2.imshow('right_eye', right_roi)
  8.   rh, rw, rc = right_roi.shape
  9.   if rh>0 and lh>0:
  10.     rows, cols, _ =right_roi.shape   #保存视频尺寸以备用
  11.     gray_roi = cv2.cvtColor(right_roi, cv2.COLOR_BGR2GRAY)   #转灰度
  12.     gray_roi = cv2.GaussianBlur(gray_roi, (7, 7), 0)    #高斯滤波一次
  13.     _, threshold = cv2.threshold(gray_roi, 30, 255, cv2.THRESH_BINARY_INV)  #二值化,依据需要改变阈值
  14.     contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #画连通域
  15.     contours = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True)
  16.     for cnt in contours:
  17.         (x, y, w, h) = cv2.boundingRect(cnt)
  18.         cv2.circle(right_roi, (x + int(w/2), y + int(h/2)), int(h/2), (0, 0, 255), 3)
  19.         break
  20.     rows, cols, _ =left_roi.shape   #保存视频尺寸以备用
  21.     gray_roi = cv2.cvtColor(left_roi, cv2.COLOR_BGR2GRAY)   #转灰度
  22.     gray_roi = cv2.GaussianBlur(gray_roi, (7, 7), 0)    #高斯滤波一次
  23.     _, threshold = cv2.threshold(gray_roi, 30, 255, cv2.THRESH_BINARY_INV)  #二值化,依据需要改变阈值
  24.     contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #画连通域
  25.     contours = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True)
  26.     for cnt in contours:
  27.         (x, y, w, h) = cv2.boundingRect(cnt)
  28.         cv2.circle(left_roi, (x + int(w/2), y + int(h/2)), int(h/2), (0, 0, 255), 3)
  29.         break
复制代码

【硬件连接】
树莓派电容式触摸屏试用——瞳孔跟踪图4
【测试图片】
树莓派电容式触摸屏试用——瞳孔跟踪图5

树莓派电容式触摸屏试用——瞳孔跟踪图6

树莓派电容式触摸屏试用——瞳孔跟踪图7

【演示视频】


创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(8)
派大星ym
派大星ym
,,
大熊小明
大熊小明
666666666666
盐焗海盐
盐焗海盐
大写的佩服!!!!!
盐焗海盐
盐焗海盐
6666666666666666666
macCosmo
macCosmo
666,很科幻
水晶
水晶
666666666666666
诩
占个板凳
诩
貌似懂了电影里的特效之一~
- 没有更多了 -