all_camera_viewer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 //##################
19 //#### includes ####
20 
21 // standard includes
22 //--
23 
24 // ROS includes
25 #include <ros/ros.h>
26 #include <cv_bridge/CvBridge.h>
31 #ifdef __ROS_1_1__
34 #endif
35 
36 // ROS message includes
37 #include <sensor_msgs/Image.h>
38 #include <sensor_msgs/CameraInfo.h>
39 #include <sensor_msgs/fill_image.h>
40 
41 #include <cob_camera_sensors/AcquireCalibrationImages.h>
42 
43 // external includes
45 
46 #include <opencv/highgui.h>
47 #include <boost/thread/mutex.hpp>
48 
49 using namespace message_filters;
50 
51 #ifdef __ROS_1_1__
54 #endif
55 
62 {
63 private:
65 
67 
68  // Subscriptions
75 
76 #ifdef __ROS_1_1__
80 #else
81  message_filters::TimeSynchronizer<sensor_msgs::Image,
82  sensor_msgs::Image, sensor_msgs::Image> shared_sub_sync_;
83  message_filters::TimeSynchronizer<sensor_msgs::Image,
84  sensor_msgs::Image> stereo_sub_sync_;
85  message_filters::TimeSynchronizer<sensor_msgs::Image,
86  sensor_msgs::Image, sensor_msgs::Image> all_sub_sync_;
87 #endif
88 
91 
92  sensor_msgs::Image color_image_msg_;
93  sensor_msgs::Image xyz_image_msg_;
94  sensor_msgs::Image confidence_mask_msg_;
95 
98  IplImage* xyz_image_32F3_;
99  IplImage* grey_image_32F1_;
100 
103  cv::Mat xyz_mat_32F3_;
104  cv::Mat grey_mat_32F1_;
105  cv::Mat grey_mat_8U1_;
106  std::vector<cv::Mat> vec_grey_mat_32F1_;
107 
109 
110  sensor_msgs::CvBridge cv_bridge_0_;
111  sensor_msgs::CvBridge cv_bridge_1_;
112  sensor_msgs::CvBridge cv_bridge_2_;
113 
115 
116  boost::mutex m_ServiceMutex;
117 
119 
123 public:
125  AllCameraViewer(const ros::NodeHandle& node_handle)
126  : node_handle_(node_handle),
127  image_transport_(node_handle),
128 #ifdef __ROS_1_1__
129  shared_sub_sync_(ThreeImageSyncPolicy(3)),
130  stereo_sub_sync_(TwoImageSyncPolicy(3)),
131  all_sub_sync_(ThreeImageSyncPolicy(3)),
132 #else
133  shared_sub_sync_(3),
134  stereo_sub_sync_(3),
135  all_sub_sync_(3),
136 #endif
137  sub_counter_(0),
138  right_color_image_8U3_(0),
139  left_color_image_8U3_(0),
140  xyz_image_32F3_(0),
141  grey_image_32F1_(0)
142  {
143  use_tof_camera_ = true;
144  use_left_color_camera_ = true;
145  use_right_color_camera_ = true;
146  image_counter_ = 0;
147  tof_image_counter_ = 0;
148  }
149 
152  {
153  }
154 
159  bool init()
160  {
161  if (loadParameters() == false) return false;
162 
165 
166  save_camera_images_service_ = node_handle_.advertiseService("save_camera_images", &AllCameraViewer::saveCameraImagesServiceCallback, this);
167 
168  // Synchronize inputs of incoming image data.
169  // Topic subscriptions happen on demand in the connection callback.
170 
171  // TODO: Dynamically determine, which cameras are available
172 
173  if(use_right_color_camera_ && use_tof_camera_ && !use_left_color_camera_)
174  {
175  ROS_INFO("[all_camera_viewer] Setting up subscribers for right color and tof camera");
176  shared_sub_sync_.connectInput(right_color_camera_image_sub_, tof_camera_grey_image_sub_);
177  shared_sub_sync_.registerCallback(boost::bind(&AllCameraViewer::sharedModeSrvCallback, this, _1, _2));
178  }
179  else if(use_right_color_camera_ && !use_tof_camera_ && use_left_color_camera_)
180  {
181  ROS_INFO("[all_camera_viewer] Setting up subscribers left and right color camera");
182  stereo_sub_sync_.connectInput(left_color_camera_image_sub_, right_color_camera_image_sub_);
183  stereo_sub_sync_.registerCallback(boost::bind(&AllCameraViewer::stereoModeSrvCallback, this, _1, _2));
184  }
185  else if(use_right_color_camera_ && use_tof_camera_ && use_left_color_camera_)
186  {
187  ROS_INFO("[all_camera_viewer] Setting up subscribers for left color, right color and tof camera");
188  all_sub_sync_.connectInput(left_color_camera_image_sub_, right_color_camera_image_sub_, tof_camera_grey_image_sub_);
189  all_sub_sync_.registerCallback(boost::bind(&AllCameraViewer::allModeSrvCallback, this, _1, _2, _3));
190  }
191  else
192  {
193  ROS_ERROR("[all_camera_viewer] Specified camera configuration not available");
194  return false;
195  }
196 
197 
198  connectCallback();
199 
200  ROS_INFO("[all_camera_viewer] Initializing [OK]");
201  return true;
202  }
203 
206  {
207  if (sub_counter_ == 0)
208  {
209  sub_counter_++;
210  ROS_DEBUG("[all_camera_viewer] Subscribing to camera topics");
211 
212  if (use_right_color_camera_)
213  {
214  right_color_camera_image_sub_.subscribe(image_transport_, "right/image_color", 1);
215  right_camera_info_sub_.subscribe(node_handle_, "right/camera_info", 1);
216  }
217  if (use_left_color_camera_)
218  {
219  left_color_camera_image_sub_.subscribe(image_transport_, "left/image_color", 1);
220  left_camera_info_sub_.subscribe(node_handle_, "left/camera_info", 1);
221  }
222  if (use_tof_camera_)
223  {
224  tof_camera_grey_image_sub_.subscribe(image_transport_, "image_grey", 1);
225  }
226  }
227  }
228 
231  {
232  sub_counter_--;
233  if (sub_counter_ == 0)
234  {
235  ROS_DEBUG("[all_camera_viewer] Unsubscribing from camera topics");
236 
237  if (use_right_color_camera_)
238  {
239  right_color_camera_image_sub_.unsubscribe();
240  right_camera_info_sub_.unsubscribe();
241  }
242  if (use_left_color_camera_)
243  {
244  left_color_camera_image_sub_.unsubscribe();
245  left_camera_info_sub_.unsubscribe();
246  }
247  if (use_tof_camera_)
248  {
249  tof_camera_grey_image_sub_.unsubscribe();
250  }
251  }
252  }
253 
254  void allModeSrvCallback(const sensor_msgs::ImageConstPtr& left_camera_data,
255  const sensor_msgs::ImageConstPtr& right_camera_data,
256  const sensor_msgs::ImageConstPtr& tof_camera_grey_data)
257  {
258  ROS_INFO("[all_camera_viewer] allModeSrvCallback");
259  boost::mutex::scoped_lock lock(m_ServiceMutex);
260  // Convert ROS image messages to openCV IplImages
261  try
262  {
263  right_color_image_8U3_ = cv_bridge_0_.imgMsgToCv(right_camera_data, "bgr8");
264  left_color_image_8U3_ = cv_bridge_1_.imgMsgToCv(left_camera_data, "bgr8");
265  grey_image_32F1_ = cv_bridge_2_.imgMsgToCv(tof_camera_grey_data, "passthrough");
266 
267  cv::Mat tmp = right_color_image_8U3_;
268  right_color_mat_8U3_ = tmp.clone();
269 
270  tmp = left_color_image_8U3_;
271  left_color_mat_8U3_ = tmp.clone();
272 
273  tmp = grey_image_32F1_;
274  grey_mat_32F1_ = tmp.clone();
275  }
276  catch (sensor_msgs::CvBridgeException& e)
277  {
278  ROS_ERROR("[all_camera_viewer] Could not convert stereo images with cv_bridge.");
279  }
280 
281  // Modifies <code>grey_mat_8U1_</code> and <code>vec_grey_mat_32F1_</code>
282  // using <code>grey_mat_32F1_</code>
283  updateTofGreyscaleData();
284 
285  cv::imshow("TOF grey data", grey_mat_8U1_);
286 
287  cv::Mat right_color_8U3;
288  cv::resize(right_color_mat_8U3_, right_color_8U3, cv::Size(), 0.5, 0.5);
289  cv::imshow("Right color data", right_color_8U3);
290 
291  cv::Mat left_color_8U3;
292  cv::resize(left_color_mat_8U3_, left_color_8U3, cv::Size(), 0.5, 0.5);
293  cv::imshow("Left color data", left_color_8U3);
294  cv::waitKey(50);
295 
296  ROS_INFO("[all_camera_viewer] allModeSrvCallback [OK]");
297  }
298 
301  void sharedModeSrvCallback(const sensor_msgs::ImageConstPtr& right_camera_data,
302  const sensor_msgs::ImageConstPtr& tof_camera_grey_data)
303  {
304  boost::mutex::scoped_lock lock(m_ServiceMutex);
305  ROS_INFO("[all_camera_viewer] sharedModeSrvCallback");
306  // Convert ROS image messages to openCV IplImages
307  try
308  {
309  right_color_image_8U3_ = cv_bridge_0_.imgMsgToCv(right_camera_data, "passthrough");
310  grey_image_32F1_ = cv_bridge_2_.imgMsgToCv(tof_camera_grey_data, "passthrough");
311 
312  cv::Mat tmp = right_color_image_8U3_;
313  right_color_mat_8U3_ = tmp.clone();
314 
315  tmp = grey_image_32F1_;
316  grey_mat_32F1_ = tmp.clone();
317  }
318  catch (sensor_msgs::CvBridgeException& e)
319  {
320  ROS_ERROR("[all_camera_viewer] Could not convert images with cv_bridge.");
321  }
322 
323  // Modifies <code>grey_mat_8U1_</code> and <code>vec_grey_mat_32F1_</code>
324  // using <code>grey_mat_32F1_</code>
325  updateTofGreyscaleData();
326 
327  cv::imshow("TOF grey data", grey_mat_8U1_);
328 
329  cv::Mat right_color_8U3;
330  cv::resize(right_color_mat_8U3_, right_color_8U3, cv::Size(), 0.5, 0.5);
331  cv::imshow("Right color data", right_color_8U3);
332  cv::waitKey(1000);
333  }
334 
339  {
340  cv::Mat filtered_grey_mat_32F1 = cv::Mat::zeros(grey_mat_32F1_.rows, grey_mat_32F1_.cols, CV_8UC1/*32FC1*/);
341 
342  // Accumulate greyscale images to remove noise
343  if (vec_grey_mat_32F1_.size() <= (unsigned int) tof_image_counter_)
344  vec_grey_mat_32F1_.push_back(grey_mat_32F1_);
345  else
346  vec_grey_mat_32F1_[tof_image_counter_] = grey_mat_32F1_;
347  // Update counter
348  tof_image_counter_ = (++tof_image_counter_)%5;
349 
350  // Compute average out of accumulated tof greyscale data
351  for (unsigned int i=0; i<vec_grey_mat_32F1_.size(); i++)
352  filtered_grey_mat_32F1 += vec_grey_mat_32F1_[i];
353  filtered_grey_mat_32F1 * (1/vec_grey_mat_32F1_.size());
354 
355  // Update 8bit image
356  cv::Mat temp0_grey_mat_8U1;
357  cv::Mat temp1_grey_mat_8U1;
358 
359  // Convert CV_32FC1 image to CV_8UC1
360  /*double m_scaleMin;
361  double m_scaleMax;
362  cv::minMaxLoc(filtered_grey_mat_32F1, &m_scaleMin, &m_scaleMax);
363  cv::Mat minmat(filtered_grey_mat_32F1.size(), 32FC1, cv::Scalar(m_scaleMin));
364  filtered_grey_mat_32F1 = cv::Mat(filtered_grey_mat_32F1 - minmat)/ m_scaleMax;
365  filtered_grey_mat_32F1.convertTo(temp0_grey_mat_8U1, CV_8U, 256);*/
366 
367  // Perform histogram equalization on 8bit image
368  //cv::equalizeHist(temp0_grey_mat_8U1, temp1_grey_mat_8U1);
369 
370  // Upsample image by a factor of 2 using bilinear interpolation
371  // and save result to member variable
372  grey_mat_8U1_ = filtered_grey_mat_32F1;//temp0_grey_mat_8U1;
373  //resize(temp0_grey_mat_8U1, grey_mat_8U1_, cv::Size(), 2, 2, cv::INTER_LINEAR);
374  }
375 
378  void stereoModeSrvCallback(const sensor_msgs::ImageConstPtr& left_camera_data,
379  const sensor_msgs::ImageConstPtr& right_camera_data)
380  {
381  ROS_INFO("[all_camera_viewer] stereoModeSrvCallback");
382  boost::mutex::scoped_lock lock(m_ServiceMutex);
383  // Convert ROS image messages to openCV IplImages
384  try
385  {
386  right_color_image_8U3_ = cv_bridge_0_.imgMsgToCv(right_camera_data, "passthrough");
387  left_color_image_8U3_ = cv_bridge_1_.imgMsgToCv(left_camera_data, "passthrough");
388 
389  cv::Mat tmp = right_color_image_8U3_;
390  right_color_mat_8U3_ = tmp.clone();
391 
392  tmp = left_color_image_8U3_;
393  left_color_mat_8U3_ = tmp.clone();
394  }
395  catch (sensor_msgs::CvBridgeException& e)
396  {
397  ROS_ERROR("[all_camera_viewer] Could not convert stereo images with cv_bridge.");
398  }
399 
400  cv::Mat right_color_8U3;
401  cv::resize(right_color_mat_8U3_, right_color_8U3, cv::Size(), 0.5, 0.5);
402  cv::imshow("Right color data", right_color_8U3);
403 
404  cv::Mat left_color_8U3;
405  cv::resize(left_color_mat_8U3_, left_color_8U3, cv::Size(), 0.5, 0.5);
406  cv::imshow("Left color data", left_color_8U3);
407  cv::waitKey(1000);
408 
409  ROS_INFO("[all_camera_viewer] stereoModeSrvCallback [OK]");
410  }
411 
412  bool saveCameraImagesServiceCallback(cob_camera_sensors::AcquireCalibrationImages::Request &req,
413  cob_camera_sensors::AcquireCalibrationImages::Response &res)
414  {
415  ROS_INFO("[all_camera_viewer] Service Callback");
416  boost::mutex::scoped_lock lock(m_ServiceMutex);
417 
418  if (req.reset_image_counter) image_counter_ = 0;
419 
420  char counterBuffer [50];
421  sprintf(counterBuffer, "%04d", image_counter_);
422 
423  if (use_right_color_camera_ && right_color_mat_8U3_.empty())
424  {
425  ROS_INFO("[all_camera_viewer] Right color image not available");
426  return false;
427  }
428  else
429  {
430  std::stringstream ss;
431  ss << "right_color_image_";
432  ss << counterBuffer;
433  ss << ".bmp";
434  cv::imwrite(absolute_output_directory_path_ + ss.str(), right_color_mat_8U3_);
435  ROS_INFO("[all_camera_viewer] Saved right color image %d to %s", image_counter_, ss.str().c_str());
436  }
437 
438  if (use_left_color_camera_ && left_color_mat_8U3_.empty())
439  {
440  ROS_INFO("[all_camera_viewer] Left color image not available");
441  return false;
442  }
443  else
444  {
445  std::stringstream ss;
446  ss << "left_color_image_";
447  ss << counterBuffer;
448  ss << ".bmp";
449  cv::imwrite(absolute_output_directory_path_ + ss.str(), left_color_mat_8U3_);
450  ROS_INFO("[all_camera_viewer] Saved left color image %d to %s", image_counter_, ss.str().c_str());
451  }
452 
453 
454  if (use_tof_camera_ && grey_mat_8U1_.empty())
455  {
456  ROS_INFO("[all_camera_viewer] Tof grayscale image not available");
457  return false;
458  }
459  else
460  {
461  std::stringstream ss;
462  ss << "tof_grey_image_";
463  ss << counterBuffer;
464  ss << ".bmp";
465  cv::imwrite(absolute_output_directory_path_ + ss.str(), grey_mat_8U1_);
466  ROS_INFO("[all_camera_viewer] Saved tof gray image %d to %s", image_counter_, ss.str().c_str());
467  }
468 
469  image_counter_++;
470 
471  return true;
472  }
473 
474  unsigned long loadParameters()
475  {
476  std::string tmp_string;
477 
479  if (node_handle_.getParam("all_camera_viewer/use_tof_camera", use_tof_camera_) == false)
480  {
481  ROS_ERROR("[all_camera_viewer] 'use_tof_camera' not specified");
482  return false;
483  }
484  ROS_INFO("use tof camera: %d", use_tof_camera_);
485 
486  if (node_handle_.getParam("all_camera_viewer/use_right_color_camera", use_right_color_camera_) == false)
487  {
488  ROS_ERROR("[all_camera_viewer] 'use_right_color_camera' not specified");
489  return false;
490  }
491  ROS_INFO("use right color camera: %d", use_right_color_camera_);
492 
493  if (node_handle_.getParam("all_camera_viewer/use_left_color_camera", use_left_color_camera_) == false)
494  {
495  ROS_ERROR("[all_camera_viewer] 'use_left_color_camera' not specified");
496  return false;
497  }
498  ROS_INFO("use left color camera: %d", use_left_color_camera_);
499 
500  if (node_handle_.getParam("all_camera_viewer/absolute_output_directory_path", absolute_output_directory_path_) == false)
501  {
502  ROS_ERROR("[all_camera_viewer] 'absolute_output_directory_path' not specified");
503  return false;
504  }
505  ROS_INFO("use left color camera: %d", use_left_color_camera_);
506 
507  return true;
508  }
509 
510 };
511 
512 //#######################
513 //#### main programm ####
514 int main(int argc, char** argv)
515 {
517  ros::init(argc, argv, "all_camera_viewer");
518 
520  ros::NodeHandle nh;
521 
523  AllCameraViewer camera_node(nh);
524 
526  if (!camera_node.init()) return 0;
527 
528  ros::spin();
529 
530  return 0;
531 }
cv::Mat grey_mat_8U1_
Received gray values from tof sensor.
message_filters::TimeSynchronizer< sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::Image > shared_sub_sync_
message_filters::TimeSynchronizer< sensor_msgs::Image, sensor_msgs::Image > stereo_sub_sync_
cv::Mat grey_mat_32F1_
Received gray values from tof sensor.
std::string absolute_output_directory_path_
Directory, where camera images are saved.
ros::ServiceServer save_camera_images_service_
image_transport::Subscriber sub
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
boost::function< void(const SingleSubscriberPublisher &)> SubscriberStatusCallback
void stereoModeSrvCallback(const sensor_msgs::ImageConstPtr &left_camera_data, const sensor_msgs::ImageConstPtr &right_camera_data)
IplImage * xyz_image_32F3_
Received point cloud form tof sensor.
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
unsigned long loadParameters()
int main(int argc, char **argv)
ROSCPP_DECL void spin(Spinner &spinner)
sensor_msgs::CvBridge cv_bridge_0_
Converts ROS image messages to openCV IplImages.
int tof_image_counter_
Number of subscribers to topic.
image_transport::SubscriberFilter right_color_camera_image_sub_
Right color camera image topic.
#define ROS_INFO(...)
message_filters::TimeSynchronizer< sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::Image > all_sub_sync_
void sharedModeSrvCallback(const sensor_msgs::ImageConstPtr &right_camera_data, const sensor_msgs::ImageConstPtr &tof_camera_grey_data)
void allModeSrvCallback(const sensor_msgs::ImageConstPtr &left_camera_data, const sensor_msgs::ImageConstPtr &right_camera_data, const sensor_msgs::ImageConstPtr &tof_camera_grey_data)
IplImage * left_color_image_8U3_
Received color image of the left camera.
void disconnectCallback()
Unsubscribe from camera topics if possible.
sensor_msgs::CvBridge cv_bridge_1_
Converts ROS image messages to openCV IplImages.
void subscribe(ImageTransport &it, const std::string &base_topic, uint32_t queue_size, const TransportHints &transport_hints=TransportHints())
cv::Mat right_color_mat_8U3_
Received color image of the right camera.
AllCameraViewer(const ros::NodeHandle &node_handle)
Constructor.
void subscribe(ros::NodeHandle &nh, const std::string &topic, uint32_t queue_size, const ros::TransportHints &transport_hints=ros::TransportHints(), ros::CallbackQueueInterface *callback_queue=0)
bool saveCameraImagesServiceCallback(cob_camera_sensors::AcquireCalibrationImages::Request &req, cob_camera_sensors::AcquireCalibrationImages::Response &res)
bool getParam(const std::string &key, std::string &s) const
cv::Mat xyz_mat_32F3_
Received point cloud form tof sensor.
IplImage * right_color_image_8U3_
Received color image of the right camera.
sensor_msgs::Image xyz_image_msg_
sensor_msgs::Image confidence_mask_msg_
void connectCallback()
Subscribe to camera topics if not already done.
message_filters::Subscriber< sensor_msgs::CameraInfo > right_camera_info_sub_
Right camera information service.
sensor_msgs::Image color_image_msg_
Number of accumulated tog greyscale images.
message_filters::Subscriber< sensor_msgs::CameraInfo > left_camera_info_sub_
Left camera information service.
sensor_msgs::CvBridge cv_bridge_2_
Converts ROS image messages to openCV IplImages.
image_transport::SubscriberFilter left_color_camera_image_sub_
Left color camera image topic.
boost::mutex m_ServiceMutex
~AllCameraViewer()
Destructor.
cv::Mat left_color_mat_8U3_
Received color image of the left camera.
ros::NodeHandle node_handle_
#define ROS_ERROR(...)
std::vector< cv::Mat > vec_grey_mat_32F1_
Accumulated tof greyscale images for noise reduction.
image_transport::SubscriberFilter tof_camera_grey_image_sub_
Tof camera intensity image topic.
int image_counter_
Counts the number of images saved to the hard disk.
IplImage * grey_image_32F1_
Received gray values from tof sensor.
image_transport::ImageTransport image_transport_
#define ROS_DEBUG(...)


cob_camera_sensors
Author(s): Jan Fischer , Richard Bormann
autogenerated on Thu Mar 19 2020 03:23:05