-
Notifications
You must be signed in to change notification settings - Fork 9
/
image_bounding_box.cpp
120 lines (104 loc) · 3.84 KB
/
image_bounding_box.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* Copyright 2018 Bonn-Rhein-Sieg University
*
* Author: Minh Nguyen, Santosh Thoduka
*
*/
#include <vector>
#include <string>
#include <stdexcept>
#include <tf/transform_listener.h>
#include <mas_perception_libs/bounding_box_2d.h>
#include <mas_perception_libs/image_bounding_box.h>
namespace mas_perception_libs
{
ImageBoundingBox::ImageBoundingBox(const sensor_msgs::Image &pImageMsg,
const sensor_msgs::CameraInfo &pCameraInfo,
const mas_perception_msgs::BoundingBoxList &pBoundingBoxList)
{
if (pBoundingBoxList.bounding_boxes.empty())
{
throw std::invalid_argument("bounding box list is empty");
}
// get camera model
mCameraModel.fromCameraInfo(pCameraInfo);
// convert to CV image
try
{
mImagePtr = cv_bridge::toCvCopy(pImageMsg, sensor_msgs::image_encodings::BGR8);
}
catch (cv_bridge::Exception &ex)
{
std::ostringstream message;
message << "can't convert ROS image message to CV image: " << ex.what();
throw std::runtime_error(message.str());
}
// wait for transform
std::string object_frame_id = pBoundingBoxList.header.frame_id;
std::string image_frame_id = pImageMsg.header.frame_id;
try
{
mTfListener.waitForTransform(object_frame_id, image_frame_id,
pImageMsg.header.stamp, ros::Duration(1.0));
}
catch (tf::TransformException &ex)
{
std::ostringstream message;
message << "caught exception waiting for transform: " << ex.what();
throw std::runtime_error(message.str());
}
for (const auto &boundingBox : pBoundingBoxList.bounding_boxes)
{
// transform vertices to image frame
std::vector<cv::Point2f> imageVertices;
for (const auto &vertice : boundingBox.vertices)
{
geometry_msgs::PointStamped point;
geometry_msgs::PointStamped transformedPoint;
point.point = vertice;
point.header.frame_id = object_frame_id;
point.header.stamp = pImageMsg.header.stamp;
try
{
mTfListener.transformPoint(image_frame_id, point, transformedPoint);
}
catch (tf::TransformException &ex)
{
std::ostringstream message;
message << "failed to transform point from frame '" << object_frame_id
<< "' to frame '" << image_frame_id << "': " << ex.what();
throw std::runtime_error(message.str());
}
cv::Point3d point_xyz(transformedPoint.point.x, transformedPoint.point.y, transformedPoint.point.z);
cv::Point2f uv;
uv = mCameraModel.project3dToPixel(point_xyz);
imageVertices.push_back(uv);
}
cv::Mat croppedImage = cropImage(mImagePtr->image, imageVertices, 5);
cv_bridge::CvImage image_msg;
image_msg.encoding = sensor_msgs::image_encodings::BGR8;
image_msg.image = croppedImage;
image_msg.header = pImageMsg.header;
mCroppedImageList.images.push_back(*image_msg.toImageMsg());
mBoxVerticesVector.push_back(imageVertices);
}
}
ImageBoundingBox::~ImageBoundingBox() = default;
sensor_msgs::ImagePtr
drawLabeledBoxesImgMsg(const sensor_msgs::Image& pImageMsg, std::vector<BoundingBox2D> pBoxes,
int pThickness, double pFontScale)
{
cv_bridge::CvImagePtr cvImagePtr;
try
{
cvImagePtr = cv_bridge::toCvCopy(pImageMsg, sensor_msgs::image_encodings::BGR8);
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("error converting message to CV image %s", e.what());
throw;
}
drawLabeledBoxes(cvImagePtr->image, pBoxes, pThickness, pFontScale);
return cvImagePtr->toImageMsg();
}
} // namespace mas_perception_libs