Skip to content

Commit 851c6d3

Browse files
committed
Final submission
1 parent 9501336 commit 851c6d3

File tree

12 files changed

+2119
-1818
lines changed

12 files changed

+2119
-1818
lines changed

cuboid_detection/CMakeLists.txt

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ add_compile_options(-std=c++11)
88
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
99
## is used, also find other catkin packages
1010
find_package(catkin REQUIRED COMPONENTS
11+
rospy
12+
roscpp
13+
pcl_ros
14+
pcl_conversions
1115
cv_bridge
1216
image_transport
13-
pcl_conversions
14-
pcl_ros
15-
roscpp
17+
std_msgs
1618
sensor_msgs
17-
color_object_detection
19+
geometry_msgs
20+
message_generation
21+
eigen_conversions
1822
)
1923

2024
## System dependencies are found with CMake's conventions
@@ -54,11 +58,10 @@ include_directories(${OpenCV_INCLUDE_DIRS})
5458
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
5559

5660
## Generate messages in the 'msg' folder
57-
# add_message_files(
58-
# FILES
59-
# Message1.msg
60-
# Message2.msg
61-
# )
61+
add_message_files(
62+
FILES
63+
Rectangle.msg
64+
)
6265

6366
## Generate services in the 'srv' folder
6467
# add_service_files(
@@ -75,10 +78,11 @@ include_directories(${OpenCV_INCLUDE_DIRS})
7578
# )
7679

7780
## Generate added messages and services with any dependencies listed here
78-
# generate_messages(
79-
# DEPENDENCIES
80-
# sensor_msgs
81-
# )
81+
generate_messages(
82+
DEPENDENCIES
83+
sensor_msgs
84+
std_msgs
85+
)
8286

8387
################################################
8488
## Declare ROS dynamic reconfigure parameters ##
@@ -112,7 +116,7 @@ include_directories(${OpenCV_INCLUDE_DIRS})
112116
catkin_package(
113117
INCLUDE_DIRS include
114118
LIBRARIES cuboid_detection
115-
CATKIN_DEPENDS cv_bridge image_transport pcl_conversions pcl_ros roscpp sensor_msgs
119+
CATKIN_DEPENDS cv_bridge image_transport pcl_conversions pcl_ros roscpp sensor_msgs rospy std_msgs geometry_msgs message_generation eigen_conversions
116120
# DEPENDS system_lib
117121
)
118122

cuboid_detection/launch/bbox_filter.launch

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33

44
<!-- Launch ground plane segmentation -->
55
<include file="$(find cuboid_detection)/launch/ground_plane_segmentation.launch"/>
6-
<!-- <include file="$(find cuboid_detection)/launch/surface_normal_estimation.launch"/> -->
76

87
<!-- Detect 2D bbox -->
98
<node
10-
pkg="color_object_detection"
9+
pkg="cuboid_detection"
1110
type="object_detection.py"
1211
name="object_detection"
1312
output="screen">

cuboid_detection/launch/iterative_closest_point.launch

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33

44
<!-- Launch Bounding Box Filter -->
55
<include file="$(find cuboid_detection)/launch/bbox_filter.launch"/>
6-
<include file="$(find cuboid_detection)/launch/surface_normal_estimation.launch"/>
7-
86

7+
<!-- Launch surface normal estimation -->
8+
<include file="$(find cuboid_detection)/launch/surface_normal_estimation.launch"/>
9+
910
<!-- Run ICP node -->
1011
<node
1112
pkg="cuboid_detection"
@@ -26,7 +27,23 @@
2627
width: 0.075
2728
height: 0.1
2829
</rosparam>
30+
</node>
31+
32+
<!-- Display the 3D bounding box -->
33+
<node
34+
pkg="cuboid_detection"
35+
type="draw_bbox.py"
36+
name="draw_bbox"
37+
output="screen">
2938

39+
<!-- Set topics and params -->
40+
<rosparam>
41+
camera_info_topic: "/camera/color/camera_info"
42+
image_color_topic: "/camera/color/image_raw"
43+
bbox_points_topic: "/icp/bbox_points"
44+
extrinsics: "/camera/extrinsics/depth_to_color"
45+
output_topic: "/draw_bbox/image"
46+
</rosparam>
3047
</node>
3148

