Skip to content

Commit f7cfb4a

Browse files
authored
Merge pull request #2 from dash-robotics/develop_avi
Bounding box filter completed
2 parents 8a52162 + dfb2784 commit f7cfb4a

File tree

6 files changed

+249
-37
lines changed

6 files changed

+249
-37
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
cuboid_detection/bags/*
22

3+
.vscode/
4+
35
# Prerequisites
46
*.d
57

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
#!/usr/bin/env python
22
from __future__ import print_function
33

4-
import roslib
54
import sys
6-
import rospy
5+
76
import cv2
7+
import numpy as np
8+
import rospy
9+
import roslib
810
from std_msgs.msg import String
911
from sensor_msgs.msg import Image
1012
from cv_bridge import CvBridge, CvBridgeError
11-
import numpy as np
1213

1314
from color_object_detection.msg import Rectangle
1415

15-
class image_converter:
16+
class ImageConverter:
1617

1718
def __init__(self):
18-
self.image_pub = rospy.Publisher("/camera/color/image_raw/segmented",Image, queue_size=10)
19-
self.bbox_pub = rospy.Publisher("/bbox", Rectangle, queue_size=1000)
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)
2021

2122
self.bridge = CvBridge()
22-
self.image_sub = rospy.Subscriber("/camera/color/image_raw",Image,self.callback)
23+
self.image_sub = rospy.Subscriber("/camera/color/image_raw", Image, self.callback)
2324

2425
def callback(self,data):
2526
try:
@@ -31,39 +32,40 @@ def callback(self,data):
3132
hsv_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2HSV)
3233

3334
# define range of blue color in HSV
34-
lower_red1 = np.array([0,50,100])
35-
upper_red1 = np.array([10,255,255])
35+
lower_red1 = np.array([0, 50, 100])
36+
upper_red1 = np.array([10, 255, 255])
3637

37-
lower_red2 = np.array([175,50,100])
38-
upper_red2 = np.array([180,255,255])
38+
lower_red2 = np.array([175, 50, 100])
39+
upper_red2 = np.array([180, 255, 255])
3940

4041
# Threshold the HSV image to get only blue colors
4142
mask1 = cv2.inRange(hsv_image, lower_red1, upper_red1)
4243
mask2 = cv2.inRange(hsv_image, lower_red2, upper_red2)
4344
mask = cv2.bitwise_or(mask1,mask2)
44-
kernel = np.ones((5,5),np.uint8)
45+
kernel = np.ones((5, 5), np.uint8)
4546

46-
mask = cv2.erode(mask,kernel,iterations = 2)
47-
mask = cv2.dilate(mask,kernel,iterations = 2)
47+
mask = cv2.erode(mask, kernel, iterations=2)
48+
mask = cv2.dilate(mask, kernel, iterations=2)
4849

49-
ret,thresh = cv2.threshold(mask,200,255,0)
50+
ret,thresh = cv2.threshold(mask, 200, 255, 0)
5051
im, contours,hierarchy= cv2.findContours(thresh, 1, 2)
5152

5253
c = max(contours, key = cv2.contourArea)
5354

5455
cnt = contours[0]
55-
x,y,w,h = cv2.boundingRect(c)
56+
x, y, w, h = cv2.boundingRect(c)
5657

5758
# Bitwise-AND mask and original image
5859
# res1 = cv2.bitwise_and(cv_image,cv_image, mask= mask1)
5960
# res2 = cv2.bitwise_and(cv_image,cv_image, mask= mask2)
6061
# res = cv2.bitwise_or(res1, res2)
6162

62-
rect = Rectangle(x,y,x+w,y+h)
63+
d = 10
64+
rect = Rectangle(x - d, y - d, x + w + d, y + h + d)
6365
self.bbox_pub.publish(rect)
6466

65-
res = cv2.bitwise_and(cv_image,cv_image, mask= mask)
66-
cv2.rectangle(res,(x,y),(x+w,y+h),(0,255,0),2)
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)
6769

6870
# cv2.imshow("Image window", res)
6971
# cv2.waitKey(3)
@@ -74,8 +76,8 @@ def callback(self,data):
7476
print(e)
7577

7678
def main(args):
77-
rospy.init_node('image_converter', anonymous=True)
78-
ic = image_converter()
79+
rospy.init_node('object_detector', anonymous=True)
80+
ic = ImageConverter()
7981

8082
try:
8183
rospy.spin()
@@ -84,4 +86,4 @@ def main(args):
8486
cv2.destroyAllWindows()
8587

8688
if __name__ == '__main__':
87-
main(sys.argv)
89+
main(sys.argv)

cuboid_detection/CMakeLists.txt

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ find_package(catkin REQUIRED COMPONENTS
1414
pcl_ros
1515
roscpp
1616
sensor_msgs
17+
color_object_detection
1718
)
1819

1920
## System dependencies are found with CMake's conventions
@@ -139,15 +140,9 @@ include
139140
## Declare a C++ executable
140141
## With catkin_make all packages are built within a single CMake context
141142
## The recommended prefix ensures that target names across packages don't collide
142-
143-
## >>>>>>>>>>>>>>>>>>>>>>>
144-
## ADD YOUR PROGRAMS HERE
145-
146-
# add_executable(${PROJECT_NAME}_node src/cuboid_detection_node.cpp)
147-
# add_executable(example src/example.cpp)
148143
add_executable(ground_plane_segmentation src/ground_plane_segmentation.cpp)
149-
150-
## <<<<<<<<<<<<<<<<<<<<<<<
144+
add_executable(iterative_closest_point src/iterative_closest_point.cpp)
145+
add_executable(bbox_filter src/bbox_filter.cpp)
151146

152147
## Rename C++ executable without prefix
153148
## The above recommended prefix causes long target names, the following renames the
@@ -160,11 +155,6 @@ add_executable(ground_plane_segmentation src/ground_plane_segmentation.cpp)
160155
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
161156

162157
## Specify libraries to link a library or executable target against
163-
# target_link_libraries(${PROJECT_NAME}_node
164-
# ${catkin_LIBRARIES}
165-
# )
166-
# target_link_libraries(${PROJECT_NAME}
167-
# ${OpenCV_LIBS}
168-
# )
169-
# target_link_libraries(example ${catkin_LIBRARIES})
170158
target_link_libraries(ground_plane_segmentation ${catkin_LIBRARIES})
159+
target_link_libraries(iterative_closest_point ${catkin_LIBRARIES})
160+
target_link_libraries(bbox_filter ${catkin_LIBRARIES})
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<launch>
3+
4+
<!-- Launch ground plane segmentation -->
5+
<include file="$(find cuboid_detection)/launch/ground_plane_segmentation.launch"/>
6+
7+
<!-- Detect 2D bbox -->
8+
<node
9+
pkg="color_object_detection"
10+
type="object_detection.py"
11+
name="object_detection"
12+
output="screen">
13+
</node>
14+
15+
<!-- Filter points within the bbox -->
16+
<node
17+
pkg="cuboid_detection"
18+
type="bbox_filter"
19+
name="bbox_filter"
20+
output="screen">
21+
</node>
22+
23+
</launch>
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
Author: Avinash
3+
Version: 1.0.2
4+
Date: Apr 03, 2019
5+
*/
6+
7+
#include <iostream>
8+
#include <vector>
9+
#include <ros/ros.h>
10+
#include <sensor_msgs/CameraInfo.h>
11+
#include <sensor_msgs/PointCloud2.h>
12+
#include <pcl_ros/point_cloud.h>
13+
#include <pcl_ros/filters/extract_indices.h>
14+
#include <pcl_conversions/pcl_conversions.h>
15+
#include <color_object_detection/Rectangle.h>
16+
17+
using namespace std;
18+
19+
// Flags
20+
bool DEBUG = false;
21+
bool READ_INFO = true;
22+
23+
int bbox[4];
24+
int min_inlier[2];
25+
int max_inlier[2];
26+
27+
ros::Publisher pcl_pub;
28+
vector<double> proj_matrix;
29+
30+
bool within_bbox(float x, float y, float z)
31+
{
32+
// Check if projection matrix is read
33+
if (READ_INFO) return false;
34+
35+
// 3D to 2D projection
36+
float u = (proj_matrix[0] * x) + (proj_matrix[1] * y) + (proj_matrix[2] * z) + proj_matrix[3];
37+
float v = (proj_matrix[4] * x) + (proj_matrix[5] * y) + (proj_matrix[6] * z) + proj_matrix[7];
38+
float w = (proj_matrix[8] * x) + (proj_matrix[9] * y) + (proj_matrix[10] * z) + proj_matrix[11];
39+
40+
// Normalize the uv points
41+
u /= w;
42+
v /= w;
43+
44+
// Check if these points are within the 2D bbox
45+
if (bbox[0] < u && u < bbox[2]) {
46+
if (bbox[1] < v && v < bbox[3]) {
47+
return true;
48+
}
49+
}
50+
return false;
51+
}
52+
53+
/****************** Callbacks *********************/
54+
55+
void info_cb(const sensor_msgs::CameraInfoConstPtr& camInfo_msg)
56+
{
57+
if (READ_INFO)
58+
{
59+
cerr << "\nCamera Info:" << endl;
60+
for (int i = 0; i < 12; i++)
61+
{
62+
cerr << camInfo_msg->P[i] << " ";
63+
proj_matrix.push_back(camInfo_msg->P[i]);
64+
}
65+
READ_INFO = false;
66+
}
67+
}
68+
69+
void bbox_cb(const color_object_detection::Rectangle msg)
70+
{
71+
bbox[0] = msg.x1;
72+
bbox[1] = msg.y1;
73+
bbox[2] = msg.x2;
74+
bbox[3] = msg.y2;
75+
}
76+
77+
void pcl_cb(const sensor_msgs::PointCloud2ConstPtr& input)
78+
{
79+
// Convert the sensor_msgs/PointCloud2 data to pcl/PointCloud
80+
pcl::PCLPointCloud2::Ptr input_cloud_ptr(new pcl::PCLPointCloud2);
81+
pcl::PointCloud<pcl::PointXYZ>::Ptr pcl_cloud_ptr(new pcl::PointCloud<pcl::PointXYZ>);
82+
pcl_conversions::toPCL(*input, *input_cloud_ptr);
83+
pcl::fromPCLPointCloud2(*input_cloud_ptr, *pcl_cloud_ptr);
84+
85+
// Store the inliers
86+
pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
87+
88+
// Check inliers for all points `in the PCL
89+
for (int i = 0; i < pcl_cloud_ptr->size(); i++)
90+
{
91+
if (within_bbox(pcl_cloud_ptr->points[i].x, pcl_cloud_ptr->points[i].y, pcl_cloud_ptr->points[i].z))
92+
{
93+
inliers->indices.push_back(i);
94+
}
95+
}
96+
97+
// Extract the inliers
98+
pcl::PCLPointCloud2::Ptr output_ptr(new pcl::PCLPointCloud2);
99+
pcl::ExtractIndices<pcl::PCLPointCloud2> extract;
100+
extract.setInputCloud(input_cloud_ptr);
101+
extract.setIndices(inliers);
102+
extract.setNegative(false);
103+
extract.filter(*output_ptr);
104+
105+
// Convert to ROS data type
106+
sensor_msgs::PointCloud2 output;
107+
pcl_conversions::fromPCL(*output_ptr, output);
108+
pcl_pub.publish(output);
109+
}
110+
111+
int main(int argc, char** argv)
112+
{
113+
// Setup node
114+
ros::init(argc, argv, "bbox_filter");
115+
ros::NodeHandle nh;
116+
117+
// Subscribers
118+
ros::Subscriber bbox_sub = nh.subscribe("/object_detection/bbox", 1, bbox_cb);
119+
ros::Subscriber info_sub = nh.subscribe("/camera/color/camera_info", 1, info_cb);
120+
ros::Subscriber pcl_sub = nh.subscribe("/ground_plane_segmentation/points", 1, pcl_cb);
121+
122+
// Publisher
123+
pcl_pub = nh.advertise<sensor_msgs::PointCloud2>("/bbox_filter/points", 1);
124+
125+
// Spin
126+
ros::spin();
127+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
*********************************************************
3+
* *******************************************************
4+
* *********** Iterative Closest Point (ICP) ************
5+
* *******************************************************
6+
* ************ written by Avinash on 04-02-2019 *********
7+
*********************************************************
8+
*/
9+
10+
11+
#include <iostream>
12+
#include <ros/ros.h>
13+
#include <pcl_ros/point_cloud.h>
14+
#include <pcl_conversions/pcl_conversions.h>
15+
#include <pcl/io/pcd_io.h>
16+
#include <pcl/point_types.h>
17+
#include <pcl/registration/icp.h>
18+
#include <sensor_msgs/point_cloud_conversion.h>
19+
#include <sensor_msgs/PointCloud.h>
20+
#include <sensor_msgs/PointCloud2.h>
21+
22+
23+
typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
24+
static ros::Publisher icp_PCL_pub;
25+
26+
pcl::PointCloud<pcl::PointXYZ>::Ptr template_cuboid(new pcl::PointCloud<pcl::PointXYZ>);
27+
pcl::PointCloud<pcl::PointXYZ>::Ptr input_cuboid(new pcl::PointCloud<pcl::PointXYZ>);
28+
29+
int performICP()
30+
{
31+
pcl::IterativeClosestPoint <pcl::PointXYZ, pcl::PointXYZ> icp;
32+
icp.setInputSource(input_cuboid);
33+
icp.setInputTarget(template_cuboid);
34+
pcl::PointCloud <pcl::PointXYZ> Final;
35+
icp.align(Final);
36+
std::cout << "has converged:" << icp.hasConverged() << " score: " <<
37+
icp.getFitnessScore() << std::endl;
38+
std::cout << icp.getFinalTransformation() << std::endl;
39+
40+
//icp_PCL_pub.publish(icp.getFinalTransformation());
41+
42+
return (0);
43+
}
44+
45+
void rawPCL_cb(const sensor_msgs::PointCloud2::ConstPtr& msg)
46+
{
47+
pcl::PCLPointCloud2 pcl_pc2;
48+
pcl_conversions::toPCL(*msg,pcl_pc2);
49+
pcl::fromPCLPointCloud2(pcl_pc2,*input_cuboid);
50+
performICP();
51+
}
52+
53+
int main(int argc, char **argv)
54+
{
55+
ros::init(argc,argv,"iterative_closest_point");
56+
ros::NodeHandle nh;
57+
//icp_PCL_pub = nh.advertise<geometry_msgs::>("iterative_closest_point", 1000);
58+
ros::Subscriber raw_PCL_sub = nh.subscribe<sensor_msgs::PointCloud2>("/ground_plane_segmentation/points", 1000, rawPCL_cb);
59+
60+
if (pcl::io::loadPCDFile<pcl::PointXYZ> ("$/{workspaceFolder}/src/perception/cuboid_detection/templates/template_cuboid_L200_W100_H75.pcd", *template_cuboid) == -1) //* load the file
61+
{
62+
PCL_ERROR ("Couldn't read file test_pcd.pcd \n");
63+
return (-1);
64+
}
65+
66+
ros::spinOnce();
67+
return 0;
68+
}

0 commit comments

Comments
 (0)