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());
 
  140   instance_settings.
setValue(
"color_scheme", 
ui_.color_scheme_combo_box->currentIndex());
 
  145   bool zoom1_checked = instance_settings.
value(
"zoom1", 
false).toBool();
 
  146   ui_.zoom_1_push_button->setChecked(zoom1_checked);
 
  148   bool dynamic_range_checked = instance_settings.
value(
"dynamic_range", 
false).toBool();
 
  149   ui_.dynamic_range_check_box->setChecked(dynamic_range_checked);
 
  151   double max_range = instance_settings.
value(
"max_range", 
ui_.max_range_double_spin_box->value()).toDouble();
 
  152   ui_.max_range_double_spin_box->setValue(max_range);
 
  157   QString topic = instance_settings.
value(
"topic", 
"").toString();
 
  169   bool publish_click_location = instance_settings.
value(
"publish_click_location", 
false).toBool();
 
  170   ui_.publish_click_location_check_box->setChecked(publish_click_location);
 
  172   QString pub_topic = instance_settings.
value(
"mouse_pub_topic", 
"").toString();
 
  173   ui_.publish_click_location_topic_line_edit->setText(pub_topic);
 
  175   bool toolbar_hidden = instance_settings.
value(
"toolbar_hidden", 
false).toBool();
 
  178   bool smooth_image_checked = instance_settings.
value(
"smooth_image", 
false).toBool();
 
  179   ui_.smooth_image_check_box->setChecked(smooth_image_checked);
 
  186   int color_scheme = instance_settings.
value(
"color_scheme", 
ui_.color_scheme_combo_box->currentIndex()).toInt();
 
  187   ui_.color_scheme_combo_box->setCurrentIndex(color_scheme);
 
  192   static const std::map<std::string, int> COLOR_SCHEME_MAP
 
  195     { 
"Autumn", cv::COLORMAP_AUTUMN },
 
  196     { 
"Bone", cv::COLORMAP_BONE },
 
  197     { 
"Cool", cv::COLORMAP_COOL },
 
  198     { 
"Hot", cv::COLORMAP_HOT },
 
  199     { 
"Hsv", cv::COLORMAP_HSV },
 
  200     { 
"Jet", cv::COLORMAP_JET },
 
  201     { 
"Ocean", cv::COLORMAP_OCEAN },
 
  202     { 
"Pink", cv::COLORMAP_PINK },
 
  203     { 
"Rainbow", cv::COLORMAP_RAINBOW },
 
  204     { 
"Spring", cv::COLORMAP_SPRING },
 
  205     { 
"Summer", cv::COLORMAP_SUMMER },
 
  206     { 
"Winter", cv::COLORMAP_WINTER }
 
  209   for (
const auto& kv : COLOR_SCHEME_MAP)
 
  211     ui_.color_scheme_combo_box->addItem(QString::fromStdString(kv.first), QVariant(kv.second));
 
  217   QSet<QString> message_types;
 
  218   message_types.insert(
"sensor_msgs/Image");
 
  219   QSet<QString> message_sub_types;
 
  220   message_sub_types.insert(
"sensor_msgs/CompressedImage");
 
  223   QList<QString> transports;
 
  226   for (std::vector<std::string>::const_iterator it = declared.begin(); it != declared.end(); it++)
 
  229     QString transport = it->c_str();
 
  232     QString prefix = 
"image_transport/";
 
  233     if (transport.startsWith(prefix))
 
  235       transport = transport.mid(prefix.length());
 
  237     transports.append(transport);
 
  240   QString selected = 
ui_.topics_combo_box->currentText();
 
  243   QList<QString> topics = 
getTopics(message_types, message_sub_types, transports).values();
 
  246   ui_.topics_combo_box->clear();
 
  247   for (QList<QString>::const_iterator it = topics.begin(); it != topics.end(); it++)
 
  250     label.replace(
" ", 
"/");
 
  251     ui_.topics_combo_box->addItem(label, QVariant(*it));
 
  260   QSet<QString> message_sub_types;
 
  261   return getTopics(message_types, message_sub_types, transports).values();
 
  264 QSet<QString> 
ImageView::getTopics(
const QSet<QString>& message_types, 
const QSet<QString>& message_sub_types, 
const QList<QString>& transports)
 
  269   QSet<QString> all_topics;
 
  270   for (ros::master::V_TopicInfo::const_iterator it = topic_info.begin(); it != topic_info.end(); it++)
 
  272     all_topics.insert(it->name.c_str());
 
  275   QSet<QString> topics;
 
  276   for (ros::master::V_TopicInfo::const_iterator it = topic_info.begin(); it != topic_info.end(); it++)
 
  278     if (message_types.contains(it->datatype.c_str()))
 
  280       QString topic = it->name.c_str();
 
  283       topics.insert(topic);
 
  287       for (QList<QString>::const_iterator jt = transports.begin(); jt != transports.end(); jt++)
 
  289         if (all_topics.contains(topic + 
"/" + *jt))
 
  291           QString sub = topic + 
" " + *jt;
 
  297     if (message_sub_types.contains(it->datatype.c_str()))
 
  299       QString topic = it->name.c_str();
 
  300       int index = topic.lastIndexOf(
"/");
 
  303         topic.replace(index, 1, 
" ");
 
  304         topics.insert(topic);
 
  314   int index = 
ui_.topics_combo_box->findText(topic);
 
  318     QString label(topic);
 
  319     label.replace(
" ", 
"/");
 
  320     ui_.topics_combo_box->addItem(label, QVariant(topic));
 
  321     index = 
