本帖最后由 云天 于 2021-6-25 07:23 编辑
谷歌出了一个开源的、跨平台的、可定制化的机器学习解决方案工具包,给在线流媒体(当然也可以用于普通的视频、图像等)提供了机器学习解决方案。感兴趣的同学可以打开这个网址了解详情: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()
复制代码
【演示视频】