72755浏览
查看: 72755|回复: 8

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

[复制链接]
本帖最后由 云天 于 2022-5-2 16:39 编辑

【项目背景】
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

【演示视频】


 初级技匠

发表于 2022-5-7 13:28:38

貌似懂了电影里的特效之一~
回复

使用道具 举报

 初级技匠

发表于 2022-5-7 13:31:19

占个板凳  
回复

使用道具 举报

水晶  初级技师

发表于 2022-5-10 16:04:03

666666666666666
回复

使用道具 举报

macCosmo  中级技师

发表于 2022-5-16 11:27:52

666,很科幻
回复

使用道具 举报

盐焗海盐  见习技师

发表于 2022-5-21 13:08:47

6666666666666666666
回复

使用道具 举报

盐焗海盐  见习技师

发表于 2022-5-23 10:37:59

大写的佩服!!!!!
回复

使用道具 举报

大熊小明  学徒

发表于 2022-6-15 16:44:28

666666666666
回复

使用道具 举报

派大星ym  初级技匠

发表于 2022-8-1 13:38:00

,,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail