Skip to content

Commit e70b07b

Browse files
committed
openvino
1 parent 41ca6be commit e70b07b

File tree

10 files changed

+314
-18
lines changed

10 files changed

+314
-18
lines changed

weights/openvino/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.bin
2+
*.xml
3+
*.onnx
4+
*.mapping
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## YOLOX_Nano's weights file (OpenVINO)
2+
3+
- yolox_nano.bin
4+
- yolox_nano.mapping
5+
- yolox_nano.onnx
6+
- yolox_nano.xml
7+
8+
## How to create and Install OpenVINO's weights
9+
10+
> Note : Setup Open VINO before run these commands.
11+
12+
```bash
13+
rm -rf ~/openvino_download
14+
mkdir ~/openvino_download
15+
cd ~/openvino_download
16+
wget https://github.com/Megvii-BaseDetection/YOLOX/releases/download/0.1.1rc0/yolox_nano.onnx
17+
export MO=/opt/intel/openvino_2021/deployment_tools/model_optimizer/mo.py
18+
python3 $MO --input_model ./yolox_nano.onnx --input_shape [1,3,640,640] --data_type FP16 --output_dir ./
19+
cp -r ./* ~/ros2_ws/src/YOLOX-ROS/weights/openvino/
20+
cd ~/ros2_ws/
21+
colcon build --symlink-install
22+
```
23+
24+
25+