3249
</launch>

cuboid_detection/msg/Rectangle.msg

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
int64 x1
2+
int64 y1
3+
int64 x2
4+
int64 y2

cuboid_detection/package.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,40 @@
5555
<build_depend>roscpp</build_depend>
5656
<build_depend>sensor_msgs</build_depend>
5757
<build_depend>libpcl-all-dev</build_depend>
58+
<build_depend>rospy</build_depend>
59+
<build_depend>std_msgs</build_depend>
60+
<build_depend>geometry_msgs</build_depend>
61+
<build_depend>vision_msgs</build_depend>
62+
<build_depend>message_generation</build_depend>
63+
<build_depend>eigen_conversions</build_depend>
64+
5865
<build_export_depend>cv_bridge</build_export_depend>
5966
<build_export_depend>image_transport</build_export_depend>
6067
<build_export_depend>pcl_conversions</build_export_depend>
6168
<build_export_depend>pcl_ros</build_export_depend>
6269
<build_export_depend>roscpp</build_export_depend>
6370
<build_export_depend>sensor_msgs</build_export_depend>
71+
<build_export_depend>rospy</build_export_depend>
72+
<build_export_depend>std_msgs</build_export_depend>
73+
<build_export_depend>geometry_msgs</build_export_depend>
74+
<build_export_depend>vision_msgs</build_export_depend>
75+
<build_export_depend>message_generation</build_export_depend>
76+
<build_export_depend>eigen_conversions</build_export_depend>
77+
6478
<exec_depend>libpcl-all</exec_depend>
6579
<exec_depend>cv_bridge</exec_depend>
6680
<exec_depend>image_transport</exec_depend>
6781
<exec_depend>pcl_conversions</exec_depend>
6882
<exec_depend>pcl_ros</exec_depend>
6983
<exec_depend>roscpp</exec_depend>
7084
<exec_depend>sensor_msgs</exec_depend>
85+
<exec_depend>rospy</exec_depend>
86+
<exec_depend>std_msgs</exec_depend>
87+
<exec_depend>geometry_msgs</exec_depend>
88+
<exec_depend>vision_msgs</exec_depend>
89+
<exec_depend>message_runtime</exec_depend>
90+
<exec_depend>message_generation</exec_depend>
91+
<exec_depend>eigen_conversions</exec_depend>
7192

7293

