谷歌出了一个开源的、跨平台的、可定制化的机器学习解决方案工具包,给在线流媒体(当然也可以用于普通的视频、图像等)提供了机器学习解决方案。感兴趣的同学可以打开这个网址了解详情:mediapipe.dev/
它提供了手势、人体姿势、人脸、物品等识别和追踪功能,并提供了C++、Python、JavaScript等编程语言的工具包以及iOS、Android平台的解决方案,今天我们就来看一下如何使用MediaPipe提供的MediaPipe 面网格来写一个Python代码识别眨眼、张闭嘴来控制Arduino板上RGB灯带。【MediaPipe 面网格】
MediaPipe Face Mesh 是一种面部几何解决方案,即使在移动设备上也能实时估计 468 个 3D 面部标志。它采用机器学习 (ML) 来推断 3D 表面几何形状,只需要一个摄像头输入,无需专用深度传感器。该解决方案在整个管道中利用轻量级模型架构和 GPU 加速,提供对实时体验至关重要的实时性能。
【Mind+MediaPipe 面网格】
在Mind+的Python模式中,通过“库管理”中PIP模式安装”mediapipe“
【标识468个面部标志】
-
- import cv2
- import time
- import mediapipe as mp
- mp_drawing = mp.solutions.drawing_utils
- mp_face_mesh = mp.solutions.face_mesh
- from pinpong.board import Board,Pin,NeoPixel
- NEOPIXEL_PIN = Pin.D7
- PIXELS_NUM = 7 #灯数
- Board("uno").begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
- np = NeoPixel(Pin(NEOPIXEL_PIN), PIXELS_NUM)
- # For webcam input:
- drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
- cap = cv2.VideoCapture(0)
- Width=cap.get(3)
- Height=cap.get(4)
- i=1
- with mp_face_mesh.FaceMesh(
- min_detection_confidence=0.5,
- min_tracking_confidence=0.5) as face_mesh:
- while cap.isOpened():
- success, image = cap.read()
- if not success:
- print("Ignoring empty camera frame.")
- # If loading a video, use 'break' instead of 'continue'.
- continue
-
- # Flip the image horizontally for a later selfie-view display, and convert
- # the BGR image to RGB.
- image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
- # To improve performance, optionally mark the image as not writeable to
- # pass by reference.
- image.flags.writeable = False
- results = face_mesh.process(image)
-
- # Draw the face mesh annotations on the image.
- image.flags.writeable = True
- image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
- if results.multi_face_landmarks:
- for face_landmarks in results.multi_face_landmarks:
- mp_drawing.draw_landmarks(
- image=image,
- landmark_list=face_landmarks,
- connections=mp_face_mesh.FACE_CONNECTIONS,
- landmark_drawing_spec=drawing_spec,
- connection_drawing_spec=drawing_spec)
-
- up=results.multi_face_landmarks[0].landmark[13]
- down=results.multi_face_landmarks[0].landmark[14]
- cv2.circle(image,(int(up.x*Width),int(up.y*Height)),4,(255,0,0),-1)
- cv2.circle(image,(int(down.x*Width),int(down.y*Height)),4,(255,0,0),-1)
- for i in range(0,468):#标记468个3D 面部标志。
- text=results.multi_face_landmarks[0].landmark[i]
- cv2.putText(image, str(i), (int(text.x*Width),int(text.y*Height)),cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255, 0, 0), 1)
- print(abs(down.y-up.y)*Height)
- if(abs(down.y-up.y)*Height)>20:
- for num in range(0,7):
- np[num]=(255,0,0)
- else:
- for num in range(0,7):
- np[num]=(0,0,0)
- cv2.imshow('MediaPipe FaceMesh', image)
- if cv2.waitKey(5) & 0xFF == 27:
- break
- cap.release()
复制代码

【张嘴请开灯】
up=results.multi_face_landmarks[0].landmark[13]
down=results.multi_face_landmarks[0].landmark[14]
13和14在一个在上嘴唇,一个在下嘴唇,利用两个标识点的纵坐标的差值来判断是否张嘴。
【睁眼请开灯】
up=results.multi_face_landmarks[0].landmark[159]
down=results.multi_face_landmarks[0].landmark[145]
159与145标识点在右眼的上眼睑和下眼睑。 -
- import cv2
- import time
- import mediapipe as mp
- mp_drawing = mp.solutions.drawing_utils
- mp_face_mesh = mp.solutions.face_mesh
- from pinpong.board import Board,Pin,NeoPixel
- NEOPIXEL_PIN = Pin.D7
- PIXELS_NUM = 7 #灯数
- Board("uno").begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
- np = NeoPixel(Pin(NEOPIXEL_PIN), PIXELS_NUM)
- # For webcam input:
- drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
- cap = cv2.VideoCapture(0)
- Width=cap.get(3)
- Height=cap.get(4)
- i=1
- with mp_face_mesh.FaceMesh(
- min_detection_confidence=0.5,
- min_tracking_confidence=0.5) as face_mesh:
- while cap.isOpened():
- success, image = cap.read()
- if not success:
- print("Ignoring empty camera frame.")
- # If loading a video, use 'break' instead of 'continue'.
- continue
-
- # Flip the image horizontally for a later selfie-view display, and convert
- # the BGR image to RGB.
- image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
- # To improve performance, optionally mark the image as not writeable to
- # pass by reference.
- image.flags.writeable = False
- results = face_mesh.process(image)
-
- # Draw the face mesh annotations on the image.
- image.flags.writeable = True
- image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
- if results.multi_face_landmarks:
- for face_landmarks in results.multi_face_landmarks:
- mp_drawing.draw_landmarks(
- image=image,
- landmark_list=face_landmarks,
- connections=mp_face_mesh.FACE_CONNECTIONS,
- landmark_drawing_spec=drawing_spec,
- connection_drawing_spec=drawing_spec)
-
- up=results.multi_face_landmarks[0].landmark[159]
- down=results.multi_face_landmarks[0].landmark[145]
- cv2.circle(image,(int(up.x*Width),int(up.y*Height)),4,(255,0,0),-1)
- cv2.circle(image,(int(down.x*Width),int(down.y*Height)),4,(255,0,0),-1)
- #for i in range(0,468):#标记468个3D 面部标志。
- #text=results.multi_face_landmarks[0].landmark[i]
- #cv2.putText(image, str(i), (int(text.x*Width),int(text.y*Height)),cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255, 0, 0), 1)
- print(abs(down.y-up.y)*Height)
- if(abs(down.y-up.y)*Height)>8:
- for num in range(0,7):
- np[num]=(255,0,0)
- else:
- for num in range(0,7):
- np[num]=(0,0,0)
- cv2.imshow('MediaPipe FaceMesh', image)
- if cv2.waitKey(5) & 0xFF == 27:
- break
- cap.release()
复制代码

【演示视频】
|