2 #include <image_transport/image_transport.h> 3 #include <boost/thread/mutex.hpp> 4 #include <std_msgs/String.h> 5 #include <std_msgs/Int8.h> 11 #include <visp3/gui/vpDisplayX.h> 12 #include <visp3/gui/vpDisplayGDI.h> 13 #include <visp3/gui/vpDisplayOpenCV.h> 14 #include <visp3/core/vpImageConvert.h> 15 #include <visp3/core/vpPixelMeterConversion.h> 16 #include <visp3/blob/vpDot2.h> 17 #include <visp3/vision/vpPose.h> 20 #include <visp_ros/BlobTracker.h> 33 image_transport::ImageTransport m_it;
34 image_transport::Subscriber m_image_sub;
37 unsigned int m_queue_size;
41 vpDisplayX *m_display;
42 #elif defined(VISP_HAVE_GDI) 43 vpDisplayGDI *m_display;
44 #elif defined(VISP_HAVE_OPENCV) 45 vpDisplayOpenCV *m_display;
47 vpImage<unsigned char> m_I_grayscale;
48 std::vector<vpDot2> m_blob;
49 unsigned int m_nblobs;
51 vpCameraParameters m_cam;
52 std::vector<vpPoint> m_points_3d;
53 std::vector<vpImagePoint> m_points_2d;
54 vpHomogeneousMatrix m_cMo;
55 unsigned int m_thickness;
64 BlobTracker() : m_it(m_nh), m_image_sub(), m_tracker_publisher(), m_status_publisher(), m_queue_size(1), m_state(START),
65 m_lock(), m_display(NULL), m_I_grayscale(), m_blob(), m_nblobs(4), m_square_size(0.12), m_cam(), m_points_3d(), m_points_2d(), m_cMo(), m_thickness(2),
66 m_cam_px(-1), m_cam_py(-1), m_cam_u0(-1), m_cam_v0(-1), m_cam_kud(-1), m_cam_kdu(-1)
68 m_image_sub = m_it.subscribe(
"/camera/image_raw", m_queue_size, &BlobTracker::callback,
this);
69 m_tracker_publisher = m_nh.
advertise<visp_ros::BlobTracker>(
"blob_tracker/data", m_queue_size);
70 m_status_publisher = m_nh.
advertise<std_msgs::Int8>(
"blob_tracker/status", m_queue_size);
72 m_blob.resize(m_nblobs);
73 m_points_3d.resize(m_nblobs);
74 m_points_2d.resize(m_nblobs);
77 m_nh.
getParam(
"square_size", m_square_size);
87 if (m_cam_px < 0 || m_cam_py < 0 || m_cam_u0 < 0 || m_cam_v0 < 0) {
88 ROS_ERROR(
"Camera parameters are not set");
91 if (m_cam_kud == -1 || m_cam_kdu == -1) {
92 m_cam.initPersProjWithoutDistortion(m_cam_px, m_cam_py, m_cam_u0, m_cam_v0);
95 m_cam.initPersProjWithDistortion(m_cam_px, m_cam_py, m_cam_u0, m_cam_v0, m_cam_kud, m_cam_kdu);
110 m_points_3d[0] = vpPoint(-m_square_size / 2., -m_square_size / 2., 0);
111 m_points_3d[1] = vpPoint( m_square_size / 2., -m_square_size / 2., 0);
112 m_points_3d[2] = vpPoint( m_square_size / 2., m_square_size / 2., 0);
113 m_points_3d[3] = vpPoint(-m_square_size / 2., m_square_size / 2., 0);
119 while (m_nh.
ok() && ! quit) {
121 boost::mutex::scoped_lock(m_lock);
151 std::cout <<
"Image processing stopped..." << std::endl;
154 void init_display () {
156 m_display =
new vpDisplayX;
158 m_display =
new vpDisplayGDI;
159 #elif VISP_HAVE_OPENCV 160 m_display =
new vpDisplayOpenCV;
163 std::cout <<
"Image size: " << m_I_grayscale.getWidth() <<
" x " << m_I_grayscale.getHeight() << std::endl;
164 std::cout <<
"Camera parameters:\n" << m_cam << std::endl;
165 m_display->init(m_I_grayscale, 80, m_I_grayscale.getHeight()+20,
"Image processing");
169 void display(
const sensor_msgs::ImageConstPtr& msg) {
172 vpImageConvert::convert(cv_frame, m_I_grayscale);
174 if (m_display == NULL) {
178 vpDisplay::display(m_I_grayscale);
179 vpDisplay::displayText(m_I_grayscale, 20, 20,
"Click to start initialisation", vpColor::red);
180 vpDisplay::flush(m_I_grayscale);
182 if (vpDisplay::getClick(m_I_grayscale,
false)) {
186 ROS_ERROR(
"cv_bridge exception: %s", e.what());
191 void callback(
const sensor_msgs::ImageConstPtr& msg) {
192 boost::mutex::scoped_lock(m_lock);
197 std_msgs::Int8 status_msg;
199 m_status_publisher.publish(status_msg);
207 std_msgs::Int8 status_msg;
209 m_status_publisher.publish(status_msg);
212 vpImageConvert::convert(cv_frame, m_I_grayscale);
214 vpDisplay::display(m_I_grayscale);
215 vpDisplay::displayText(m_I_grayscale, 20, 20,
"Click in the 4 blobs clockwise to initialise the tracker", vpColor::red);
216 vpDisplay::flush(m_I_grayscale);
218 for (
unsigned int i = 0; i < m_blob.size(); i++) {
219 m_blob[i].setGraphics(
true);
220 m_blob[i].setGraphicsThickness(m_thickness);
221 m_blob[i].initTracking(m_I_grayscale);
222 m_blob[i].track(m_I_grayscale);
223 m_points_2d[i] = m_blob[i].getCog();
225 std::stringstream ss;
227 vpDisplay::displayText(m_I_grayscale, m_blob[i].getCog() + vpImagePoint(-20, 20), ss.str(), vpColor::red);
228 vpDisplay::flush(m_I_grayscale);
230 compute_pose(m_points_3d, m_points_2d, m_cam,
true, m_cMo);
233 vpDisplay::flush(m_I_grayscale);
235 std::cout <<
"Tracking failed during initialisation" << std::endl;
245 vpImageConvert::convert(cv_frame, m_I_grayscale);
247 vpDisplay::display(m_I_grayscale);
248 vpDisplay::displayText(m_I_grayscale, 20, 20,
"Tracking in progress", vpColor::red);
249 vpDisplay::displayText(m_I_grayscale, 40, 20,
"Right click to quit", vpColor::red);
251 visp_ros::BlobTracker blob_tracker_msg;
253 for (
unsigned int i = 0; i < m_blob.size(); i++) {
254 m_blob[i].track(m_I_grayscale);
255 m_points_2d[i] = m_blob[i].getCog();
256 std::stringstream ss;
258 vpDisplay::displayText(m_I_grayscale, m_blob[i].getCog() + vpImagePoint(-20, 20), ss.str(), vpColor::red);
260 compute_pose(m_points_3d, m_points_2d, m_cam,
false, m_cMo);
261 vpDisplay::displayFrame(m_I_grayscale, m_cMo, m_cam, m_square_size / 2., vpColor::none, m_thickness);
265 geometry_msgs::PoseStamped msg_pose;
266 msg_pose.header.stamp = now;
267 msg_pose.header.frame_id = msg->header.frame_id;
269 blob_tracker_msg.pose_stamped = msg_pose;
271 cv_ptr->toImageMsg(blob_tracker_msg.image);
273 for (
unsigned int i = 0; i < m_blob.size(); i++) {
274 visp_ros::ImagePoint ip;
275 ip.i = m_blob[i].getCog().get_i();
276 ip.j = m_blob[i].getCog().get_j();
277 blob_tracker_msg.blob_cogs.push_back(ip);
279 visp_ros::ProjectedPoint pp;
280 vpPixelMeterConversion::convertPoint(m_cam, m_blob[i].getCog(), pp.x, pp.y);
281 blob_tracker_msg.blob_proj.push_back(pp);
283 vpDisplay::flush(m_I_grayscale);
285 std_msgs::Int8 status_msg;
288 vpMouseButton::vpMouseButtonType button;
289 if (vpDisplay::getClick(m_I_grayscale, button,
false)) {
290 if (button == vpMouseButton::button3) {
296 m_tracker_publisher.
publish(blob_tracker_msg);
297 m_status_publisher.publish(status_msg);
299 std::cout <<
"Tracking failed" << std::endl;
302 std_msgs::Int8 status_msg;
304 m_status_publisher.publish(status_msg);
312 std_msgs::Int8 status_msg;
314 m_status_publisher.publish(status_msg);
330 double compute_pose(std::vector<vpPoint> &points_3d,
const std::vector<vpImagePoint> &points_2d,
const vpCameraParameters &cam,
331 bool init, vpHomogeneousMatrix &cMo)
335 for (
unsigned int i = 0; i < points_3d.size(); i++) {
336 vpPixelMeterConversion::convertPoint(cam, points_2d[i], x, y);
337 points_3d[i].set_x(x);
338 points_3d[i].set_y(y);
339 pose.addPoint(points_3d[i]);
343 vpHomogeneousMatrix cMo_dem;
344 vpHomogeneousMatrix cMo_lag;
345 double residual_dem = std::numeric_limits<double>::max();
346 double residual_lag = std::numeric_limits<double>::max();
349 pose.computePose(vpPose::DEMENTHON, cMo_dem);
350 residual_dem = pose.computeResidual(cMo_dem);
352 residual_dem = std::numeric_limits<double>::max();
355 pose.computePose(vpPose::LAGRANGE, cMo_lag);
356 residual_lag = pose.computeResidual(cMo_lag);
358 residual_lag = std::numeric_limits<double>::max();
360 if (residual_dem < residual_lag)
365 pose.computePose(vpPose::VIRTUAL_VS, cMo);
366 double residual = pose.computeResidual(cMo);
373 int main(
int argc,
char** argv) {
374 ros::init(argc, argv,
"visp_ros_blob_tracker_node");
375 BlobTracker blobTracker;
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
void publish(const boost::shared_ptr< M > &message) const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
int main(int argc, char **argv)
TFSIMD_FORCE_INLINE const tfScalar & y() const
ROSCPP_DECL void spin(Spinner &spinner)
geometry_msgs::Pose toGeometryMsgsPose(const vpHomogeneousMatrix &mat)
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
TFSIMD_FORCE_INLINE const tfScalar & x() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool getParam(const std::string &key, std::string &s) const
ROSCPP_DECL void spinOnce()