ui_.topics_combo_box->findText(topic);
 
  323   ui_.topics_combo_box->setCurrentIndex(index);
 
  333   ui_.image_frame->setImage(QImage());
 
  335   QStringList parts = 
ui_.topics_combo_box->itemData(index).toString().split(
" ");
 
  336   QString topic = parts.first();
 
  337   QString transport = parts.length() == 2 ? parts.last() : 
"raw";
 
  339   if (!topic.isEmpty())
 
  347       QMessageBox::warning(
widget_, tr(
"Loading image transport plugin failed"), e.what());
 
  358     if (
ui_.image_frame->getImage().isNull())
 
  362     ui_.image_frame->setInnerFrameFixedSize(
ui_.image_frame->getImage().size());
 
  364     ui_.image_frame->setInnerFrameMinimumSize(QSize(80, 60));
 
  365     ui_.image_frame->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
 
  366     widget_->setMinimumSize(QSize(80, 60));
 
  367     widget_->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
 
  373   ui_.max_range_double_spin_box->setEnabled(!checked);
 
  384   QImage img = 
ui_.image_frame->getImageCopy();
 
  386   QString file_name = QFileDialog::getSaveFileName(
widget_, tr(
"Save as image"), 
"image.png", tr(
"Image (*.bmp *.jpg *.png *.tiff)"));
 
  387   if (file_name.isEmpty())
 
  397   std::string topicName;
 
  400     topicName = 
ui_.publish_click_location_topic_line_edit->text().toStdString();
 
  406       topicName = 
"mouse_left";
 
  408     ui_.publish_click_location_topic_line_edit->setText(QString::fromStdString(topicName));
 
  421   if(
ui_.publish_click_location_check_box->isChecked() && !
ui_.image_frame->getImage().isNull())
 
  423     geometry_msgs::Point clickCanvasLocation;
 
  425     clickCanvasLocation.x = round((
double)x/(
double)
ui_.image_frame->width()*(
double)
ui_.image_frame->getImage().width());
 
  426     clickCanvasLocation.y = round((
double)y/(
double)
ui_.image_frame->height()*(
double)
ui_.image_frame->getImage().height());
 
  427     clickCanvasLocation.z = 0;
 
  429     geometry_msgs::Point clickLocation = clickCanvasLocation;
 
  434         clickLocation.x = clickCanvasLocation.y;
 
  435         clickLocation.y = 
ui_.image_frame->getImage().width() - clickCanvasLocation.x;
 
  438         clickLocation.x = 
ui_.image_frame->getImage().width() - clickCanvasLocation.x;
 
  439         clickLocation.y = 
ui_.image_frame->getImage().height() - clickCanvasLocation.y;
 
  442         clickLocation.x = 
ui_.image_frame->getImage().height() - clickCanvasLocation.y;
 
  443         clickLocation.y = clickCanvasLocation.x;
 
  461   ui_.toolbar_widget->setVisible(!hide);
 
  485     case ROTATE_0:   
ui_.rotate_label->setText(
"0°"); 
break;
 
  486     case ROTATE_90:  
ui_.rotate_label->setText(
"90°"); 
break;
 
  496   if (pixel[0] + pixel[1] + pixel[2] > 3 * 127)
 
  497     pixel = cv::Vec3b(0,0,0);
 
  499     pixel = cv::Vec3b(255,255,255);
 
  513     indices.append(size / 2);
 
  516       indices.append(size / 2 - 1);
 
  517     index = 1.0f * (size - 1) / 2;
 
  523     indices.append(round(index));
 
  525     indices.append(size - 1 - round(index));
 
  533     indices.append(round(index));
 
  534     indices.append(size - 1 - round(index));
 
  545   for (QList<int>::const_iterator x = columns.begin(); x != columns.end(); ++x)
 
  555   for (QList<int>::const_iterator y = rows.begin(); y != rows.end(); ++y)
 
  581       if (msg->encoding == 
"CV_8UC3")
 
  585       } 
else if (msg->encoding == 
"8UC1") {
 
  588       } 
else if (msg->encoding == 
"16UC1" || msg->encoding == 
"32FC1") {
 
  591         double max = 
ui_.max_range_double_spin_box->value();
 
  592         if (msg->encoding == 
"16UC1") max *= 1000;
 
  593         if (
ui_.dynamic_range_check_box->isChecked())
 
  596           cv::minMaxLoc(cv_ptr->image, &min, &max);
 
  603         cv::Mat img_scaled_8u;
 
  604         cv::Mat(cv_ptr->image-min).convertTo(img_scaled_8u, CV_8UC1, 255. / (max - min));
 
  606         const auto color_scheme_index = 
ui_.color_scheme_combo_box->currentIndex();
 
  607         const auto color_scheme = 
ui_.color_scheme_combo_box->itemData(color_scheme_index).toInt();
 
  608         if (color_scheme == -1) {
 
  611           cv::Mat img_color_scheme;
 
  612           cv::applyColorMap(img_scaled_8u, img_color_scheme, color_scheme);
 
  616         qWarning(
"ImageView.callback_image() could not convert image from '%s' to 'rgb8' (%s)", msg->encoding.c_str(), e.what());
 
  617         ui_.image_frame->setImage(QImage());
 
  623       qWarning(
"ImageView.callback_image() while trying to convert image from '%s' to 'rgb8' an exception was thrown (%s)", msg->encoding.c_str(), e.what());
 
  624       ui_.image_frame->setImage(QImage());
 
  659   ui_.image_frame->setImage(image);
 
  661   if (!
ui_.zoom_1_push_button->isEnabled())
 
  663     ui_.zoom_1_push_button->setEnabled(
true);