2020static const char * kNumFacesInputSidePacket = " num_faces" ;
2121static const char * kLandmarksOutputStream = " multi_face_landmarks" ;
2222static const char * kFaceRectsOutputStream = " face_rects_from_landmarks" ;
23+ static const char * kFaceDetectionRectsOutputStream = " face_rects_from_detections" ;
2324
2425// Max number of faces to detect/process.
2526static const int kNumFaces = 1 ;
@@ -68,8 +69,17 @@ + (MPPGraph*)loadGraphFromResource:(NSString*)resource {
6869 // Set graph configurations
6970 [newGraph setSidePacket: (mediapipe: :MakePacket<int >(kNumFaces ))
7071 named: kNumFacesInputSidePacket ];
72+ // The landmarks output stream.
73+ // !! This output does *not* give out any output when there are no faces detected by the face detector!
7174 [newGraph addFrameOutputStream: kLandmarksOutputStream
7275 outputPacketType: MPPPacketTypeRaw];
76+
77+ [newGraph addFrameOutputStream: kFaceRectsOutputStream
78+ outputPacketType: MPPPacketTypeRaw];
79+ // The face detections rect output stream
80+ // This is kind of almost direct from blazeface I think, so it's likely out every frame.
81+ // [newGraph addFrameOutputStream:kFaceDetectionRectsOutputStream
82+ // outputPacketType:MPPPacketTypeRaw];
7383 return newGraph;
7484}
7585
@@ -140,10 +150,6 @@ - (void)mediapipeGraph:(MPPGraph*)graph
140150 fromStream : (const std::string&)streamName {
141151 if (streamName == kLandmarksOutputStream ) {
142152 if (packet.IsEmpty ()) {
143- NSLog (@" [TS:%lld ] No face landmarks" , packet.Timestamp().Value());
144- if ([self .delegate respondsToSelector: @selector (didReceiveFaces: )]) {
145- [self .delegate didReceiveFaces: @[]];
146- }
147153 return ;
148154 }
149155 const auto & multi_face_landmarks = packet.Get <std::vector<::mediapipe::NormalizedLandmarkList>>();
@@ -170,20 +176,55 @@ - (void)mediapipeGraph:(MPPGraph*)graph
170176 [self .delegate didReceiveFaces: faceLandmarks];
171177 }
172178 }
179+ else if (streamName == kFaceDetectionRectsOutputStream ) {
180+ if (packet.IsEmpty ()) {
181+ NSLog (@" [TS:%lld ] No face detections" , packet.Timestamp().Value());
182+ if ([self .delegate respondsToSelector: @selector (didReceiveFaces: )]) {
183+ [self .delegate didReceiveFaceBoxes: @[]];
184+ }
185+ return ;
186+ }
187+ const auto & face_rects_from_landmarks = packet.Get <std::vector<::mediapipe::NormalizedRect>>();
188+ NSMutableArray <FaceMeshIOSLibNormalizedRect *>*outRects = [NSMutableArray new ];
189+ for (int face_index = 0 ; face_index < face_rects_from_landmarks.size (); ++face_index) {
190+ const auto & face = face_rects_from_landmarks[face_index];
191+ float centerX = face.x_center ();
192+ float centerY = face.y_center ();
193+ float height = face.height ();
194+ float width = face.width ();
195+ float rotation = face.rotation ();
196+ FaceMeshIOSLibNormalizedRect *rect = [FaceMeshIOSLibNormalizedRect new ];
197+ rect.centerX = centerX; rect.centerY = centerY; rect.height = height; rect.width = width; rect.rotation = rotation;
198+ [outRects addObject: rect];
199+ }
200+ if ([self .delegate respondsToSelector: @selector (didReceiveFaceDetections: )]) {
201+ [self .delegate didReceiveFaceDetections: outRects];
202+ }
203+ }
173204 else if (streamName == kFaceRectsOutputStream ) {
174205 if (packet.IsEmpty ()) {
206+ NSLog (@" [TS:%lld ] No face rects" , packet.Timestamp().Value());
207+ if ([self .delegate respondsToSelector: @selector (didReceiveFaces: )]) {
208+ [self .delegate didReceiveFaceBoxes: @[]];
209+ }
175210 return ;
176211 }
177212 const auto & face_rects_from_landmarks = packet.Get <std::vector<::mediapipe::NormalizedRect>>();
213+ NSMutableArray <FaceMeshIOSLibNormalizedRect *>*outRects = [NSMutableArray new ];
178214 for (int face_index = 0 ; face_index < face_rects_from_landmarks.size (); ++face_index) {
179215 const auto & face = face_rects_from_landmarks[face_index];
180216 float centerX = face.x_center ();
181217 float centerY = face.y_center ();
182218 float height = face.height ();
183219 float width = face.width ();
184220 float rotation = face.rotation ();
221+ FaceMeshIOSLibNormalizedRect *rect = [FaceMeshIOSLibNormalizedRect new ];
222+ rect.centerX = centerX; rect.centerY = centerY; rect.height = height; rect.width = width; rect.rotation = rotation;
223+ [outRects addObject: rect];
224+ }
225+ if ([self .delegate respondsToSelector: @selector (didReceiveFaceBoxes: )]) {
226+ [self .delegate didReceiveFaceBoxes: outRects];
185227 }
186- // TODO: MAYBE MAKE A DELEGATE METHOD HERE.
187228 }
188229}
189230
@@ -212,3 +253,6 @@ - (void)processVideoFrame:(CVPixelBufferRef)imageBuffer {
212253
213254@implementation FaceMeshIOSLibFaceLandmarkPoint
214255@end
256+
257+ @implementation FaceMeshIOSLibNormalizedRect
258+ @end
0 commit comments