Welcome to NUWA-HP60C Depth Camera repository
4.Face Mesh
4. FaceMesh
4.1. Introduction
MediaPipe is an open-source data stream processing machine learning application development framework developed by Google. It is a graph-based data processing pipeline used to build data sources in various forms, such as video, audio, sensor data, and any time series data. MediaPipe is cross-platform and can run on embedded platforms (such as Raspberry Pi), mobile devices (iOS and Android), workstations and servers, and supports mobile GPU acceleration. MediaPipe provides cross-platform, customizable ML solutions for real-time and streaming media. The core framework of MediaPipe is implemented in C++ and provides support for languages such as Java and Objective C. The main concepts of MediaPipe include packets, streams, calculators, graphs, and subgraphs.
Features of MediaPipe:
- End-to-end acceleration: built-in fast ML inference and processing can be accelerated even on ordinary hardware.
- Build once, deploy anywhere: unified solution for Android, iOS, desktop/cloud, web and IoT.
- Ready-to-use solution: cutting-edge ML solution that demonstrates the full capabilities of the framework.
- Free and open source: framework and solution under Apache2.0, fully extensible and customizable.
4.2, Dlib
DLIB is a modern C++ toolkit that contains machine learning algorithms and tools for creating complex software in C++ to solve real-world problems. It is widely used by industry and academia in fields such as robotics, embedded devices, mobile phones and large high-performance computing environments. The dlib library uses 68 points to mark important parts of the face, such as 18-22 points mark the right eyebrow, 51-68 marks the mouth. Use the get_frontal_face_detector module of the dlib library to detect faces, and use the shape_predictor_68_face_landmarks.dat feature data to predict facial feature values.

4.3, FaceMesh
4.3.1, Start
Start the camera
roslaunch ascamera hp60c.launch
Terminal input,
xxxxxxxxxxroslaunch yahboomcar_mediapipe 04_FaceMesh.launch

4.3.2, Source code
Source code location: /home/yahboom/ascam_ws/src/yahboomcar_mediapipe/scripts/04_FaceMesh.py
x#!/usr/bin/env python3# encoding: utf-8import timeimport rospyimport cv2 as cvimport numpy as npimport mediapipe as mpfrom geometry_msgs.msg import Pointfrom yahboomcar_msgs.msg import PointArrayfrom sensor_msgs.msg import Imagefrom cv_bridge import CvBridgeclass FaceMesh: def __init__(self, staticMode=False, maxFaces=2, minDetectionCon=0.5, minTrackingCon=0.5): self.mpDraw = mp.solutions.drawing_utils self.mpFaceMesh = mp.solutions.face_mesh self.faceMesh = self.mpFaceMesh.FaceMesh( static_image_mode=staticMode, max_num_faces=maxFaces, min_detection_confidence=minDetectionCon, min_tracking_confidence=minTrackingCon ) self.pub_point = rospy.Publisher('/mediapipe/points', PointArray, queue_size=1000) self.lmDrawSpec = mp.solutions.drawing_utils.DrawingSpec(color=(0, 0, 255), thickness=-1, circle_radius=3) self.drawSpec = self.mpDraw.DrawingSpec(color=(0, 255, 0), thickness=1, circle_radius=1) self.bridge = CvBridge() self.sub_image = rospy.Subscriber('/ascamera_hp60c/rgb0/image', Image, self.image_callback, queue_size=1) self.pTime = 0 def pubFaceMeshPoint(self, frame, draw=True): pointArray = PointArray() img = np.zeros(frame.shape, np.uint8) imgRGB = cv.cvtColor(frame, cv.COLOR_BGR2RGB) self.results = self.faceMesh.process(imgRGB) if self.results.multi_face_landmarks: for i in range(len(self.results.multi_face_landmarks)): if draw: self.mpDraw.draw_landmarks(frame, self.results.multi_face_landmarks[i], self.mpFaceMesh.FACEMESH_CONTOURS, self.lmDrawSpec, self.drawSpec) self.mpDraw.draw_landmarks(img, self.results.multi_face_landmarks[i], self.mpFaceMesh.FACEMESH_CONTOURS, self.lmDrawSpec, self.drawSpec) for id, lm in enumerate(self.results.multi_face_landmarks[i].landmark): point = Point() point.x, point.y, point.z = lm.x, lm.y, lm.z pointArray.points.append(point) self.pub_point.publish(pointArray) return frame, img def frame_combine(slef,frame, src): if len(frame.shape) == 3: frameH, frameW = frame.shape[:2] srcH, srcW = src.shape[:2] dst = np.zeros((max(frameH, srcH), frameW + srcW, 3), np.uint8) dst[:, :frameW] = frame[:, :] dst[:, frameW:] = src[:, :] else: src = cv.cvtColor(src, cv.COLOR_BGR2GRAY) frameH, frameW = frame.shape[:2] imgH, imgW = src.shape[:2] dst = np.zeros((frameH, frameW + imgW), np.uint8) dst[:, :frameW] = frame[:, :] dst[:, frameW:] = src[:, :] return dst def image_callback(self, msg): try: # Convert ROS image messages to OpenCV images frame = self.bridge.imgmsg_to_cv2(msg, desired_encoding="bgr8") # Process images and publish keypoints frame, img = self.pubFaceMeshPoint(frame, draw=True) # Calculate and display frame rate cTime = time.time() fps = 1 / (cTime - self.pTime) self.pTime = cTime text = "FPS : " + str(int(fps)) cv.putText(frame, text, (20, 30), cv.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2) # Merge and display images dst = self.frame_combine(frame, img) cv.imshow('dst', dst) # Check for 'q' key pressed to quit if cv.waitKey(1) & 0xFF == ord('q'): rospy.signal_shutdown("User requested shutdown") except Exception as e: rospy.logerr("Could not process image: %s" % e)if __name__ == '__main__': rospy.init_node('FaceMesh', anonymous=True) face_mesh = FaceMesh(maxFaces=2) rospy.spin() cv.destroyAllWindows()