Skip to content

Commit aafd8e1

Browse files
committed
Including Face recognition in folder
1 parent dfe96d1 commit aafd8e1

File tree

8 files changed

+451
-5
lines changed

8 files changed

+451
-5
lines changed

people_tracking_v2/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,11 @@ include_directories(
193193
# )
194194

195195
install(PROGRAMS
196-
scripts/detect_poses
197-
scripts/pose_estimation_node
196+
scripts/pose_estimation/detect_poses
197+
scripts/pose_estimation/pose_estimation_node
198+
scripts/get_face_recognition
199+
scripts/face_recognition_node
200+
scripts/train_from_images
198201
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
199202
)
200203

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
#!/usr/bin/env python
2+
import math
3+
import os
4+
import sys
5+
import diagnostic_updater
6+
import rospy
7+
from cv_bridge import CvBridge, CvBridgeError
8+
from sensor_msgs.msg import RegionOfInterest, Image
9+
from std_srvs.srv import Empty
10+
from image_recognition_msgs.msg import (
11+
Recognition,
12+
Recognitions,
13+
CategoryProbability,
14+
CategoricalDistribution,
15+
)
16+
from image_recognition_msgs.srv import Recognize, Annotate
17+
from image_recognition_util import image_writer
18+
from src.face_recognition.face_recognizer import FaceRecognizer
19+
20+
21+
class OpenfaceROS:
22+
def __init__(
23+
self,
24+
save_images_folder,
25+
topic_save_images,
26+
service_save_images,
27+
topic_publish_result_image,
28+
service_publish_result_image,
29+
):
30+
"""
31+
OpenfaceROS class that wraps the FaceRecognizer in a ROS node
32+
33+
:param save_images_folder: path where to store the images
34+
:param topic_save_images: whether to save images originated from image topic callback
35+
:param service_save_images: whether to save images originated from a service call
36+
:param topic_publish_result_image: whether to publish images originated from image topic callback
37+
:param service_publish_result_image: whether to publish images originated from a serice call
38+
"""
39+
40+
# Openface ROS
41+
self._face_recognizer = FaceRecognizer()
42+
self._save_images_folder = save_images_folder
43+
self._topic_save_images = topic_save_images
44+
self._service_save_images = service_save_images
45+
self._topic_publish_result_image = topic_publish_result_image
46+
self._service_publish_result_image = service_publish_result_image
47+
48+
self._bridge = CvBridge()
49+
self._annotate_srv = rospy.Service("annotate", Annotate, self._annotate_srv)
50+
self._recognize_srv = rospy.Service("recognize", Recognize, self._recognize_srv)
51+
self._image_subscriber = rospy.Subscriber("image", Image, self._image_callback)
52+
self._recognitions_publisher = rospy.Publisher("recognitions", Recognitions, queue_size=10)
53+
54+
if not self._save_images_folder and (self._topic_save_images or self._service_save_images):
55+
rospy.logerr("~save_images_folder is not defined but we would like to save images ...")
56+
rospy.signal_shutdown("")
57+
58+
if self._topic_publish_result_image or self._service_publish_result_image:
59+
self._result_image_publisher = rospy.Publisher("result_image", Image, queue_size=10)
60+
61+
rospy.loginfo("OpenfaceROS initialized:")
62+
rospy.loginfo(" - save_images_folder=%s", save_images_folder)
63+
rospy.loginfo(" - topic_save_images=%s", topic_save_images)
64+
rospy.loginfo(" - service_save_images=%s", service_save_images)
65+
rospy.loginfo(" - topic_publish_result_image=%s", topic_publish_result_image)
66+
rospy.loginfo(" - service_publish_result_image=%s", service_publish_result_image)
67+
68+
def _annotate_srv(self, req):
69+
# Convert to opencv image
70+
"""
71+
Annotate service callback that trains the face of the user
72+
73+
:param req: Face annotation request
74+
:return: Empty
75+
"""
76+
try:
77+
bgr_image = self._bridge.imgmsg_to_cv2(req.image, "bgr8")
78+
except CvBridgeError as e:
79+
raise Exception("Could not convert to opencv image: %s" % str(e))
80+
81+
for annotation in req.annotations:
82+
roi_image = bgr_image[
83+
annotation.roi.y_offset: annotation.roi.y_offset + annotation.roi.height,
84+
annotation.roi.x_offset: annotation.roi.x_offset + annotation.roi.width,
85+
]
86+
87+
if self._save_images_folder:
88+
image_writer.write_annotated(self._save_images_folder, roi_image, annotation.label, True)
89+
90+
try:
91+
self._face_recognizer.train(roi_image, annotation.label)
92+
except Exception as e:
93+
raise Exception("Could not get representation of face image: %s" % str(e))
94+
95+
rospy.loginfo("Succesfully learned face of '%s'" % annotation.label)
96+
97+
return {}
98+
99+
def _get_recognitions(self, image_msg, save_images, publish_images):
100+
# Convert to opencv image
101+
"""
102+
Recognize service callback
103+
104+
:param req: The input image
105+
:return: Recognitions
106+
"""
107+
try:
108+
bgr_image = self._bridge.imgmsg_to_cv2(image_msg, "bgr8")
109+
except CvBridgeError as e:
110+
raise Exception("Could not convert to opencv image: %s" % str(e))
111+
112+
# Write raw image
113+
if save_images:
114+
image_writer.write_raw(self._save_images_folder, bgr_image)
115+
116+
images = []
117+
labels = ['Miguel']
118+
119+
# Call facebet neural network in two stages
120+
face_recognitions = self._face_recognizer.face_detection(bgr_image)
121+
distance, labels_pred = self._face_recognizer.detection_recognition(bgr_image, labels, train=True)
122+
123+
# Fill recognitions
124+
recognitions = []
125+
126+
# rospy.loginfo("Face recognitions: %s", face_recognitions)
127+
128+
label_idx = 0
129+
for fr in face_recognitions:
130+
face_recognition = [math.floor(xi) for xi in fr]
131+
if save_images:
132+
label = labels_pred[label_idx]
133+
roi_image = bgr_image[
134+
face_recognition[2]: face_recognition[3],
135+
face_recognition[0]: face_recognition[1],
136+
]
137+
image_writer.write_annotated(self._save_images_folder, roi_image, label, False)
138+
images.append(roi_image)
139+
labels.append(label)
140+
label = labels_pred[label_idx]
141+
distance_fr = distance[label_idx]
142+
recognitions.append(
143+
Recognition(
144+
categorical_distribution=CategoricalDistribution(
145+
unknown_probability=0.0, # TODO: When is it unknown?
146+
probabilities=[
147+
# This line needs some changing
148+
CategoryProbability(label=label, probability=1.0 / (distance_fr + 0.001)) for l2 in face_recognition
149+
],
150+
),
151+
roi=RegionOfInterest(
152+
x_offset=face_recognition[0],
153+
y_offset=face_recognition[1],
154+
width=face_recognition[2] - face_recognition[0],
155+
height=face_recognition[3] - face_recognition[1],
156+
),
157+
)
158+
)
159+
label_idx = label_idx + 1
160+
161+
annotated_original_image = image_writer.get_annotated_cv_image(bgr_image, recognitions)
162+
if save_images:
163+
image_writer.write_estimations(
164+
self._save_images_folder,
165+
images,
166+
labels,
167+
annotated_original_image,
168+
suffix="_face_recognition",
169+
)
170+
171+
if publish_images:
172+
self._result_image_publisher.publish(self._bridge.cv2_to_imgmsg(annotated_original_image, "bgr8"))
173+
174+
# Service response
175+
return recognitions
176+
177+
def _image_callback(self, image_msg):
178+
# Comment this exception for beeter debbuging
179+
try:
180+
recognitions = self._get_recognitions(
181+
image_msg,
182+
save_images=self._topic_save_images,
183+
publish_images=self._topic_publish_result_image,
184+
)
185+
except Exception as e:
186+
rospy.logerr(str(e))
187+
return
188+
189+
self._recognitions_publisher.publish(Recognitions(header=image_msg.header, recognitions=recognitions))
190+
191+
def _recognize_srv(self, req):
192+
recognitions = self._get_recognitions(
193+
req.image,
194+
save_images=self._service_save_images,
195+
publish_images=self._service_publish_result_image,
196+
)
197+
198+
# Service response
199+
return {"recognitions": recognitions}
200+
201+
202+
if __name__ == "__main__":
203+
rospy.init_node("face_recognition")
204+
try:
205+
save_images = rospy.get_param("~save_images", True)
206+
topic_save_images = rospy.get_param("~topic_save_images", False)
207+
service_save_images = rospy.get_param("~service_save_images", True)
208+
topic_publish_result_image = rospy.get_param("~topic_publish_result_image", True)
209+
service_publish_result_image = rospy.get_param("~service_publish_result_image", True)
210+
211+
save_images_folder = None
212+
if save_images:
213+
save_images_folder = os.path.expanduser(rospy.get_param("~save_images_folder", "/tmp/facenet_saved_images"))
214+
except KeyError as e:
215+
rospy.logerr("Parameter %s not found" % e)
216+
sys.exit(1)
217+
218+
image_recognition_openface = OpenfaceROS(
219+
save_images_folder,
220+
topic_save_images,
221+
service_save_images,
222+
topic_publish_result_image,
223+
service_publish_result_image,
224+
)
225+
updater = diagnostic_updater.Updater()
226+
updater.setHardwareID("none")
227+
updater.add(diagnostic_updater.Heartbeat())
228+
rospy.Timer(rospy.Duration(1), lambda event: updater.force_update())
229+
230+
rospy.spin()

people_tracking_v2/scripts/detect_poses.py renamed to people_tracking_v2/scripts/pose_estimation/detect_poses.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import cv2
88

9-
from image_recognition_pose_estimation.yolo_pose_wrapper import YoloPoseWrapper
9+
from pose_estimation.yolo_pose_wrapper import YoloPoseWrapper
1010

1111

1212
def main(args: argparse.Namespace):

people_tracking_v2/scripts/pose_estimation_node.py renamed to people_tracking_v2/scripts/pose_estimation/pose_estimation_node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from image_recognition_util import image_writer
1414
from sensor_msgs.msg import Image
1515

16-
from image_recognition_pose_estimation.yolo_pose_wrapper import YoloPoseWrapper
16+
from pose_estimation.yolo_pose_wrapper import YoloPoseWrapper
1717

1818

1919
class PoseEstimationNode:

0 commit comments

Comments
 (0)