Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ROS nodes FPS performance measurements #419

Merged
merged 80 commits into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
f199d38
Added performance node
tsampazk Mar 13, 2023
a1d88ad
Added time measurement for tool inference and publishing
tsampazk Mar 13, 2023
733bd91
Moved performance start time before image preprocessing
tsampazk Mar 21, 2023
ad08216
audiovisual_emotion_recognition_node.py performance and some formatting
tsampazk Mar 22, 2023
69f6b55
binary_high_resolution_node.py performance
tsampazk Mar 22, 2023
be8a07a
continual_skeleton_based_action_recognition_node.py performance and s…
tsampazk Mar 22, 2023
e855f2e
face_detection_retinaface_node.py performance
tsampazk Mar 22, 2023
e476392
face_recognition_node.py performance
tsampazk Mar 22, 2023
5238abe
facial_emotion_estimation_node.py performance
tsampazk Mar 22, 2023
50ee6e4
fall_detection_node.py performance
tsampazk Mar 22, 2023
481aade
heart_anomaly_detection_node.py performance
tsampazk Mar 22, 2023
472e3f8
hr_pose_estimation_node.py performance
tsampazk Mar 22, 2023
1ccbe63
landmark_based_facial_expression_recognition_node.py performance
tsampazk Mar 22, 2023
09d480f
object_detection_2d_centernet_node.py performance
tsampazk Mar 22, 2023
c38f7ee
object_detection_2d_detr_node.py performance
tsampazk Mar 22, 2023
a5a50d9
object_detection_2d_gem_node.py performance
tsampazk Mar 22, 2023
65e34d8
object_detection_2d_nanodet_node.py performance
tsampazk Mar 22, 2023
3af0f63
object_detection_2d_ssd_node.py performance
tsampazk Mar 22, 2023
e8ad377
object_detection_2d_yolov3_node.py performance
tsampazk Mar 22, 2023
c6a66ce
object_detection_2d_yolov5_node.py performance
tsampazk Mar 22, 2023
8611525
object_detection_3d_voxel_node.py performance
tsampazk Mar 22, 2023
613fdc5
object_tracking_2d_deep_sort_node.py performance
tsampazk Mar 22, 2023
15d889a
object_tracking_2d_fair_mot_node.py performance
tsampazk Mar 22, 2023
2f3dfee
object_tracking_2d_siamrpn_node.py performance
tsampazk Mar 22, 2023
d5a52f9
object_tracking_3d_ab3dmot_node.py performance
tsampazk Mar 22, 2023
b62a867
panoptic_segmentation_efficient_lps_node.py performance
tsampazk Mar 22, 2023
4cee604
panoptic_segmentation_efficient_ps_node.py performance
tsampazk Mar 22, 2023
b3b616f
pose_estimation_node.py minor fixes
tsampazk Mar 22, 2023
576b896
rgbd_hand_gesture_recognition_node.py performance
tsampazk Mar 22, 2023
8bcc78b
semantic_segmentation_bisenet_node.py performance
tsampazk Mar 22, 2023
5cad7be
skeleton_based_action_recognition_node.py performance
tsampazk Mar 22, 2023
6340548
speech_command_recognition_node.py performance
tsampazk Mar 22, 2023
8bd1ccc
video_activity_recognition_node.py performance
tsampazk Mar 22, 2023
fafa9b3
Added section for utility nodes and entry for the performance node
tsampazk Mar 23, 2023
2614e17
Added entry in notes for logging performance
tsampazk Mar 23, 2023
11e4b5b
Added entries for the new performance topic in all nodes
tsampazk Mar 23, 2023
1836478
audiovisual_emotion_recognition_node.py ROS2 performance
tsampazk Mar 24, 2023
dd3f416
binary_high_resolution_node.py ROS2 performance
tsampazk Mar 24, 2023
c434ba2
continual_skeleton_based_action_recognition_node.py ROS2 performance
tsampazk Mar 24, 2023
6da8dd0
face_detection_retinaface_node.py ROS2 performance
tsampazk Mar 24, 2023
8e22ab5
face_recognition_node.py ROS2 performance
tsampazk Mar 24, 2023
1ada491
facial_emotion_estimation_node.py ROS2 performance
tsampazk Mar 24, 2023
ad12e95
fall_detection_node.py ROS2 performance
tsampazk Mar 24, 2023
7d40dcb
heart_anomaly_detection_node.py ROS2 performance
tsampazk Mar 24, 2023
b10db4c
hr_pose_estimation_node.py ros1 renamed class
tsampazk Mar 24, 2023
691b1f9
hr_pose_estimation_node.py ROS2 performance
tsampazk Mar 24, 2023
2b697c3
landmark_based_facial_expression_recognition_node.py ROS2 performance
tsampazk Mar 24, 2023
0085265
object_detection_2d_centernet_node.py ROS2 performance
tsampazk Mar 24, 2023
62217b7
object_detection_2d_detr_node.py ROS2 performance
tsampazk Mar 24, 2023
fed1430
object_detection_2d_gem_node.py ROS2 performance
tsampazk Mar 24, 2023
c1f684f
object_detection_2d_nanodet_node.py ROS1 minor fix
tsampazk Mar 24, 2023
5826087
object_detection_2d_nanodet_node.py ROS2 performance
tsampazk Mar 24, 2023
1a83b22
object_detection_2d_ssd_node.py ROS2 performance
tsampazk Mar 24, 2023
94c80be
object_detection_2d_yolov3_node.py ROS1 class name fix
tsampazk Mar 24, 2023
2248fbf
object_detection_2d_yolov3_node.py ROS2 performance
tsampazk Mar 24, 2023
3cd9839
object_detection_2d_yolov5_node.py ROS1 class name fix
tsampazk Mar 24, 2023
f63144c
object_detection_2d_yolov5_node.py ROS2 performance
tsampazk Mar 24, 2023
c709714
object_detection_3d_voxel_node.py ROS2 performance
tsampazk Mar 24, 2023
be5d0c2
object_tracking_2d_deep_sort_node.py ROS2 performance
tsampazk Mar 24, 2023
c1be58d
object_tracking_2d_fair_mot_node.py ROS2 performance
tsampazk Mar 24, 2023
75f0faa
object_tracking_2d_siamrpn_node.py ROS2 performance
tsampazk Mar 24, 2023
cba574c
object_tracking_3d_ab3dmot_node.py ROS2 performance
tsampazk Mar 24, 2023
e6dd984
panoptic_segmentation_efficient_lps_node.py ROS1 some imports rearran…
tsampazk Mar 24, 2023
c8a9e48
panoptic_segmentation_efficient_lps_node.py ROS2 performance
tsampazk Mar 24, 2023
068eff8
panoptic_segmentation_efficient_ps_node.py ROS1 some imports rearrang…
tsampazk Mar 24, 2023
b9d8168
panoptic_segmentation_efficient_ps_node.py ROS2 performance
tsampazk Mar 24, 2023
08d24ab
pose_estimation_node.py ROS2 performance
tsampazk Mar 24, 2023
c84d9e8
rgbd_hand_gesture_recognition_node.py ROS2 performance
tsampazk Mar 24, 2023
1e99fd2
semantic_segmentation_bisenet_node.py ROS2 performance
tsampazk Mar 24, 2023
bb5f274
skeleton_based_action_recognition_node.py ROS2 performance and some r…
tsampazk Mar 24, 2023
f68523d
speech_command_recognition_node.py ROS2 performance
tsampazk Mar 24, 2023
afa47a0
video_activity_recognition_node.py ROS2 performance
tsampazk Mar 24, 2023
e0fb25b
Added ROS2 performance_node.py
tsampazk Mar 24, 2023
5d13583
ROS2 readme updates for performance topics/node
tsampazk Mar 24, 2023
4b47c30
Apply suggestions from code review
tsampazk Mar 27, 2023
75994ee
Disable running tracking infer if no tracking is needed for ab3dmot ROS2
tsampazk Mar 27, 2023
5182ad0
Disable running tracking infer if no tracking is needed for ab3dmot ROS1
tsampazk Mar 27, 2023
3a30c7d
Apply suggestions from code review
tsampazk Apr 5, 2023
4c1701a
Removed additional spaces after suggested change
tsampazk Apr 5, 2023
ff6e1d6
Applied review suggestion to ROS2 node as well
tsampazk Apr 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions projects/opendr_ws/src/opendr_perception/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ include_directories(
#############

catkin_install_python(PROGRAMS
scripts/performance_node.py
scripts/pose_estimation_node.py
scripts/hr_pose_estimation_node.py
scripts/fall_detection_node.py
Expand Down
55 changes: 54 additions & 1 deletion projects/opendr_ws/src/opendr_perception/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
import torch
import librosa
import cv2
from time import perf_counter

import rospy
import message_filters
from std_msgs.msg import Float32
from sensor_msgs.msg import Image as ROS_Image
from audio_common_msgs.msg import AudioData
from vision_msgs.msg import Classification2D
Expand All @@ -36,7 +38,8 @@
class AudiovisualEmotionNode:

def __init__(self, input_video_topic="/usb_cam/image_raw", input_audio_topic="/audio/audio",
output_emotions_topic="/opendr/audiovisual_emotion", buffer_size=3.6, device="cuda"):
output_emotions_topic="/opendr/audiovisual_emotion", performance_topic=None,
buffer_size=3.6, device="cuda"):
"""
Creates a ROS Node for audiovisual emotion recognition
:param input_video_topic: Topic from which we are reading the input video. Expects detected face of size 224x224
Expand All @@ -45,6 +48,9 @@ def __init__(self, input_video_topic="/usb_cam/image_raw", input_audio_topic="/a
:type input_audio_topic: str
:param output_emotions_topic: Topic to which we are publishing the predicted class
:type output_emotions_topic: str
:param performance_topic: Topic to which we are publishing performance information (if None, no performance
message is published)
:type performance_topic: str
:param buffer_size: length of audio and video in sec
:type buffer_size: float
:param device: device on which we are running inference ('cpu' or 'cuda')
Expand All @@ -56,6 +62,11 @@ def __init__(self, input_video_topic="/usb_cam/image_raw", input_audio_topic="/a
self.input_video_topic = input_video_topic
self.input_audio_topic = input_audio_topic

if performance_topic is not None:
self.performance_publisher = rospy.Publisher(performance_topic, Float32, queue_size=1)
else:
self.performance_publisher = None

self.bridge = ROSBridge()

# Initialize the gesture recognition
Expand All @@ -69,7 +80,7 @@ def __init__(self, input_video_topic="/usb_cam/image_raw", input_audio_topic="/a
self.video_buffer = np.zeros((1, 224, 224, 3))

self.video_transform = transforms.Compose([
transforms.ToTensor(255)])
transforms.ToTensor(255)])

def listen(self):
"""
Expand All @@ -94,26 +105,35 @@ def callback(self, image_data, audio_data):
:param audio_data: input audio message, speech
:type audio_data: audio_common_msgs.msg.AudioData
"""
audio_data = np.reshape(np.frombuffer(audio_data.data, dtype=np.int16)/32768.0, (1, -1))
if self.performance_publisher:
start_time = perf_counter()
audio_data = np.reshape(np.frombuffer(audio_data.data, dtype=np.int16) / 32768.0, (1, -1))
self.data_buffer = np.append(self.data_buffer, audio_data)

image_data = self.bridge.from_ros_image(image_data, encoding='bgr8').convert(format='channels_last')
image_data = cv2.resize(image_data, (224, 224))

self.video_buffer = np.append(self.video_buffer, np.expand_dims(image_data.data, 0), axis=0)

if self.data_buffer.shape[0] > 16000*self.buffer_size:
if self.data_buffer.shape[0] > 16000 * self.buffer_size:
audio = librosa.feature.mfcc(self.data_buffer[1:], sr=16000, n_mfcc=10)
audio = Timeseries(audio)

to_select = select_distributed(15, len(self.video_buffer)-1)
to_select = select_distributed(15, len(self.video_buffer) - 1)
video = self.video_buffer[1:][to_select]

video = [self.video_transform(img) for img in video]
video = Video(torch.stack(video, 0).permute(1, 0, 2, 3))

class_pred = self.avlearner.infer(audio, video)

if self.performance_publisher:
end_time = perf_counter()
fps = 1.0 / (end_time - start_time) # NOQA
fps_msg = Float32()
fps_msg.data = fps
self.performance_publisher.publish(fps_msg)

# Publish output
ros_class = self.bridge.from_category_to_rosclass(class_pred)
self.publisher.publish(ros_class)
Expand All @@ -122,7 +142,7 @@ def callback(self, image_data, audio_data):
self.video_buffer = np.zeros((1, 224, 224, 3))


def select_distributed(m, n): return [i*n//m + n//(2*m) for i in range(m)]
def select_distributed(m, n): return [i * n // m + n // (2 * m) for i in range(m)]


if __name__ == '__main__':
Expand All @@ -133,6 +153,8 @@ def select_distributed(m, n): return [i*n//m + n//(2*m) for i in range(m)]
help="Listen to audio input data on this topic")
parser.add_argument("-o", "--output_emotions_topic", type=str, default="/opendr/audiovisual_emotion",
help="Topic name for output emotions recognition")
parser.add_argument("--performance_topic", help="Topic name for performance messages, disabled (None) by default",
type=str, default=None)
parser.add_argument("--device", type=str, default="cuda",
help="Device to use (cpu, cuda)", choices=["cuda", "cpu"])
parser.add_argument("--buffer_size", type=float, default=3.6,
Expand All @@ -154,5 +176,6 @@ def select_distributed(m, n): return [i*n//m + n//(2*m) for i in range(m)]

avnode = AudiovisualEmotionNode(input_video_topic=args.input_video_topic, input_audio_topic=args.input_audio_topic,
output_emotions_topic=args.output_emotions_topic,
performance_topic=args.performance_topic,
buffer_size=args.buffer_size, device=device)
avnode.listen()
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
import numpy as np
import torch
import cv2
from time import perf_counter

import rospy
from std_msgs.msg import Float32
from sensor_msgs.msg import Image as ROS_Image
from opendr_bridge import ROSBridge

Expand All @@ -29,7 +31,7 @@
class BinaryHighResolutionNode:

def __init__(self, input_rgb_image_topic="/usb_cam/image_raw", output_heatmap_topic="/opendr/binary_hr_heatmap",
output_rgb_image_topic="/opendr/binary_hr_heatmap_visualization",
output_rgb_image_topic="/opendr/binary_hr_heatmap_visualization", performance_topic=None,
model_path=None, architecture="VGG_720p", device="cuda"):
"""
Create a ROS Node for binary high resolution classification with Binary High Resolution.
Expand All @@ -40,6 +42,9 @@ def __init__(self, input_rgb_image_topic="/usb_cam/image_raw", output_heatmap_to
:param output_rgb_image_topic: Topic to which we are publishing the heatmap image blended with the
input image for visualization purposes
:type output_rgb_image_topic: str
:param performance_topic: Topic to which we are publishing performance information (if None, no performance
message is published)
:type performance_topic: str
:param model_path: The path to the directory of a trained model
:type model_path: str
:param architecture: Architecture used on trained model (`VGG_720p` or `VGG_1080p`)
Expand All @@ -59,6 +64,11 @@ def __init__(self, input_rgb_image_topic="/usb_cam/image_raw", output_heatmap_to
else:
self.visualization_publisher = None

if performance_topic is not None:
self.performance_publisher = rospy.Publisher(performance_topic, Float32, queue_size=1)
else:
self.performance_publisher = None

self.bridge = ROSBridge()

# Initialize the binary high resolution model
Expand Down Expand Up @@ -94,12 +104,21 @@ def callback(self, data):
:param data: Input image message
:type data: sensor_msgs.msg.Image
"""
if self.performance_publisher:
start_time = perf_counter()
# Convert sensor_msgs.msg.Image into OpenDR Image
image = self.bridge.from_ros_image(data, encoding='bgr8')
image = image.convert("channels_last")
# Run learner to retrieve the OpenDR heatmap
heatmap = self.learner.infer(image)

if self.performance_publisher:
end_time = perf_counter()
fps = 1.0 / (end_time - start_time) # NOQA
fps_msg = Float32()
fps_msg.data = fps
self.performance_publisher.publish(fps_msg)

# Publish heatmap in the form of an image
if self.heatmap_publisher is not None:
self.heatmap_publisher.publish(self.bridge.to_ros_image(heatmap))
Expand All @@ -126,6 +145,8 @@ def main():
"blended with the input image for visualization purposes",
type=lambda value: value if value.lower() != "none" else None,
default="/opendr/binary_hr_heatmap_visualization")
parser.add_argument("--performance_topic", help="Topic name for performance messages, disabled (None) by default",
type=str, default=None)
parser.add_argument("-m", "--model_path", help="Path to the directory of the trained model",
type=str, default="test_model")
parser.add_argument("-a", "--architecture", help="Architecture used for the trained model, either \"VGG_720p\" or "
Expand All @@ -152,6 +173,7 @@ def main():
input_rgb_image_topic=args.input_rgb_image_topic,
output_heatmap_topic=args.output_heatmap_topic,
output_rgb_image_topic=args.output_rgb_image_topic,
performance_topic=args.performance_topic,
model_path=args.model_path,
architecture=args.architecture)
binary_hr_node.listen()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
import argparse
import torch
import numpy as np
from time import perf_counter

import rospy
from std_msgs.msg import String
from std_msgs.msg import String, Float32
from vision_msgs.msg import ObjectHypothesis
from sensor_msgs.msg import Image as ROS_Image
from opendr_bridge.msg import OpenDRPose2D
Expand All @@ -37,6 +38,7 @@ def __init__(self, input_rgb_image_topic="/usb_cam/image_raw",
pose_annotations_topic="/opendr/poses",
output_category_topic="/opendr/continual_skeleton_recognized_action",
output_category_description_topic="/opendr/continual_skeleton_recognized_action_description",
performance_topic=None,
device="cuda", model='costgcn'):
"""
Creates a ROS Node for continual skeleton-based action recognition.
Expand All @@ -54,6 +56,9 @@ def __init__(self, input_rgb_image_topic="/usb_cam/image_raw",
:param output_category_description_topic: Topic to which we are publishing the description of the recognized
action (if None, we are not publishing the description)
:type output_category_description_topic: str
:param performance_topic: Topic to which we are publishing performance information (if None, no performance
message is published)
:type performance_topic: str
:param device: device on which we are running inference ('cpu' or 'cuda')
:type device: str
:param model: model to use for continual skeleton-based action recognition.
Expand Down Expand Up @@ -85,6 +90,11 @@ def __init__(self, input_rgb_image_topic="/usb_cam/image_raw",
else:
self.string_publisher = None

if performance_topic is not None:
self.performance_publisher = rospy.Publisher(performance_topic, Float32, queue_size=1)
else:
self.performance_publisher = None

# Initialize the pose estimation
self.pose_estimator = LightweightOpenPoseLearner(device=device, num_refinement_stages=2,
mobilenet_use_stride=False,
Expand Down Expand Up @@ -117,6 +127,8 @@ def callback(self, data):
:param data: input message
:type data: sensor_msgs.msg.Image
"""
if self.performance_publisher:
start_time = perf_counter()

# Convert sensor_msgs.msg.Image into OpenDR Image
image = self.bridge.from_ros_image(data, encoding='bgr8')
Expand All @@ -127,6 +139,22 @@ def callback(self, data):
# select two poses with the highest energy
poses = _select_2_poses(poses)

num_frames = 1
poses_list = [poses]
skeleton_seq = _pose2numpy(num_frames, poses_list)

# Run action recognition
result = self.action_classifier.infer(skeleton_seq) # input_size: BxCxTxVxS
category = result[0]
category.confidence = float(category.confidence.max())

if self.performance_publisher:
end_time = perf_counter()
fps = 1.0 / (end_time - start_time) # NOQA
fps_msg = Float32()
fps_msg.data = fps
self.performance_publisher.publish(fps_msg)

# Publish detections in ROS message
if self.pose_publisher is not None:
for pose in poses:
Expand All @@ -142,15 +170,6 @@ def callback(self, data):
# Convert the annotated OpenDR image to ROS image message using bridge and publish it
self.image_publisher.publish(self.bridge.to_ros_image(Image(image), encoding='bgr8'))

num_frames = 1
poses_list = [poses]
skeleton_seq = _pose2numpy(num_frames, poses_list)

# Run action recognition
result = self.action_classifier.infer(skeleton_seq) # input_size: BxCxTxVxS
category = result[0]
category.confidence = float(category.confidence.max())

if self.hypothesis_publisher is not None:
self.hypothesis_publisher.publish(self.bridge.to_ros_category(category))

Expand Down Expand Up @@ -199,6 +218,8 @@ def main():
"recognized action category",
type=lambda value: value if value.lower() != "none" else None,
default="/opendr/continual_skeleton_recognized_action_description")
parser.add_argument("--performance_topic", help="Topic name for performance messages, disabled (None) by default",
type=str, default=None)
parser.add_argument("--device", help="Device to use, either \"cpu\" or \"cuda\"",
type=str, default="cuda", choices=["cuda", "cpu"])
parser.add_argument("--model", help="Model to use, either \"costgcn\"",
Expand All @@ -225,6 +246,7 @@ def main():
pose_annotations_topic=args.pose_annotations_topic,
output_category_topic=args.output_category_topic,
output_category_description_topic=args.output_category_description_topic,
performance_topic=args.performance_topic,
device=device,
model=args.model)
continual_skeleton_action_recognition_node.listen()
Expand Down
Loading