camshiftdemo.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
3 #include <geometry_msgs/PolygonStamped.h>
4 #include <dynamic_reconfigure/server.h>
5 #include <jsk_perception/camshiftdemoConfig.h>
6 #include <jsk_recognition_msgs/RotatedRectStamped.h>
7 #include <sensor_msgs/SetCameraInfo.h>
8 
9 // opencv/samples/cp/camshiftdemo.c
10 
11 #include <sensor_msgs/Image.h>
12 #include <sensor_msgs/fill_image.h>
13 
15 #include <cv_bridge/cv_bridge.h>
16 
17 #include <opencv2/video/tracking.hpp>
18 #include <opencv2/imgproc/imgproc.hpp>
19 #include <opencv2/highgui/highgui.hpp>
20 
21 #include <iostream>
22 #include <ctype.h>
23 
24 #if ( CV_MAJOR_VERSION >= 4)
25 #include <opencv2/highgui/highgui_c.h>
26 #endif
27 using namespace cv;
28 using namespace std;
29 
31 {
32 protected:
37  sensor_msgs::Image img_;
42  bool debug_;
43 
44  typedef jsk_perception::camshiftdemoConfig Config;
45  typedef dynamic_reconfigure::Server<Config> ReconfigureServer;
46  ReconfigureServer reconfigure_server_;
47  Config config_;
48 
49  Mat image_;
50  Mat hsv_, hue_, mask_, histimg_, backproj_;
51 
52  // opencv 2.1 uses MatND which is removed in 2.2
53  // this code will be removend in D-Turtle
54 #if (CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION < 2)
55  MatND hist_;
56 #else
57  Mat hist_;
58 #endif
59 
63  bool showHist_;
65  Rect selection_;
66  int vmin_, vmax_, smin_;
67 
69  RotatedRect trackBox_;
70  int hsize_;
71  float hranges_[2];
72  const float* phranges_;
73 
74  typedef struct {
75  Mat *image;
76  bool *selectObject;
78  Rect *selection;
82 
83 public:
85  : it_(nh)
86  {
87  // ros setup
88  ros::NodeHandle local_nh("~");
89  local_nh.param("max_queue_size", max_queue_size_, 3);
90  local_nh.param("debug", debug_, true);
91 
93  sub_ = it.subscribe(nh.resolveName("image"), 1, &CamShiftDemo::imageCB, this);
94  pub_ = it.advertise(local_nh.resolveName("image"), 1);
95  pub_hist_ = it.advertise(local_nh.resolveName("histimg"), 1);
96 
97  sub_rectangle_ = nh.subscribe(nh.resolveName("screenrectangle"), 1, &CamShiftDemo::setRectangleCB, this);
98  pub_result_ = nh.advertise<jsk_recognition_msgs::RotatedRectStamped>(local_nh.resolveName("result"), 1);
99 
100  //roi_service_ = local_nh.advertiseService("set_roi", sensor_msgs::SetCameraInfo);
101  roi_service_ = local_nh.advertiseService("set_roi", &CamShiftDemo::setROICb, this);
102 
103  // camshiftdemo.cpp
104  backprojMode_ = false;
105  selectObject_ = false;
106  trackObject_ = 0;
107  showHist_ = true;
108  vmin_ = 10; vmax_ = 256; smin_ = 30;
109 
110  hsize_ = 16;
111  hranges_[0] = 0; hranges_[1] = 180;
112  phranges_ = hranges_;
113 
114  // Set up reconfigure server
115  config_.vmin = vmin_;
116  config_.vmax = vmax_;
117  config_.smin = smin_;
118  ReconfigureServer::CallbackType f = boost::bind(&CamShiftDemo::configCb, this, _1, _2);
119  reconfigure_server_.setCallback(f);
120 
121 
122  on_mouse_param_.image = &image_;
123  on_mouse_param_.selectObject = &selectObject_;
124  on_mouse_param_.trackObject = &trackObject_;
125  on_mouse_param_.selection = &selection_;
126  on_mouse_param_.origin = &origin_;
127 
128  if ( debug_ )
129  {
130  namedWindow( "Histogram", 1 );
131  namedWindow( "CamShift Demo", 1 );
132 
133  setMouseCallback( "CamShift Demo", onMouse, (void *)&on_mouse_param_ );
134  createTrackbar( "Vmin", "CamShift Demo", &vmin_, 256, 0 );
135  createTrackbar( "Vmax", "CamShift Demo", &vmax_, 256, 0 );
136  createTrackbar( "Smin", "CamShift Demo", &smin_, 256, 0 );
137 
138  histimg_ = Mat::zeros(200, 320, CV_8UC3);
139  }
140 
141  if ( ! debug_ )
142  {
144  }
145  }
146 
148  {
149  }
150 
151  bool setROICb(sensor_msgs::SetCameraInfo::Request &req,
152  sensor_msgs::SetCameraInfo::Response &res)
153  {
154 
155  onMouse(CV_EVENT_LBUTTONDOWN,
156  req.camera_info.roi.x_offset,
157  req.camera_info.roi.y_offset,
158  0,
159  &on_mouse_param_);
160  onMouse(CV_EVENT_LBUTTONUP,
161  req.camera_info.roi.x_offset + req.camera_info.roi.width,
162  req.camera_info.roi.y_offset + req.camera_info.roi.height,
163  0,
164  &on_mouse_param_);
165  res.success = true;
166  return true;
167  }
168 
169  void imageCB(const sensor_msgs::ImageConstPtr& msg_ptr)
170  {
171  cv_bridge::CvImagePtr cv_ptr;
172  Mat frame;
173 
174  try
175  {
176  cv_ptr = cv_bridge::toCvCopy(msg_ptr, "bgr8");
177  frame = cv_ptr->image;
178  }
180  {
181  ROS_ERROR("error");
182  }
183 
184  frame.copyTo(image_);
185  cvtColor(image_, hsv_, CV_BGR2HSV);
186 
187  if( trackObject_ )
188  {
189  int _vmin = vmin_, _vmax = vmax_;
190 
191  inRange(hsv_, Scalar(0, smin_, MIN(_vmin,_vmax)),
192  Scalar(180, 256, MAX(_vmin, _vmax)), mask_);
193  int ch[] = {0, 0};
194  hue_.create(hsv_.size(), hsv_.depth());
195  mixChannels(&hsv_, 1, &hue_, 1, ch, 1);
196 
197  if( trackObject_ < 0 )
198  {
199  Mat roi(hue_, selection_), maskroi(mask_, selection_);
200  calcHist(&roi, 1, 0, maskroi, hist_, 1, &hsize_, &phranges_);
201  normalize(hist_, hist_, 0, 255, CV_MINMAX);
202 
203  trackWindow_ = selection_;
204  trackObject_ = 1;
205 
206  histimg_ = Scalar::all(0);
207  int binW = histimg_.cols / hsize_;
208  Mat buf(1, hsize_, CV_8UC3);
209  for( int i = 0; i < hsize_; i++ )
210  buf.at<Vec3b>(i) = Vec3b(saturate_cast<uchar>(i*180./hsize_), 255, 255);
211  cvtColor(buf, buf, CV_HSV2BGR);
212 
213  for( int i = 0; i < hsize_; i++ )
214  {
215  int val = saturate_cast<int>(hist_.at<float>(i)*histimg_.rows/255);
216  rectangle( histimg_, Point(i*binW,histimg_.rows),
217  Point((i+1)*binW,histimg_.rows - val),
218  Scalar(buf.at<Vec3b>(i)), -1, 8 );
219  }
220  }
221 
222  try {
223  calcBackProject(&hue_, 1, 0, hist_, backproj_, &phranges_);
224  backproj_ &= mask_;
225  trackBox_ = CamShift(backproj_, trackWindow_,
226  TermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ));
227 
228  if( backprojMode_ )
229  cvtColor( backproj_, image_, CV_GRAY2BGR );
230  ellipse( image_, trackBox_, Scalar(0,0,255), 3, CV_AA );
231 
232  jsk_recognition_msgs::RotatedRectStamped result_msg;
233  result_msg.header = msg_ptr->header;
234  result_msg.rect.x = trackBox_.center.x;
235  result_msg.rect.y = trackBox_.center.y;
236  result_msg.rect.width = trackBox_.size.width;
237  result_msg.rect.height = trackBox_.size.height;
238  result_msg.rect.angle = trackBox_.angle; // degree->rad
239  pub_result_.publish(result_msg);
240 
241  } catch (...) {
242  ROS_WARN("illegal tracBox = x:%f y:%f width:%f height:%f angle:%f",
243  trackBox_.center.x, trackBox_.center.y,
244  trackBox_.size.width, trackBox_.size.height,
245  trackBox_.angle);
246  }
247  }
248 
249  if( selectObject_ && selection_.width > 0 && selection_.height > 0 )
250  {
251  Mat roi(image_, selection_);
252  bitwise_not(roi, roi);
253  }
254 
255  img_.header = msg_ptr->header;
256  fillImage(img_, "bgr8", image_.rows, image_.cols, image_.step, const_cast<uint8_t*>(image_.data));
257  pub_.publish(img_);
258  fillImage(img_, "bgr8", histimg_.rows, histimg_.cols, histimg_.step, const_cast<uint8_t*>(histimg_.data));
259  pub_hist_.publish(img_);
260 
261  if ( debug_ )
262  {
263  imshow( "CamShift Demo", image_ );
264  imshow( "Histogram", histimg_ );
265 
266  char c = (char)waitKey(10);
267  switch(c)
268  {
269  case 'b':
270  backprojMode_ = !backprojMode_;
271  break;
272  case 'c':
273  trackObject_ = 0;
274  histimg_ = Scalar::all(0);
275  break;
276  case 'h':
277  showHist_ = !showHist_;
278  if( !showHist_ )
279  destroyWindow( "Histogram" );
280  else
281  namedWindow( "Histogram", 1 );
282  break;
283  default:
284  ;
285  }
286  }
287  }
288 
289  void setRectangleCB(const geometry_msgs::PolygonStampedConstPtr& msg_ptr)
290  {
291  selection_.x = msg_ptr->polygon.points[0].x;
292  selection_.y = msg_ptr->polygon.points[0].y;
293  selection_.width = msg_ptr->polygon.points[1].x - msg_ptr->polygon.points[0].x;
294  selection_.height = msg_ptr->polygon.points[1].y - msg_ptr->polygon.points[0].y;
295  selection_ &= Rect(0, 0, image_.cols, image_.rows);
296  trackObject_ = -1;
297  }
298 
299  void configCb(Config &config, uint32_t level)
300  {
301  config_ = config;
302  vmin_ = config_.vmin;
303  vmax_ = config_.vmax;
304  smin_ = config_.smin;
305  switch ( config_.display_mode )
306  {
307  case jsk_perception::camshiftdemo_RGB:
308  backprojMode_ = false;
309  break;
310  case jsk_perception::camshiftdemo_Backproject:
311  backprojMode_ = true;
312  break;
313  }
314  }
315 
316 
317  static void onMouse( int event, int x, int y, int flags, void* param)
318  {
319  on_mouse_param_type* on_mouse_param = (on_mouse_param_type *)param;
320  Mat* image = on_mouse_param->image;
321  bool *selectObject = on_mouse_param->selectObject;
322  int *trackObject = on_mouse_param->trackObject;
323  Rect *selection = on_mouse_param->selection;
324  Point *origin = on_mouse_param->origin;
325 
326  if( *selectObject )
327  {
328  selection->x = MIN(x, origin->x);
329  selection->y = MIN(y, origin->y);
330  selection->width = std::abs(x - origin->x);
331  selection->height = std::abs(y - origin->y);
332 
333  *selection &= Rect(0, 0, image->cols, image->rows);
334  }
335 
336  switch( event )
337  {
338  case CV_EVENT_LBUTTONDOWN:
339  *origin = Point(x,y);
340  *selection = Rect(x,y,0,0);
341  *selectObject = true;
342  break;
343  case CV_EVENT_LBUTTONUP:
344  *selectObject = false;
345  if( selection->width > 0 && selection->height > 0 )
346  *trackObject = -1;
347  break;
348  }
349  }
350 
351 };
352 
353 
354 int main(int argc, char** argv)
355 {
356  ros::init(argc, argv, "camshiftdemo");
358  if (n.resolveName("image") == "/image") {
359  ROS_WARN("%s: image has not been remapped! Typical command-line usage:\n"
360  "\t$ ./%s image:=<image topic>", argv[0], argv[0]);
361  }
362 
363  CamShiftDemo c(n);
364 
365  ros::spin();
366 
367  return 0;
368 }
Subscriber subscribe(const std::string &base_topic, uint32_t queue_size, const boost::function< void(const sensor_msgs::ImageConstPtr &)> &callback, const ros::VoidPtr &tracked_object=ros::VoidPtr(), const TransportHints &transport_hints=TransportHints())
f
void publish(const boost::shared_ptr< M > &message) const
RotatedRect trackBox_
void imageCB(const sensor_msgs::ImageConstPtr &msg_ptr)
ros::NodeHandle nh_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
on_mouse_param_type on_mouse_param_
std::string resolveName(const std::string &name, bool remap=true) const
GLfloat n[6][3]
ReconfigureServer reconfigure_server_
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
ros::Publisher pub_result_
static void onMouse(int event, int x, int y, int flags, void *param)
CamShiftDemo(ros::NodeHandle nh)
int main(int argc, char **argv)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
#define ROS_WARN(...)
void setRectangleCB(const geometry_msgs::PolygonStampedConstPtr &msg_ptr)
ROSCPP_DECL void spin(Spinner &spinner)
const float * phranges_
jsk_perception::camshiftdemoConfig Config
image_transport::Publisher pub_hist_
dynamic_reconfigure::Server< Config > ReconfigureServer
CvImagePtr cvtColor(const CvImageConstPtr &source, const std::string &encoding)
void publish(const sensor_msgs::Image &message) const
bool param(const std::string &param_name, T &param_val, const T &default_val) const
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
sensor_msgs::Image img_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
pointer error(enum errorcode ec,...) pointer error(va_alist) va_dcl
TFSIMD_FORCE_INLINE Vector3 & normalize()
void startWindowThread()
pointer MAX(context *ctx, int n, argv)
image_transport::ImageTransport it_
ch
image_transport::Subscriber sub_
frame
pointer MIN(context *ctx, int n, argv)
void configCb(Config &config, uint32_t level)
ros::Subscriber sub_rectangle_
c
Eigen::Vector3f Point
#define ROS_ERROR(...)
bool setROICb(sensor_msgs::SetCameraInfo::Request &req, sensor_msgs::SetCameraInfo::Response &res)
ros::ServiceServer roi_service_


jsk_perception
Author(s): Manabu Saito, Ryohei Ueda
autogenerated on Mon May 3 2021 03:03:27