10 #ifdef SL_BUILD_WITH_MEDIAPIPE
14 # define CHECK_MP_RESULT(result) \
17 const char* error = mp_get_last_error(); \
18 std::cerr << error << std::endl; \
19 mp_free_error(error); \
20 SL_EXIT_MSG("Exiting due to MediaPipe error"); \
23 typedef std::vector<std::pair<mp_hand_landmark, mp_hand_landmark>> ConnectionList;
26 static const ConnectionList CONNECTIONS = {
27 {mp_hand_landmark_wrist, mp_hand_landmark_thumb_cmc},
28 {mp_hand_landmark_thumb_cmc, mp_hand_landmark_thumb_mcp},
29 {mp_hand_landmark_thumb_mcp, mp_hand_landmark_thumb_ip},
30 {mp_hand_landmark_thumb_ip, mp_hand_landmark_thumb_tip},
31 {mp_hand_landmark_wrist, mp_hand_landmark_index_finger_mcp},
32 {mp_hand_landmark_index_finger_mcp, mp_hand_landmark_index_finger_pip},
33 {mp_hand_landmark_index_finger_pip, mp_hand_landmark_index_finger_dip},
34 {mp_hand_landmark_index_finger_dip, mp_hand_landmark_index_finger_tip},
35 {mp_hand_landmark_index_finger_mcp, mp_hand_landmark_middle_finger_mcp},
36 {mp_hand_landmark_middle_finger_mcp, mp_hand_landmark_middle_finger_pip},
37 {mp_hand_landmark_middle_finger_pip, mp_hand_landmark_middle_finger_dip},
38 {mp_hand_landmark_middle_finger_dip, mp_hand_landmark_middle_finger_tip},
39 {mp_hand_landmark_middle_finger_mcp, mp_hand_landmark_ring_finger_mcp},
40 {mp_hand_landmark_ring_finger_mcp, mp_hand_landmark_ring_finger_pip},
41 {mp_hand_landmark_ring_finger_pip, mp_hand_landmark_ring_finger_dip},
42 {mp_hand_landmark_ring_finger_dip, mp_hand_landmark_ring_finger_tip},
43 {mp_hand_landmark_ring_finger_mcp, mp_hand_landmark_pinky_mcp},
44 {mp_hand_landmark_wrist, mp_hand_landmark_pinky_mcp},
45 {mp_hand_landmark_pinky_mcp, mp_hand_landmark_pinky_pip},
46 {mp_hand_landmark_pinky_pip, mp_hand_landmark_pinky_dip},
47 {mp_hand_landmark_pinky_dip, mp_hand_landmark_pinky_tip}};
49 CVTrackedMediaPipeHands::CVTrackedMediaPipeHands(
SLstring dataPath)
51 mp_set_resource_dir(dataPath.c_str());
53 SLstring graphPath = dataPath +
"mediapipe/modules/hand_landmark/hand_landmark_tracking_cpu.binarypb";
54 auto* builder = mp_create_instance_builder(graphPath.c_str(),
"image");
63 mp_add_side_packet(builder,
65 mp_create_packet_bool(
true));
69 mp_add_side_packet(builder,
71 mp_create_packet_int(2));
77 mp_add_side_packet(builder,
79 mp_create_packet_int(1));
83 mp_add_option_float(builder,
84 "palmdetectioncpu__TensorsToDetectionsCalculator",
90 mp_add_option_double(builder,
91 "handlandmarkcpu__ThresholdingCalculator",
96 _instance = mp_create_instance(builder);
97 CHECK_MP_RESULT(_instance)
100 _landmarksPoller = mp_create_poller(_instance,
101 "multi_hand_landmarks");
102 CHECK_MP_RESULT(_landmarksPoller)
105 CHECK_MP_RESULT(mp_start(_instance))
117 CVTrackedMediaPipeHands::~CVTrackedMediaPipeHands()
119 mp_destroy_poller(_landmarksPoller);
120 CHECK_MP_RESULT(mp_destroy_instance(_instance))
123 bool CVTrackedMediaPipeHands::track(
CVMat imageGray,
127 processImageInMediaPipe(imageBgr);
129 if (mp_get_queue_size(_landmarksPoller) > 0)
131 auto* landmarksPacket = mp_poll_packet(_landmarksPoller);
132 auto* landmarks = mp_get_norm_multi_face_landmarks(landmarksPacket);
134 drawResults(landmarks, imageBgr);
136 mp_destroy_multi_face_landmarks(landmarks);
137 mp_destroy_packet(landmarksPacket);
143 void CVTrackedMediaPipeHands::processImageInMediaPipe(
CVMat imageBgr)
145 cv::cvtColor(imageBgr, _imageRgb, cv::COLOR_BGR2RGB);
148 inImage.data = _imageRgb.data;
149 inImage.width = _imageRgb.cols;
150 inImage.height = _imageRgb.rows;
151 inImage.format = mp_image_format_srgb;
152 mp_packet* packet = mp_create_packet_image(inImage);
155 CHECK_MP_RESULT(mp_process(_instance, packet))
158 CHECK_MP_RESULT(mp_wait_until_idle(_instance))
162 void CVTrackedMediaPipeHands::drawResults(mp_multi_face_landmark_list* landmarks,
165 for (
int i = 0; i < landmarks->length; i++)
167 auto& hand = landmarks->elements[i];
169 for (
auto& connection : CONNECTIONS)
171 auto p1 = hand.elements[connection.first];
172 auto p2 = hand.elements[connection.second];
173 float x1 = (float)imageBgr.cols * p1.x;
174 float y1 = (
float)imageBgr.rows * p1.y;
175 float x2 = (float)imageBgr.cols * p2.x;
176 float y2 = (
float)imageBgr.rows * p2.y;
185 for (
int j = 0; j < hand.length; j++)
187 auto p = hand.elements[j];
188 float x = (float)imageBgr.cols * p.x;
189 float y = (
float)imageBgr.rows * p.y;
190 float radius = std::max(3.0f + 25.0f * -p.z, 1.0f);
Live video camera calibration class with OpenCV an OpenCV calibration.