40 #include <opencv2/imgproc/imgproc.hpp> 42 #include <QFileDialog> 43 #include <QMessageBox> 52 , rotate_state_(ROTATE_0)
54 setObjectName(
"ImageView");
69 ui_.color_scheme_combo_box->setCurrentIndex(
ui_.color_scheme_combo_box->findText(
"Gray"));
72 ui_.topics_combo_box->setCurrentIndex(
ui_.topics_combo_box->findText(
""));
73 connect(
ui_.topics_combo_box, SIGNAL(currentIndexChanged(
int)),
this, SLOT(
onTopicChanged(
int)));
75 ui_.refresh_topics_push_button->setIcon(QIcon::fromTheme(
"view-refresh"));
76 connect(
ui_.refresh_topics_push_button, SIGNAL(pressed()),
this, SLOT(
updateTopicList()));
78 ui_.zoom_1_push_button->setIcon(QIcon::fromTheme(
"zoom-original"));
79 connect(
ui_.zoom_1_push_button, SIGNAL(toggled(
bool)),
this, SLOT(
onZoom1(
bool)));
81 connect(
ui_.dynamic_range_check_box, SIGNAL(toggled(
bool)),
this, SLOT(
onDynamicRange(
bool)));
83 ui_.save_as_image_push_button->setIcon(QIcon::fromTheme(
"document-save-as"));
84 connect(
ui_.save_as_image_push_button, SIGNAL(pressed()),
this, SLOT(
saveImage()));
89 const QStringList& argv = context.
argv();
96 ui_.image_frame->setOuterLayout(
ui_.image_layout);
98 QRegExp rx(
"([a-zA-Z/][a-zA-Z0-9_/]*)?");
99 ui_.publish_click_location_topic_line_edit->setValidator(
new QRegExpValidator(rx,
this));
100 connect(
ui_.publish_click_location_check_box, SIGNAL(toggled(
bool)),
this, SLOT(
onMousePublish(
bool)));
101 connect(
ui_.image_frame, SIGNAL(mouseLeft(
int,
int)),
this, SLOT(
onMouseLeft(
int,
int)));
102 connect(
ui_.publish_click_location_topic_line_edit, SIGNAL(editingFinished()),
this, SLOT(
onPubTopicChanged()));
104 connect(
ui_.smooth_image_check_box, SIGNAL(toggled(
bool)),
ui_.image_frame, SLOT(onSmoothImageChanged(
bool)));
106 connect(
ui_.rotate_left_push_button, SIGNAL(clicked(
bool)),
this, SLOT(
onRotateLeft()));
107 connect(
ui_.rotate_right_push_button, SIGNAL(clicked(
bool)),
this, SLOT(
onRotateRight()));
110 ui_.rotate_label->setMinimumWidth(
111 ui_.rotate_label->fontMetrics().width(
"XXX°")
128 QString topic =
ui_.topics_combo_box->currentText();
130 instance_settings.
setValue(
"topic", topic);
131 instance_settings.
setValue(
"zoom1",
ui_.zoom_1_push_button->isChecked());
132 instance_settings.
setValue(
"dynamic_range",
ui_.dynamic_range_check_box->isChecked());
133 instance_settings.
setValue(
"max_range",
ui_.max_range_double_spin_box->value());
134 instance_settings.
setValue(
"publish_click_location",
ui_.publish_click_location_check_box->isChecked());
135 instance_settings.
setValue(
"mouse_pub_topic",
ui_.publish_click_location_topic_line_edit->text());
137 instance_settings.
setValue(
"num_gridlines",
ui_.num_gridlines_spin_box->value());
138 instance_settings.
setValue(
"smooth_image",
ui_.smooth_image_check_box->isChecked());
144 bool zoom1_checked = instance_settings.
value(
"zoom1",
false).toBool();
145 ui_.zoom_1_push_button->setChecked(zoom1_checked);
147 bool dynamic_range_checked = instance_settings.
value(
"dynamic_range",
false).toBool();
148 ui_.dynamic_range_check_box->setChecked(dynamic_range_checked);
150 double max_range = instance_settings.
value(
"max_range",
ui_.max_range_double_spin_box->value()).toDouble();
151 ui_.max_range_double_spin_box->setValue(max_range);
156 QString topic = instance_settings.
value(
"topic",
"").toString();
168 bool publish_click_location = instance_settings.
value(
"publish_click_location",
false).toBool();
169 ui_.publish_click_location_check_box->setChecked(publish_click_location);
171 QString pub_topic = instance_settings.
value(
"mouse_pub_topic",
"").toString();
172 ui_.publish_click_location_topic_line_edit->setText(pub_topic);
174 bool toolbar_hidden = instance_settings.
value(
"toolbar_hidden",
false).toBool();
177 bool smooth_image_checked = instance_settings.
value(
"smooth_image",
false).toBool();
178 ui_.smooth_image_check_box->setChecked(smooth_image_checked);
188 static const std::map<std::string, int> COLOR_SCHEME_MAP
191 {
"Autumn", cv::COLORMAP_AUTUMN },
192 {
"Bone", cv::COLORMAP_BONE },
193 {
"Cool", cv::COLORMAP_COOL },
194 {
"Hot", cv::COLORMAP_HOT },
195 {
"Hsv", cv::COLORMAP_HSV },
196 {
"Jet", cv::COLORMAP_JET },
197 {
"Ocean", cv::COLORMAP_OCEAN },
198 {
"Pink", cv::COLORMAP_PINK },
199 {
"Rainbow", cv::COLORMAP_RAINBOW },
200 {
"Spring", cv::COLORMAP_SPRING },
201 {
"Summer", cv::COLORMAP_SUMMER },
202 {
"Winter", cv::COLORMAP_WINTER }
205 for (
const auto& kv : COLOR_SCHEME_MAP)
207 ui_.color_scheme_combo_box->addItem(QString::fromStdString(kv.first), QVariant(kv.second));
213 QSet<QString> message_types;
214 message_types.insert(
"sensor_msgs/Image");
215 QSet<QString> message_sub_types;
216 message_sub_types.insert(
"sensor_msgs/CompressedImage");
219 QList<QString> transports;
222 for (std::vector<std::string>::const_iterator it = declared.begin(); it != declared.end(); it++)
225 QString transport = it->c_str();
228 QString prefix =
"image_transport/";
229 if (transport.startsWith(prefix))
231 transport = transport.mid(prefix.length());
233 transports.append(transport);
236 QString selected =
ui_.topics_combo_box->currentText();
239 QList<QString> topics =
getTopics(message_types, message_sub_types, transports).values();
242 ui_.topics_combo_box->clear();
243 for (QList<QString>::const_iterator it = topics.begin(); it != topics.end(); it++)
246 label.replace(
" ",
"/");
247 ui_.topics_combo_box->addItem(label, QVariant(*it));
256 QSet<QString> message_sub_types;
257 return getTopics(message_types, message_sub_types, transports).values();
260 QSet<QString>
ImageView::getTopics(
const QSet<QString>& message_types,
const QSet<QString>& message_sub_types,
const QList<QString>& transports)
265 QSet<QString> all_topics;
266 for (ros::master::V_TopicInfo::const_iterator it = topic_info.begin(); it != topic_info.end(); it++)
268 all_topics.insert(it->name.c_str());
271 QSet<QString> topics;
272 for (ros::master::V_TopicInfo::const_iterator it = topic_info.begin(); it != topic_info.end(); it++)
274 if (message_types.contains(it->datatype.c_str()))
276 QString topic = it->name.c_str();
279 topics.insert(topic);
283 for (QList<QString>::const_iterator jt = transports.begin(); jt != transports.end(); jt++)
285 if (all_topics.contains(topic +
"/" + *jt))
287 QString sub = topic +
" " + *jt;
293 if (message_sub_types.contains(it->datatype.c_str()))
295 QString topic = it->name.c_str();
296 int index = topic.lastIndexOf(
"/");
299 topic.replace(index, 1,
" ");
300 topics.insert(topic);
310 int index =
ui_.topics_combo_box->findText(topic);
314 QString label(topic);
315 label.replace(
" ",
"/");
316 ui_.topics_combo_box->addItem(label, QVariant(topic));
317 index =
ui_.topics_combo_box->findText(topic);
319 ui_.topics_combo_box->setCurrentIndex(index);
327 ui_.image_frame->setImage(QImage());
329 QStringList parts =
ui_.topics_combo_box->itemData(index).toString().split(
" ");
330 QString topic = parts.first();
331 QString transport = parts.length() == 2 ? parts.last() :
"raw";
333 if (!topic.isEmpty())
341 QMessageBox::warning(
widget_, tr(
"Loading image transport plugin failed"), e.what());
352 if (
ui_.image_frame->getImage().isNull())
356 ui_.image_frame->setInnerFrameFixedSize(
ui_.image_frame->getImage().size());
358 ui_.image_frame->setInnerFrameMinimumSize(QSize(80, 60));
359 ui_.image_frame->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
360 widget_->setMinimumSize(QSize(80, 60));
361 widget_->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
367 ui_.max_range_double_spin_box->setEnabled(!checked);
378 QImage img =
ui_.image_frame->getImageCopy();
380 QString file_name = QFileDialog::getSaveFileName(
widget_, tr(
"Save as image"),
"image.png", tr(
"Image (*.bmp *.jpg *.png *.tiff)"));
381 if (file_name.isEmpty())
391 std::string topicName;
394 topicName =
ui_.publish_click_location_topic_line_edit->text().toStdString();
400 topicName =
"mouse_left";
402 ui_.publish_click_location_topic_line_edit->setText(QString::fromStdString(topicName));
415 if(
ui_.publish_click_location_check_box->isChecked() && !
ui_.image_frame->getImage().isNull())
417 geometry_msgs::Point clickCanvasLocation;
419 clickCanvasLocation.x = round((
double)x/(
double)
ui_.image_frame->width()*(double)
ui_.image_frame->getImage().width());
420 clickCanvasLocation.y = round((
double)y/(
double)
ui_.image_frame->height()*(double)
ui_.image_frame->getImage().height());
421 clickCanvasLocation.z = 0;
423 geometry_msgs::Point clickLocation = clickCanvasLocation;
428 clickLocation.x = clickCanvasLocation.y;
429 clickLocation.y =
ui_.image_frame->getImage().width() - clickCanvasLocation.x;
432 clickLocation.x =
ui_.image_frame->getImage().width() - clickCanvasLocation.x;
433 clickLocation.y =
ui_.image_frame->getImage().height() - clickCanvasLocation.y;
436 clickLocation.x =
ui_.image_frame->getImage().height() - clickCanvasLocation.y;
437 clickLocation.y = clickCanvasLocation.x;
455 ui_.toolbar_widget->setVisible(!hide);
479 case ROTATE_0:
ui_.rotate_label->setText(
"0°");
break;
480 case ROTATE_90:
ui_.rotate_label->setText(
"90°");
break;
490 if (pixel[0] + pixel[1] + pixel[2] > 3 * 127)
491 pixel = cv::Vec3b(0,0,0);
493 pixel = cv::Vec3b(255,255,255);
507 indices.append(size / 2);
510 indices.append(size / 2 - 1);
511 index = 1.0f * (size - 1) / 2;
517 indices.append(round(index));
519 indices.append(size - 1 - round(index));
527 indices.append(round(index));
528 indices.append(size - 1 - round(index));
539 for (QList<int>::const_iterator x = columns.begin(); x != columns.end(); ++x)
549 for (QList<int>::const_iterator y = rows.begin(); y != rows.end(); ++y)
575 if (msg->encoding ==
"CV_8UC3")
579 }
else if (msg->encoding ==
"8UC1") {
582 }
else if (msg->encoding ==
"16UC1" || msg->encoding ==
"32FC1") {
585 double max =
ui_.max_range_double_spin_box->value();
586 if (msg->encoding ==
"16UC1") max *= 1000;
587 if (
ui_.dynamic_range_check_box->isChecked())
590 cv::minMaxLoc(cv_ptr->image, &min, &max);
597 cv::Mat img_scaled_8u;
598 cv::Mat(cv_ptr->image-min).convertTo(img_scaled_8u, CV_8UC1, 255. / (max - min));
600 const auto color_scheme_index =
ui_.color_scheme_combo_box->currentIndex();
601 const auto color_scheme =
ui_.color_scheme_combo_box->itemData(color_scheme_index).toInt();
602 if (color_scheme == -1) {
605 cv::Mat img_color_scheme;
606 cv::applyColorMap(img_scaled_8u, img_color_scheme, color_scheme);
610 qWarning(
"ImageView.callback_image() could not convert image from '%s' to 'rgb8' (%s)", msg->encoding.c_str(), e.what());
611 ui_.image_frame->setImage(QImage());
617 qWarning(
"ImageView.callback_image() while trying to convert image from '%s' to 'rgb8' an exception was thrown (%s)", msg->encoding.c_str(), e.what());
618 ui_.image_frame->setImage(QImage());
653 ui_.image_frame->setImage(image);
655 if (!
ui_.zoom_1_push_button->isEnabled())
657 ui_.zoom_1_push_button->setEnabled(
true);
virtual void onMouseLeft(int x, int y)
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
virtual void onPubTopicChanged()
virtual void initPlugin(qt_gui_cpp::PluginContext &context)
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())
QAction * hide_toolbar_action_
virtual QSet< QString > getTopics(const QSet< QString > &message_types, const QSet< QString > &message_sub_types, const QList< QString > &transports)
virtual void callbackImage(const sensor_msgs::Image::ConstPtr &msg)
ros::Publisher pub_mouse_left_
void publish(const boost::shared_ptr< M > &message) const
virtual ROS_DEPRECATED QList< QString > getTopicList(const QSet< QString > &message_types, const QList< QString > &transports)
image_transport::Subscriber subscriber_
virtual void onMousePublish(bool checked)
virtual void onDynamicRange(bool checked)
ROSCPP_DECL bool getTopics(V_TopicInfo &topics)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void addWidget(QWidget *widget)
std::vector< TopicInfo > V_TopicInfo
virtual void onZoom1(bool checked)
const QStringList & argv() const
virtual void onRotateLeft()
virtual void onTopicChanged(int index)
virtual void shutdownPlugin()
std::string getTopic() const
std::vector< std::string > getDeclaredTransports() const
virtual void onRotateRight()
void setValue(const QString &key, const QVariant &value)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ros::NodeHandle & getNodeHandle() const
RotateState rotate_state_
virtual void updateTopicList()
virtual void saveSettings(qt_gui_cpp::Settings &plugin_settings, qt_gui_cpp::Settings &instance_settings) const
virtual void selectTopic(const QString &topic)
virtual void overlayGrid()
virtual void restoreSettings(const qt_gui_cpp::Settings &plugin_settings, const qt_gui_cpp::Settings &instance_settings)
virtual void onHideToolbarChanged(bool hide)
QList< int > getGridIndices(int size) const
virtual void invertPixels(int x, int y)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
virtual void updateNumGridlines()
virtual void setColorSchemeList()