29 #include <std_msgs/Float32MultiArray.h> 30 #include "find_object_2d/ObjectsStamped.h" 31 #include "find_object_2d/DetectionInfo.h" 39 objFramePrefix_(
"object"),
50 pub_ = nh.
advertise<std_msgs::Float32MultiArray>(
"objects", 1);
60 if(info.
objDetected_.size() && !depth.empty() && depthConstant != 0.0f)
62 std::vector<tf::StampedTransform> transforms;
63 char multiSubId =
'b';
65 QMultiMap<int, QSize>::const_iterator iterSizes=info.
objDetectedSizes_.constBegin();
66 for(QMultiMap<int, QTransform>::const_iterator iter=info.
objDetected_.constBegin();
72 float objectWidth = iterSizes->width();
73 float objectHeight = iterSizes->height();
78 multiSuffix = QString(
"_") + multiSubId++;
87 QPointF center = iter->map(QPointF(objectWidth/2, objectHeight/2));
88 cv::Vec3f center3D = this->
getDepth(depth,
89 center.x()+0.5f, center.y()+0.5f,
90 float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f,
91 1.0f/depthConstant, 1.0f/depthConstant);
97 QPointF xAxis = iter->map(QPointF(3*objectWidth/4, objectHeight/2));
99 xAxis.x()+0.5f, xAxis.y()+0.5f,
100 float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f,
101 1.0f/depthConstant, 1.0f/depthConstant);
103 QPointF yAxis = iter->map(QPointF(objectWidth/2, 3*objectHeight/4));
105 yAxis.x()+0.5f, yAxis.y()+0.5f,
106 float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f,
107 1.0f/depthConstant, 1.0f/depthConstant);
110 if((std::isfinite(center3D.val[2]) &&
usePnP_) ||
111 (std::isfinite(center3D.val[0]) && std::isfinite(center3D.val[1]) && std::isfinite(center3D.val[2]) &&
112 std::isfinite(axisEndX.val[0]) && std::isfinite(axisEndX.val[1]) && std::isfinite(axisEndX.val[2]) &&
113 std::isfinite(axisEndY.val[0]) && std::isfinite(axisEndY.val[1]) && std::isfinite(axisEndY.val[2])))
125 std::vector<cv::Point3f> objectPoints(4);
126 std::vector<cv::Point2f> imagePoints(4);
128 objectPoints[0] = cv::Point3f(-0.5, -(objectHeight/objectWidth)/2.0
f,0);
129 objectPoints[1] = cv::Point3f(0.5,-(objectHeight/objectWidth)/2.0
f,0);
130 objectPoints[2] = cv::Point3f(0.5,(objectHeight/objectWidth)/2.0
f,0);
131 objectPoints[3] = cv::Point3f(-0.5,(objectHeight/objectWidth)/2.0
f,0);
133 QPointF pt = iter->map(QPointF(0, 0));
134 imagePoints[0] = cv::Point2f(pt.x(), pt.y());
135 pt = iter->map(QPointF(objectWidth, 0));
136 imagePoints[1] = cv::Point2f(pt.x(), pt.y());
137 pt = iter->map(QPointF(objectWidth, objectHeight));
138 imagePoints[2] = cv::Point2f(pt.x(), pt.y());
139 pt = iter->map(QPointF(0, objectHeight));
140 imagePoints[3] = cv::Point2f(pt.x(), pt.y());
142 cv::Mat cameraMatrix = cv::Mat::eye(3,3,CV_64FC1);
143 cameraMatrix.at<
double>(0,0) = 1.0
f/depthConstant;
144 cameraMatrix.at<
double>(1,1) = 1.0
f/depthConstant;
145 cameraMatrix.at<
double>(0,2) =
float(depth.cols/2)-0.5f;
146 cameraMatrix.at<
double>(1,2) =
float(depth.rows/2)-0.5f;
149 cv::Mat rvec(1,3, CV_64FC1);
150 cv::Mat tvec(1,3, CV_64FC1);
151 cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);
154 cv::Rodrigues(rvec, R);
156 R.at<
double>(0,0), R.at<
double>(0,1), R.at<
double>(0,2),
157 R.at<
double>(1,0), R.at<
double>(1,1), R.at<
double>(1,2),
158 R.at<
double>(2,0), R.at<
double>(2,1), R.at<
double>(2,2));
161 tvec.at<
double>(0)*(center3D.val[2]/tvec.at<
double>(2)),
162 tvec.at<
double>(1)*(center3D.val[2]/tvec.at<
double>(2)),
163 tvec.at<
double>(2)*(center3D.val[2]/tvec.at<
double>(2))));
167 tf::Vector3 xAxis(axisEndX.val[0] - center3D.val[0], axisEndX.val[1] - center3D.val[1], axisEndX.val[2] - center3D.val[2]);
169 tf::Vector3 yAxis(axisEndY.val[0] - center3D.val[0], axisEndY.val[1] - center3D.val[1], axisEndY.val[2] - center3D.val[2]);
171 tf::Vector3 zAxis = xAxis.cross(yAxis);
174 xAxis.x(), yAxis.x() ,zAxis.x(),
175 xAxis.y(), yAxis.y(), zAxis.y(),
176 xAxis.z(), yAxis.z(), zAxis.z());
178 transform.
setOrigin(tf::Vector3(center3D.val[0], center3D.val[1], center3D.val[2]));
184 transforms.push_back(transform);
188 ROS_WARN(
"Object %d detected, center 2D at (%f,%f), but invalid depth, cannot set frame \"%s\"! " 189 "(maybe object is too near of the camera or bad depth image)\n",
191 center.x(), center.y(),
192 QString(
"%1_%2").arg(
objFramePrefix_.c_str()).arg(
id).toStdString().c_str());
195 if(transforms.size())
203 std_msgs::Float32MultiArray msg;
204 find_object_2d::ObjectsStamped msgStamped;
205 find_object_2d::DetectionInfo infoMsg;
216 msg.data = std::vector<float>(info.
objDetected_.size()*12);
217 msgStamped.objects.data = std::vector<float>(info.
objDetected_.size()*12);
226 QMultiMap<int, QSize>::const_iterator iterSizes=info.
objDetectedSizes_.constBegin();
230 for(QMultiMap<int, QTransform>::const_iterator iter=info.
objDetected_.constBegin();
232 ++iter, ++iterSizes, ++iterFilePaths, ++infoIndex, ++iterInliers, ++iterOutliers)
236 msg.data[i] = msgStamped.objects.data[i] = iter.key(); ++i;
237 msg.data[i] = msgStamped.objects.data[i] = iterSizes->width(); ++i;
238 msg.data[i] = msgStamped.objects.data[i] = iterSizes->height(); ++i;
239 msg.data[i] = msgStamped.objects.data[i] = iter->m11(); ++i;
240 msg.data[i] = msgStamped.objects.data[i] = iter->m12(); ++i;
241 msg.data[i] = msgStamped.objects.data[i] = iter->m13(); ++i;
242 msg.data[i] = msgStamped.objects.data[i] = iter->m21(); ++i;
243 msg.data[i] = msgStamped.objects.data[i] = iter->m22(); ++i;
244 msg.data[i] = msgStamped.objects.data[i] = iter->m23(); ++i;
245 msg.data[i] = msgStamped.objects.data[i] = iter->m31(); ++i;
246 msg.data[i] = msgStamped.objects.data[i] = iter->m32(); ++i;
247 msg.data[i] = msgStamped.objects.data[i] = iter->m33(); ++i;
252 infoMsg.ids[infoIndex].data = iter.key();
253 infoMsg.widths[infoIndex].data = iterSizes->width();
254 infoMsg.heights[infoIndex].data = iterSizes->height();
255 infoMsg.file_paths[infoIndex].data = iterFilePaths.value().toStdString();
256 infoMsg.inliers[infoIndex].data = iterInliers.value();
257 infoMsg.outliers[infoIndex].data = iterOutliers.value();
258 infoMsg.homographies[infoIndex].data.resize(9);
259 infoMsg.homographies[infoIndex].data[0] = iter->m11();
260 infoMsg.homographies[infoIndex].data[1] = iter->m12();
261 infoMsg.homographies[infoIndex].data[2] = iter->m13();
262 infoMsg.homographies[infoIndex].data[3] = iter->m21();
263 infoMsg.homographies[infoIndex].data[4] = iter->m22();
264 infoMsg.homographies[infoIndex].data[5] = iter->m23();
265 infoMsg.homographies[infoIndex].data[6] = iter->m31();
266 infoMsg.homographies[infoIndex].data[7] = iter->m32();
267 infoMsg.homographies[infoIndex].data[8] = iter->m33();
277 msgStamped.header.frame_id = header.
frameId_.toStdString();
278 msgStamped.header.stamp.sec = header.
sec_;
279 msgStamped.header.stamp.nsec = header.
nsec_;
285 infoMsg.header.frame_id = header.
frameId_.toStdString();
286 infoMsg.header.stamp.sec = header.
sec_;
287 infoMsg.header.stamp.nsec = header.
nsec_;
298 if(!(x >=0 && x<depthImage.cols && y >=0 && y<depthImage.rows))
300 ROS_ERROR(
"Point must be inside the image (x=%d, y=%d), image size=(%d,%d)",
302 depthImage.cols, depthImage.rows);
304 std::numeric_limits<float>::quiet_NaN (),
305 std::numeric_limits<float>::quiet_NaN (),
306 std::numeric_limits<float>::quiet_NaN ());
316 bool isInMM = depthImage.type() == CV_16UC1;
319 float unit_scaling = isInMM?0.001f:1.0f;
320 float constant_x = unit_scaling / fx;
321 float constant_y = unit_scaling / fy;
322 float bad_point = std::numeric_limits<float>::quiet_NaN ();
328 depth = (float)depthImage.at<uint16_t>(y,x);
329 isValid = depth != 0.0f;
333 depth = depthImage.at<
float>(y,x);
334 isValid = std::isfinite(depth) && depth > 0.0f;
340 pt.val[0] = pt.val[1] = pt.val[2] = bad_point;
345 pt.val[0] = (float(x) - center_x) * depth * constant_x;
346 pt.val[1] = (float(y) - center_y) * depth * constant_y;
347 pt.val[2] = depth*unit_scaling;
static tf::Quaternion createQuaternionFromRPY(double roll, double pitch, double yaw)
void getRotation(Quaternion &q) const
tf::TransformBroadcaster tfBroadcaster_
ros::Publisher pubStamped_
QMultiMap< int, QString > objDetectedFilePaths_
QMultiMap< int, QSize > objDetectedSizes_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
void publish(const boost::shared_ptr< M > &message) const
QMultiMap< int, int > objDetectedInliersCount_
FindObjectROS(QObject *parent=0)
void objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)
QMultiMap< int, QTransform > objDetected_
std::string objFramePrefix_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void publish(const find_object::DetectionInfo &info, const find_object::Header &header, const cv::Mat &depth, float depthConstant)
QMultiMap< int, int > objDetectedOutliersCount_
cv::Vec3f getDepth(const cv::Mat &depthImage, int x, int y, float cx, float cy, float fx, float fy)
uint32_t getNumSubscribers() const
Quaternion normalized() const