weights/openvino/install.bash

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
3+
# if $1 is empty
4+
if [ -z "$1" ]; then
5+
echo "Usage: $0 <target-model>"
6+
echo "Target-Models :"
7+
echo "yolox_tiny, yolox_nano, yolox_s, yolox_m, yolox_l, yolox_darknet, yolox"
8+
exit 1
9+
fi
10+
MODEL=$1
11+
MO=/opt/intel/openvino_2021/deployment_tools/model_optimizer/mo.py
12+
ROS2_WS=~/ros2_ws
13+
14+
rm -rf ~/openvino_download
15+
mkdir ~/openvino_download
16+
cd ~/openvino_download
17+
wget https://github.com/Megvii-BaseDetection/YOLOX/releases/download/0.1.1rc0/$MODEL.onnx
18+
# if $1==yolox_tiny or $1==yolox_nano
19+
if [ "$MODEL" == "yolox_tiny" ] || [ "$MODEL" == "yolox_nano" ]; then
20+
python3 $MO --input_model ./$MODEL.onnx --input_shape [1,3,416,416] --data_type FP16 --output_dir ./
21+
else
22+
python3 $MO --input_model ./$MODEL.onnx --input_shape [1,3,640,640] --data_type FP16 --output_dir ./
23+
fi
24+
echo "=========================================="
25+
echo "Model Optimizer finished"
26+
echo "=========================================="
27+
28+
cp -r ./* $ROS2_WS/src/YOLOX-ROS/weights/openvino/
29+
cd $ROS2_WS
30+
colcon build --symlink-install
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import launch
2+
import launch_ros.actions
3+
from launch.actions import IncludeLaunchDescription
4+
from ament_index_python.packages import get_package_share_directory
5+
from launch.launch_description_sources import PythonLaunchDescriptionSource
6+
7+
def generate_launch_description():
8+
yolox_ros_share_dir = get_package_share_directory('yolox_ros_py')
9+
10+
webcam = launch_ros.actions.Node(
11+
package="v4l2_camera", executable="v4l2_camera_node",
12+
parameters=[
13+
{"image_size": [640,480]},
14+
],
15+
)
16+
yolox_openvino = launch_ros.actions.Node(
17+
package="yolox_ros_py", executable="yolox_openvino",output="screen",
18+
parameters=[
19+
{"image_size/width": 640},
20+
{"image_size/height": 480},
21+
{"device" : 'CPU'},
22+
{"model_path" : yolox_ros_share_dir+"/yolox_m.xml"},
23+
{"conf" : 0.3},
24+
],
25+
)
26+
27+
rqt_graph = launch_ros.actions.Node(
28+
package="rqt_graph", executable="rqt_graph",
29+
)
30+
31+
return launch.LaunchDescription([
32+
webcam,
33+
yolox_openvino,
34+
rqt_graph
35+
])

yolox_ros_py/package.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
<name>yolox_ros_py</name>
55
<version>1.0.0</version>
66
<description>The yolox_ros_py package</description>
7-
<maintainer email="[email protected]">ubuntu</maintainer>
7+
<maintainer email="[email protected]">Ar-Ray-code</maintainer>
88
<license>Apache License, Version 2.0</license>
99
<author email="[email protected]">Ar-Ray-code</author>
1010

11+
<test_depend>ament_copyright</test_depend>
12+
<test_depend>ament_flake8</test_depend>
13+
<test_depend>ament_pep257</test_depend>
14+
<test_depend>python3-pytest</test_depend>
1115
<exec_depend>rclpy</exec_depend>
1216

1317
<export>

yolox_ros_py/setup.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
from setuptools import setup
2+
13
import os
24
from glob import glob
3-
from setuptools import setup
45
from urllib.request import urlretrieve
56

67
package_name = 'yolox_ros_py'
78

9+
810
YOLOX_S_WEIGHTS = 'yolox_s.pth'
911
YOLOX_M_WEIGHTS = 'yolox_m.pth'
1012
YOLOX_L_WEIGHTS = 'yolox_l.pth'
@@ -53,36 +55,36 @@
5355
# if not os.path.exists(YOLOX_TINY_WEIGHTS_PATH):
5456
# urlretrieve(YOLOX_TINY_WEIGHTS_URL, YOLOX_TINY_WEIGHTS_PATH)
5557

58+
5659
setup(
5760
name=package_name,
5861
version='1.0.0',
59-
packages=[],
60-
py_modules= [
61-
'scripts.yolox_ros',
62+
packages=[package_name],
63+
data_files=[
64+
('share/ament_index/resource_index/packages',
65+
['resource/' + package_name]),
66+
('share/' + package_name, ['package.xml']),
67+
(os.path.join('share', package_name), glob('./launch/*.launch.py')),
68+
(os.path.join('share', package_name), glob('../weights/*.pth')),
69+
(os.path.join('share', package_name), glob('../weights/openvino/*')),
6270
],
71+
# py_modules= [
72+
# 'scripts.yolox_ros',
73+
# 'scripts.yolox_openvino',
74+
# ],
6375
install_requires=['setuptools'],
6476
zip_safe=True,
6577
author='Ar-Ray-code',
6678
author_email="[email protected]",
67-
maintainer='user',
79+
maintainer='Ar-Ray-code',
6880
maintainer_email="[email protected]",
69-
keywords=['ROS', 'ROS2'],
70-
classifiers=[
71-
'Intended Audience :: Developers',
72-
'License :: OSI Approved :: Apache Software License',
73-
'Programming Language :: Python',
74-
'Topic :: Software Development',
75-
],
7681
description='YOLOX + ROS2 Foxy',
7782
license='Apache License, Version 2.0',
7883
tests_require=['pytest'],
7984
entry_points={
8085
'console_scripts': [
81-
'yolox_ros = scripts.yolox_ros:ros_main',
86+
'yolox_ros = yolox_ros_py.yolox_ros:ros_main',
87+
'yolox_openvino = yolox_ros_py.yolox_openvino:ros_main',
8288
],
8389
},
84-
data_files=[
85-
(os.path.join('share', package_name), glob('launch/*.launch.py')),
86-
(os.path.join('share', package_name), glob('../weights/*.pth')),
87-
],
8890
)

yolox_ros_py/yolox_ros_py/__init__.py

Whitespace-only changes.
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
#!/usr/bin/env python3
2+
# -*- coding:utf-8 -*-
3+
# Copyright (c) Megvii, Inc. and its affiliates.
4+
5+
# ROS2 rclpy -- Ar-Ray-code 2021
6+
import rclpy
7+
8+
import argparse
9+
import logging as log
10+
import os
11+
import sys
12+
13+
import cv2
14+
import numpy as np
15+
16+
from openvino.inference_engine import IECore
17+
18+
from yolox.data.data_augment import preproc as preprocess
19+
from yolox.data.datasets import COCO_CLASSES
20+
from yolox.utils import multiclass_nms, demo_postprocess, vis
21+
22+
# ROS2 =====================================
23+
import rclpy
24+
from rclpy.node import Node
25+
26+
from std_msgs.msg import Header
27+
from cv_bridge import CvBridge
28+
from sensor_msgs.msg import Image
29+
30+
from bboxes_ex_msgs.msg import BoundingBoxes
31+
from bboxes_ex_msgs.msg import BoundingBox
32+
33+
# from darkself.net_ros_msgs.msg import BoundingBoxes
34+
# from darkself.net_ros_msgs.msg import BoundingBox
35+
36+
class yolox_ros(Node):
37+
def __init__(self) -> None:
38+
39+
# ROS2 init
40+
super().__init__('yolox_ros')
41+
42+
self.setting_yolox_exp()
43+
44+
if (self.imshow_isshow):
45+
cv2.namedWindow("YOLOX")
46+
47+
self.bridge = CvBridge()
48+
49+
self.pub = self.create_publisher(BoundingBoxes,"yolox/bounding_boxes", 10)
50+
self.pub_image = self.create_publisher(Image,"yolox/image_raw", 10)
51+
self.sub = self.create_subscription(Image,"image_raw",self.imageflow_callback, 10)
52+
53+
def setting_yolox_exp(self) -> None:
54+
# set environment variables for distributed training
55+
56+
# ==============================================================
57+
58+
WEIGHTS_PATH = '/home/ubuntu/ros2_ws/install/yolox_ros_py/share/yolox_ros_py/yolox_s.xml'
59+
60+
self.declare_parameter('imshow_isshow',True)
61+
62+
self.declare_parameter('model_path', WEIGHTS_PATH)
63+
self.declare_parameter('conf', 0.3)
64+
self.declare_parameter('device', "CPU")
65+
66+
self.declare_parameter('image_size/width', 640)
67+
self.declare_parameter('image_size/height', 480)
68+
69+
70+
# =============================================================
71+
self.imshow_isshow = self.get_parameter('imshow_isshow').value
72+
73+
model_path = self.get_parameter('model_path').value
74+
self.conf = self.get_parameter('conf').value
75+
device = self.get_parameter('device').value
76+
77+
self.input_width = self.get_parameter('image_size/width').value
78+
self.input_height = self.get_parameter('image_size/height').value
79+
80+
# ==============================================================
81+
82+
print('Creating Inference Engine')
83+
ie = IECore()
84+
print(f'Reading the self.network: {model_path}')
85+
# (.xml and .bin files) or (.onnx file)
86+
87+
self.net = ie.read_network(model=model_path)
88+
print('Configuring input and output blobs')
89+
# Get names of input and output blobs
90+
self.input_blob = next(iter(self.net.input_info))
91+
self.out_blob = next(iter(self.net.outputs))
92+
93+
# Set input and output precision manually
94+
self.net.input_info[self.input_blob].precision = 'FP32'
95+
self.net.outputs[self.out_blob].precision = 'FP16'
96+
97+
# Get a number of classes recognized by a model
98+
num_of_classes = max(self.net.outputs[self.out_blob].shape)
99+
100+
print('Loading the model to the plugin')
101+
self.exec_net = ie.load_network(network=self.net, device_name=device)
102+
103+
104+
def yolox2bboxes_msgs(self, bboxes, scores, cls, cls_names, img_header:Header):
105+
bboxes_msg = BoundingBoxes()
106+
bboxes_msg.header = img_header
107+
i = 0
108+
for bbox in bboxes:
109+
one_box = BoundingBox()
110+
one_box.xmin = int(bbox[0])
111+
one_box.ymin = int(bbox[1])
112+
one_box.xmax = int(bbox[2])
113+
one_box.ymax = int(bbox[3])
114+
one_box.probability = float(scores[i])
115+
one_box.class_id = str(cls_names[int(cls[i])])
116+
bboxes_msg.bounding_boxes.append(one_box)
117+
i = i+1
118+
119+
return bboxes_msg
120+
121+
def imageflow_callback(self,msg:Image) -> None:
122+
try:
123+
# fps start
124+
start_time = cv2.getTickCount()
125+
bboxes = BoundingBoxes()
126+
img_rgb = self.bridge.imgmsg_to_cv2(msg,"bgr8")
127+
128+
origin_img = img_rgb
129+
_, _, h, w = self.net.input_info[self.input_blob].input_data.shape
130+
mean = (0.485, 0.456, 0.406)
131+
std = (0.229, 0.224, 0.225)
132+
image, ratio = preprocess(origin_img, (h, w), mean, std)
133+
134+
res = self.exec_net.infer(inputs={self.input_blob: image})
135+
res = res[self.out_blob]
136+
137+
# Predictions is result
138+
predictions = demo_postprocess(res, (h, w), p6=False)[0]
139+
140+
boxes = predictions[:, :4]
141+
scores = predictions[:, 4, None] * predictions[:, 5:]
142+
143+
boxes_xyxy = np.ones_like(boxes)
144+
boxes_xyxy[:, 0] = boxes[:, 0] - boxes[:, 2]/2.
145+
boxes_xyxy[:, 1] = boxes[:, 1] - boxes[:, 3]/2.
146+
boxes_xyxy[:, 2] = boxes[:, 0] + boxes[:, 2]/2.
147+
boxes_xyxy[:, 3] = boxes[:, 1] + boxes[:, 3]/2.
148+
boxes_xyxy /= ratio
149+
dets = multiclass_nms(boxes_xyxy, scores, nms_thr=0.45, score_thr=0.1)
150+
151+
if dets is not None:
152+
final_boxes = dets[:, :4]
153+
final_scores, final_cls_inds = dets[:, 4], dets[:, 5]
154+
origin_img = vis(origin_img, final_boxes, final_scores, final_cls_inds,
155+
conf=self.conf, class_names=COCO_CLASSES)
156+
# ==============================================================
157+
end_time = cv2.getTickCount()
158+
time_took = (end_time - start_time) / cv2.getTickFrequency()
159+
160+
# rclpy log FPS
161+
self.get_logger().info(f'FPS: {1 / time_took}')
162+
bboxes = self.yolox2bboxes_msgs(dets[:, :4], final_scores, final_cls_inds, COCO_CLASSES, msg.header)
163+
self.get_logger().info(f'bboxes: {bboxes}')
164+
try:
165+
bboxes = self.yolox2bboxes_msgs(dets[:, :4], final_scores, final_cls_inds, COCO_CLASSES, msg.header)
166+
167+
if (self.imshow_isshow):
168+
cv2.imshow("YOLOX",origin_img)
169+
cv2.waitKey(1)
170+
171+
except:
172+
self.get_logger().info('No object detected')
173+
if (self.imshow_isshow):
174+
cv2.imshow("YOLOX",origin_img)
175+
cv2.waitKey(1)
176+
177+
self.pub.publish(bboxes)
178+
self.pub_image.publish(self.bridge.cv2_to_imgmsg(img_rgb,"bgr8"))
179+
180+
except:
181+
pass
182+
183+
# origin_img is output
184+
185+
def ros_main(args = None) -> None:
186+
rclpy.init(args=args)
187+
188+
yolox_ros_class = yolox_ros()
189+
rclpy.spin(yolox_ros_class)
190+
191+
yolox_ros_class.destroy_node()
192+
rclpy.shutdown()
193+
cv2.destroyAllWindows()
194+
195+
if __name__ == "__main__":
196+
ros_main()

0 commit comments

Comments
 (0)