image_view.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2008, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 #include <image_view/ImageViewConfig.h>
35 
36 #include <ros/ros.h>
38 #include <dynamic_reconfigure/server.h>
39 
40 #include <cv_bridge/cv_bridge.h>
41 #include <opencv2/highgui/highgui.hpp>
42 
43 #include <boost/format.hpp>
44 #include <boost/thread.hpp>
45 #include <boost/filesystem.hpp>
46 
47 int g_count;
48 cv::Mat g_last_image;
49 boost::format g_filename_format;
50 boost::mutex g_image_mutex;
51 std::string g_window_name;
52 bool g_gui;
58 
59 void reconfigureCb(image_view::ImageViewConfig &config, uint32_t level)
60 {
61  boost::mutex::scoped_lock lock(g_image_mutex);
62  g_do_dynamic_scaling = config.do_dynamic_scaling;
63  g_colormap = config.colormap;
64  g_min_image_value = config.min_image_value;
65  g_max_image_value = config.max_image_value;
66 }
67 
68 void imageCb(const sensor_msgs::ImageConstPtr& msg)
69 {
70  boost::mutex::scoped_lock lock(g_image_mutex);
71 
72  // Convert to OpenCV native BGR color
74  try {
77  options.colormap = g_colormap;
78  // Set min/max value for scaling to visualize depth/float image.
80  // Not specified by rosparam, then set default value.
81  // Because of current sensor limitation, we use 10m as default of max range of depth
82  // with consistency to the configuration in rqt_image_view.
83  options.min_image_value = 0;
84  if (msg->encoding == "32FC1") {
85  options.max_image_value = 10; // 10 [m]
86  } else if (msg->encoding == "16UC1") {
87  options.max_image_value = 10 * 1000; // 10 * 1000 [mm]
88  }
89  } else {
92  }
93  cv_ptr = cv_bridge::cvtColorForDisplay(cv_bridge::toCvShare(msg), "", options);
94  g_last_image = cv_ptr->image;
95  } catch (cv_bridge::Exception& e) {
96  ROS_ERROR_THROTTLE(30, "Unable to convert '%s' image for display: '%s'",
97  msg->encoding.c_str(), e.what());
98  }
99  if (g_gui && !g_last_image.empty()) {
100  const cv::Mat &image = g_last_image;
101  cv::imshow(g_window_name, image);
102  cv::waitKey(3);
103  }
104  if (g_pub.getNumSubscribers() > 0) {
105  g_pub.publish(cv_ptr);
106  }
107 }
108 
109 static void mouseCb(int event, int x, int y, int flags, void* param)
110 {
111  if (event == cv::EVENT_LBUTTONDOWN) {
112  ROS_WARN_ONCE("Left-clicking no longer saves images. Right-click instead.");
113  return;
114  } else if (event != cv::EVENT_RBUTTONDOWN) {
115  return;
116  }
117 
118  boost::mutex::scoped_lock lock(g_image_mutex);
119 
120  const cv::Mat &image = g_last_image;
121 
122  if (image.empty()) {
123  ROS_WARN("Couldn't save image, no data!");
124  return;
125  }
126 
127  std::string filename = (g_filename_format % g_count).str();
128  if (cv::imwrite(filename, image)) {
129  ROS_INFO("Saved image %s", filename.c_str());
130  g_count++;
131  } else {
132  boost::filesystem::path full_path = boost::filesystem::complete(filename);
133  ROS_ERROR_STREAM("Failed to save image. Have permission to write there?: " << full_path);
134  }
135 }
136 
137 
138 int main(int argc, char **argv)
139 {
140  ros::init(argc, argv, "image_view", ros::init_options::AnonymousName);
141  if (ros::names::remap("image") == "image") {
142  ROS_WARN("Topic 'image' has not been remapped! Typical command-line usage:\n"
143  "\t$ rosrun image_view image_view image:=<image topic> [transport]");
144  }
145 
146  ros::NodeHandle nh;
147  ros::NodeHandle local_nh("~");
148 
149  // Default window name is the resolved topic name
150  std::string topic = nh.resolveName("image");
151  local_nh.param("window_name", g_window_name, topic);
152  local_nh.param("gui", g_gui, true); // gui/no_gui mode
153 
154  if (g_gui) {
155  std::string format_string;
156  local_nh.param("filename_format", format_string, std::string("frame%04i.jpg"));
157  g_filename_format.parse(format_string);
158 
159  // Handle window size
160  bool autosize;
161  local_nh.param("autosize", autosize, false);
162  cv::namedWindow(g_window_name, autosize ? (CV_WINDOW_AUTOSIZE | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED) : 0);
163  cv::setMouseCallback(g_window_name, &mouseCb);
164 
165  if(autosize == false)
166  {
167  if(local_nh.hasParam("width") && local_nh.hasParam("height"))
168  {
169  int width;
170  local_nh.getParam("width", width);
171  int height;
172  local_nh.getParam("height", height);
173  cv::resizeWindow(g_window_name, width, height);
174  }
175  }
176 
177  // Start the OpenCV window thread so we don't have to waitKey() somewhere
179  }
180 
181  // Handle transport
182  // priority:
183  // 1. command line argument
184  // 2. rosparam '~image_transport'
185  std::string transport;
186  local_nh.param("image_transport", transport, std::string("raw"));
187  ros::V_string myargv;
188  ros::removeROSArgs(argc, argv, myargv);
189  for (size_t i = 1; i < myargv.size(); ++i) {
190  if (myargv[i][0] != '-') {
191  transport = myargv[i];
192  break;
193  }
194  }
195  ROS_INFO_STREAM("Using transport \"" << transport << "\"");
197  image_transport::TransportHints hints(transport, ros::TransportHints(), local_nh);
198  image_transport::Subscriber sub = it.subscribe(topic, 1, imageCb, hints);
199  g_pub = local_nh.advertise<sensor_msgs::Image>("output", 1);
200 
201  dynamic_reconfigure::Server<image_view::ImageViewConfig> srv;
202  dynamic_reconfigure::Server<image_view::ImageViewConfig>::CallbackType f =
203  boost::bind(&reconfigureCb, _1, _2);
204  srv.setCallback(f);
205 
206  ros::spin();
207 
208  if (g_gui) {
209  cv::destroyWindow(g_window_name);
210  }
211  return 0;
212 }
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
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())
std::string filename
void imageCb(const sensor_msgs::ImageConstPtr &msg)
Definition: image_view.cpp:68
bool g_do_dynamic_scaling
Definition: image_view.cpp:54
static void mouseCb(int event, int x, int y, int flags, void *param)
Definition: image_view.cpp:109
void publish(const boost::shared_ptr< M > &message) const
int main(int argc, char **argv)
Definition: image_view.cpp:138
f
boost::format g_filename_format
Definition: image_view.cpp:49
boost::mutex g_image_mutex
Definition: image_view.cpp:50
std::string resolveName(const std::string &name, bool remap=true) const
int g_colormap
Definition: image_view.cpp:55
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
#define ROS_WARN(...)
ROSCPP_DECL void spin(Spinner &spinner)
ros::Publisher g_pub
Definition: image_view.cpp:53
#define ROS_ERROR_THROTTLE(rate,...)
std::vector< std::string > V_string
ROSCPP_DECL std::string remap(const std::string &name)
std::string g_window_name
Definition: image_view.cpp:51
#define ROS_WARN_ONCE(...)
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
double g_max_image_value
Definition: image_view.cpp:57
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void startWindowThread()
bool g_gui
Definition: image_view.cpp:52
double g_min_image_value
Definition: image_view.cpp:56
uint32_t getNumSubscribers() const
#define ROS_INFO_STREAM(args)
cv::Mat g_last_image
Definition: image_view.cpp:48
bool getParam(const std::string &key, std::string &s) const
CvImageConstPtr cvtColorForDisplay(const CvImageConstPtr &source, const std::string &encoding=std::string(), const CvtColorForDisplayOptions options=CvtColorForDisplayOptions())
ROSCPP_DECL void removeROSArgs(int argc, const char *const *argv, V_string &args_out)
void reconfigureCb(image_view::ImageViewConfig &config, uint32_t level)
Definition: image_view.cpp:59
int g_count
Definition: image_view.cpp:47
bool hasParam(const std::string &key) const
#define ROS_ERROR_STREAM(args)


image_view
Author(s): Patrick Mihelich
autogenerated on Thu Nov 7 2019 03:45:05