7394
<!-- The export tag contains other, unspecified, tags -->
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#!/usr/bin/env python
2+
3+
# Python 2/3 compatibility
4+
from __future__ import print_function
5+
6+
# Built-in modules
7+
import os
8+
import sys
9+
10+
# External modules
11+
import cv2
12+
import numpy as np
13+
14+
# ROS modules
15+
import rospy
16+
import ros_numpy
17+
import message_filters
18+
from cv_bridge import CvBridge, CvBridgeError
19+
from sensor_msgs.msg import Image, CameraInfo, PointCloud2
20+
from realsense2_camera.msg import Extrinsics
21+
22+
# Globals
23+
CV_BRIDGE = CvBridge()
24+
BBOX_POINTS = None
25+
EXTRINSICS = None
26+
27+
28+
def ext_callback(ext_msg):
29+
global EXTRINSICS
30+
if EXTRINSICS is None:
31+
extrinsic_matrix = np.eye(4)
32+
extrinsic_matrix[:3, :3] = np.asarray(ext_msg.rotation).reshape(3, 3)
33+
extrinsic_matrix[:3, -1] = np.asarray(ext_msg.translation)
34+
EXTRINSICS = extrinsic_matrix
35+
print('\nExtrinsics:\n', EXTRINSICS)
36+
37+
38+
def bbox_callback(bbox_msg):
39+
global BBOX_POINTS
40+
BBOX_POINTS = ros_numpy.point_cloud2.pointcloud2_to_array(bbox_msg)
41+
BBOX_POINTS = np.asarray(BBOX_POINTS.tolist())
42+
43+
44+
def callback(img_msg, info_msg, image_pub):
45+
# Read image using CV bridge
46+
try:
47+
img = CV_BRIDGE.imgmsg_to_cv2(img_msg, 'bgr8')
48+
except CvBridgeError as e:
49+
rospy.logerr(e)
50+
return
51+
52+
# Extract points from message
53+
if (BBOX_POINTS is None) or (EXTRINSICS is None): return
54+
bbox3D = BBOX_POINTS
55+
bbox3D = np.hstack((bbox3D, np.full((bbox3D.shape[0], 1), 1)))
56+
57+
# Project 3D to 2D and filter bbox within image boundaries
58+
P = np.matrix(info_msg.P).reshape(3, 4)
59+
M = np.matmul(P, EXTRINSICS)
60+
bbox2D = np.matmul(M, bbox3D.T).T
61+
bbox2D = bbox2D / bbox2D[:, -1]
62+
bbox2D = bbox2D[:, :2].astype('int').tolist()
63+
64+
# Draw the projected 3D bbox
65+
color = (0, 255, 0)
66+
cv2.line(img, tuple(bbox2D[0]), tuple(bbox2D[1]), color, 2)
67+
cv2.line(img, tuple(bbox2D[0]), tuple(bbox2D[2]), color, 2)
68+
cv2.line(img, tuple(bbox2D[0]), tuple(bbox2D[4]), color, 2)
69+
cv2.line(img, tuple(bbox2D[1]), tuple(bbox2D[3]), color, 2)
70+
cv2.line(img, tuple(bbox2D[1]), tuple(bbox2D[5]), color, 2)
71+
cv2.line(img, tuple(bbox2D[2]), tuple(bbox2D[3]), color, 2)
72+
cv2.line(img, tuple(bbox2D[2]), tuple(bbox2D[6]), color, 2)
73+
cv2.line(img, tuple(bbox2D[3]), tuple(bbox2D[7]), color, 2)
74+
cv2.line(img, tuple(bbox2D[4]), tuple(bbox2D[5]), color, 2)
75+
cv2.line(img, tuple(bbox2D[4]), tuple(bbox2D[6]), color, 2)
76+
cv2.line(img, tuple(bbox2D[5]), tuple(bbox2D[7]), color, 2)
77+
cv2.line(img, tuple(bbox2D[6]), tuple(bbox2D[7]), color, 2)
78+
79+
# Publish the projected bbox image
80+
try:
81+
image_pub.publish(CV_BRIDGE.cv2_to_imgmsg(img, "bgr8"))
82+
except CvBridgeError as e:
83+
rospy.logerr(e)
84+
85+
86+
def listener():
87+
# Start node
88+
rospy.init_node('draw_bbox', anonymous=True)
89+
90+
# Handle params
91+
camera_info = rospy.get_param('~camera_info_topic')
92+
image_color = rospy.get_param('~image_color_topic')
93+
bbox_points = rospy.get_param('~bbox_points_topic')
94+
extrinsics = rospy.get_param('~extrinsics')
95+
output_topic = rospy.get_param('~output_topic')
96+
97+
# Log info
98+
rospy.loginfo('Current PID: [%d]' % os.getpid())
99+
rospy.loginfo('CameraInfo topic: %s' % camera_info)
100+
rospy.loginfo('Image topic: %s' % image_color)
101+
rospy.loginfo('Bbox topic: %s' % bbox_points)
102+
rospy.loginfo('Extrinsics topic: %s' % extrinsics)
103+
rospy.loginfo('Output topic: %s' % output_topic)
104+
105+
# Subscribe to topics
106+
info_sub = message_filters.Subscriber(camera_info, CameraInfo)
107+
image_sub = message_filters.Subscriber(image_color, Image)
108+
bbox_sub = rospy.Subscriber(bbox_points, PointCloud2, bbox_callback)
109+
ext_sub = rospy.Subscriber(extrinsics, Extrinsics, ext_callback)
110+
111+
# Publish output topic
112+
image_pub = rospy.Publisher(output_topic, Image, queue_size=5)
113+
114+
# Synchronize the topics by time
115+
ats = message_filters.ApproximateTimeSynchronizer(
116+
[image_sub, info_sub], queue_size=10, slop=0.1)
117+
ats.registerCallback(callback, image_pub)
118+
119+
# Keep python from exiting until this node is stopped
120+
try:
121+
rospy.spin()
122+
except rospy.ROSInterruptException:
123+
rospy.loginfo('Shutting down')
124+
125+
126+
if __name__ == '__main__':
127+
# Start node
128+
listener()
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/usr/bin/env python
2+
from __future__ import print_function
3+
4+
import sys
5+
6+
import cv2
7+
import numpy as np
8+
import rospy
9+
import roslib
10+
from std_msgs.msg import String
11+
from sensor_msgs.msg import Image
12+
from cv_bridge import CvBridge, CvBridgeError
13+
14+
from color_object_detection.msg import Rectangle
15+
16+
class ImageConverter:
17+
18+
def __init__(self):
19+
self.image_pub = rospy.Publisher("/object_detection/image_segmented",Image, queue_size=10)
20+
self.bbox_pub = rospy.Publisher("/object_detection/bbox", Rectangle, queue_size=100)
21+
22+
self.bridge = CvBridge()
23+
self.image_sub = rospy.Subscriber("/camera/color/image_raw", Image, self.callback)
24+
25+
def callback(self,data):
26+
try:
27+
cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
28+
except CvBridgeError as e:
29+
print(e)
30+
31+
(rows,cols,channels) = cv_image.shape
32+
hsv_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2HSV)
33+
34+
# define range of blue color in HSV
35+
lower_red1 = np.array([0, 50, 100])
36+
upper_red1 = np.array([10, 255, 255])
37+
38+
lower_red2 = np.array([175, 50, 100])
39+
upper_red2 = np.array([180, 255, 255])
40+
41+
# Threshold the HSV image to get only blue colors
42+
mask1 = cv2.inRange(hsv_image, lower_red1, upper_red1)
43+
mask2 = cv2.inRange(hsv_image, lower_red2, upper_red2)
44+
mask = cv2.bitwise_or(mask1,mask2)
45+
kernel = np.ones((5, 5), np.uint8)
46+
47+
mask = cv2.erode(mask, kernel, iterations=2)
48+
mask = cv2.dilate(mask, kernel, iterations=2)
49+
50+
ret,thresh = cv2.threshold(mask, 200, 255, 0)
51+
im, contours,hierarchy= cv2.findContours(thresh, 1, 2)
52+
53+
c = max(contours, key = cv2.contourArea)
54+
55+
cnt = contours[0]
56+
x, y, w, h = cv2.boundingRect(c)
57+
58+
# Bitwise-AND mask and original image
59+
# res1 = cv2.bitwise_and(cv_image,cv_image, mask= mask1)
60+
# res2 = cv2.bitwise_and(cv_image,cv_image, mask= mask2)
61+
# res = cv2.bitwise_or(res1, res2)
62+
63+
d = 10
64+
rect = Rectangle(x - d, y - d, x + w + d, y + h + d)
65+
self.bbox_pub.publish(rect)
66+
67+
res = cv2.bitwise_and(cv_image, cv_image, mask= mask)
68+
cv2.rectangle(res, (x - d, y - d), (x + w + d, y + h + d), (0, 255, 0), 2)
69+
70+
# cv2.imshow("Image window", res)
71+
# cv2.waitKey(3)
72+
73+
try:
74+
self.image_pub.publish(self.bridge.cv2_to_imgmsg(res, "bgr8"))
75+
except CvBridgeError as e:
76+
print(e)
77+
78+
def main(args):
79+
rospy.init_node('object_detector', anonymous=True)
80+
ic = ImageConverter()
81+
82+
try:
83+
rospy.spin()
84+
except KeyboardInterrupt:
85+
print("Shutting down")
86+
cv2.destroyAllWindows()
87+
88+
if __name__ == '__main__':
89+
main(sys.argv)

0 commit comments

Comments
 (0)