|
@@ -0,0 +1,2497 @@
|
|
|
+/*
|
|
|
+ * ImageLabeler.cpp
|
|
|
+ *
|
|
|
+ * Created on: Oct 4, 2011
|
|
|
+ * Author: Gapchich Vladislav
|
|
|
+ */
|
|
|
+
|
|
|
+#include "ImageLabeler.h"
|
|
|
+#include "functions.h"
|
|
|
+
|
|
|
+#include <QApplication>
|
|
|
+#include <QFrame>
|
|
|
+#include <QMenuBar>
|
|
|
+#include <QMenu>
|
|
|
+#include <QAction>
|
|
|
+#include <QBoxLayout>
|
|
|
+#include <QGridLayout>
|
|
|
+#include <QPixmap>
|
|
|
+#include <QLabel>
|
|
|
+#include <QPushButton>
|
|
|
+#include <QButtonGroup>
|
|
|
+#include <QListWidget>
|
|
|
+#include <QListWidgetItem>
|
|
|
+#include <QFileDialog>
|
|
|
+#include <QColorDialog>
|
|
|
+#include <QDir>
|
|
|
+#include <QMessageBox>
|
|
|
+#include <QListIterator>
|
|
|
+#include <QDomDocument>
|
|
|
+#include <QFile>
|
|
|
+#include <QKeyEvent>
|
|
|
+#include <QDebug>
|
|
|
+
|
|
|
+ImageLabeler::ImageLabeler(QWidget *aParent) :
|
|
|
+ QMainWindow(aParent)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * Variables
|
|
|
+ */
|
|
|
+
|
|
|
+ list_images_ = new QStringList();
|
|
|
+
|
|
|
+ main_label_ = -1;
|
|
|
+ pure_data_ = 0;
|
|
|
+ //label_ID_ = -1;
|
|
|
+
|
|
|
+ /* options */
|
|
|
+ auto_color_generation_ = 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * menu bar part begins
|
|
|
+ */
|
|
|
+
|
|
|
+ menu_bar_ = new QMenuBar(this);
|
|
|
+ setMenuBar(menu_bar_);
|
|
|
+
|
|
|
+ menu_file_ = new QMenu(menu_bar_);
|
|
|
+ menu_file_->setTitle(tr("&File"));
|
|
|
+ menu_edit_ = new QMenu(menu_bar_);
|
|
|
+ menu_edit_->setTitle(tr("&Edit"));
|
|
|
+ menu_help_ = new QMenu(menu_bar_);
|
|
|
+ menu_help_->setTitle(tr("&Help"));
|
|
|
+
|
|
|
+ action_open_images_ = new QAction(this);
|
|
|
+ action_open_images_->setText(tr("&Load images"));
|
|
|
+
|
|
|
+ action_open_labeled_image_ = new QAction(this);
|
|
|
+ action_open_labeled_image_->setText(tr("&Open labeled image"));
|
|
|
+
|
|
|
+ action_load_legend_ = new QAction(this);
|
|
|
+ action_load_legend_->setText(tr("Load &legend"));
|
|
|
+
|
|
|
+ action_save_labels_ = new QAction(this);
|
|
|
+ action_save_labels_->setText(tr("&Save all info"));
|
|
|
+ action_save_labels_->setEnabled(false);
|
|
|
+
|
|
|
+ action_save_segmented_ = new QAction(this);
|
|
|
+ action_save_segmented_->setText(tr("Save segmented &picture"));
|
|
|
+ action_save_segmented_->setEnabled(false);
|
|
|
+
|
|
|
+ action_save_legend_ = new QAction(this);
|
|
|
+ action_save_legend_->setText(tr("Save &legend"));
|
|
|
+ action_save_legend_->setEnabled(false);
|
|
|
+
|
|
|
+ action_undo_ = new QAction(this);
|
|
|
+ action_undo_->setText(tr("&Undo"));
|
|
|
+ action_undo_->setEnabled(false);
|
|
|
+ action_redo_ = new QAction(this);
|
|
|
+ action_redo_->setText(tr("&Redo"));
|
|
|
+ action_redo_->setEnabled(false);
|
|
|
+ action_bound_box_tool_ = new QAction(this);
|
|
|
+ action_bound_box_tool_->setText(tr("Bounding box tool"));
|
|
|
+ action_bound_box_tool_->setEnabled(false);
|
|
|
+ action_polygon_tool_ = new QAction(this);
|
|
|
+ action_polygon_tool_->setText(tr("&Polygon tool"));
|
|
|
+ action_polygon_tool_->setEnabled(false);
|
|
|
+ action_tagging_tool_ = new QAction(this);
|
|
|
+ action_tagging_tool_->setText(tr("&Tagging tool"));
|
|
|
+ action_tagging_tool_->setEnabled(false);
|
|
|
+ action_add_description_ = new QAction(this);
|
|
|
+ action_add_description_->setText(tr("&Add image description"));
|
|
|
+ action_add_description_->setEnabled(false);
|
|
|
+ action_options_ = new QAction(this);
|
|
|
+ action_options_->setText(tr("&Options"));
|
|
|
+
|
|
|
+ action_help_content_ = new QAction(this);
|
|
|
+ action_help_content_->setText(tr("&Help content"));
|
|
|
+ action_help_content_->setEnabled(false);
|
|
|
+ action_about_ = new QAction(this);
|
|
|
+ action_about_->setText(tr("&About"));
|
|
|
+ action_about_->setEnabled(false);
|
|
|
+ /* ------------------ */
|
|
|
+
|
|
|
+ action_quit_ = new QAction(this);
|
|
|
+ action_quit_->setText(tr("&Quit"));
|
|
|
+
|
|
|
+ menu_bar_->addAction(menu_file_->menuAction());
|
|
|
+ menu_bar_->addAction(menu_edit_->menuAction());
|
|
|
+ menu_bar_->addAction(menu_help_->menuAction());
|
|
|
+
|
|
|
+ menu_file_->addAction(action_open_images_);
|
|
|
+ menu_file_->addAction(action_open_labeled_image_);
|
|
|
+ menu_file_->addAction(action_load_legend_);
|
|
|
+ menu_file_->addAction(action_save_segmented_);
|
|
|
+ menu_file_->addAction(action_save_legend_);
|
|
|
+ menu_file_->addAction(action_save_labels_);
|
|
|
+ menu_file_->addAction(action_quit_);
|
|
|
+
|
|
|
+ menu_edit_->addAction(action_undo_);
|
|
|
+ menu_edit_->addAction(action_redo_);
|
|
|
+ menu_edit_->addAction(action_bound_box_tool_);
|
|
|
+ menu_edit_->addAction(action_polygon_tool_);
|
|
|
+ menu_edit_->addAction(action_tagging_tool_);
|
|
|
+ menu_edit_->addAction(action_add_description_);
|
|
|
+ menu_edit_->addAction(action_options_);
|
|
|
+
|
|
|
+ menu_help_->addAction(action_help_content_);
|
|
|
+ menu_help_->addAction(action_about_);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * popup menu part begins
|
|
|
+ */
|
|
|
+ popup_area_list_ = new QMenu;
|
|
|
+
|
|
|
+ action_delete_area_ = new QAction(this);
|
|
|
+ action_delete_area_->setText(tr("&Delete area"));
|
|
|
+ action_edit_area_ = new QAction(this);
|
|
|
+ action_edit_area_->setText(tr("&Change area"));
|
|
|
+
|
|
|
+ popup_area_list_->addAction(action_delete_area_);
|
|
|
+ popup_area_list_->addAction(action_edit_area_);
|
|
|
+
|
|
|
+ popup_label_list_ = new QMenu;
|
|
|
+
|
|
|
+ action_set_color_ = new QAction(this);
|
|
|
+ action_set_color_->setText(tr("Set &color"));
|
|
|
+ action_toggle_priority_ = new QAction(this);
|
|
|
+ action_toggle_priority_->setText(tr("Toggle &priority"));
|
|
|
+ action_delete_label_ = new QAction(this);
|
|
|
+ action_delete_label_->setText(tr("&Delete"));
|
|
|
+
|
|
|
+ popup_label_list_->addAction(action_set_color_);
|
|
|
+ popup_label_list_->addAction(action_toggle_priority_);
|
|
|
+ popup_label_list_->addAction(action_delete_label_);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * widgets part begins
|
|
|
+ */
|
|
|
+ central_widget_ = new QWidget(this);
|
|
|
+ setCentralWidget(central_widget_);
|
|
|
+
|
|
|
+ frame_toolbox_ = new QFrame(central_widget_);
|
|
|
+ frame_toolbox_->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
|
|
|
+ frame_toolbox_->setLineWidth(0);
|
|
|
+ frame_toolbox_->setMidLineWidth(0);
|
|
|
+ frame_center_ = new QFrame(central_widget_);
|
|
|
+ //frame_image_->setFrameStyle(QFrame::Box | QFrame::Plain);
|
|
|
+ //frame_image_->setLineWidth(1);
|
|
|
+ frame_image_ = new QFrame(frame_center_);
|
|
|
+ //frame_image_->setStyleSheet("QWidget {background: #888888;}");
|
|
|
+ frame_image_->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
|
|
|
+ frame_image_->setLineWidth(0);
|
|
|
+ frame_image_->setMidLineWidth(0);
|
|
|
+ frame_labelbox_ = new QFrame(central_widget_);
|
|
|
+ frame_labelbox_->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
|
|
|
+ frame_labelbox_->setLineWidth(0);
|
|
|
+ frame_labelbox_->setMidLineWidth(0);
|
|
|
+
|
|
|
+ image_ = new QPixmap(500, 500);
|
|
|
+ image_->fill(QColor(Qt::white));
|
|
|
+
|
|
|
+ //image_holder_ = new ImageHolder(frame_image_);
|
|
|
+ image_holder_ = new ImageHolder(frame_image_);
|
|
|
+ image_holder_->setPixmap(*image_);
|
|
|
+ image_holder_->setStyleSheet("QLabel {background: #ffffff;}");
|
|
|
+ image_holder_->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
|
|
|
+ image_holder_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
|
+ image_holder_->setFocusPolicy(Qt::StrongFocus);
|
|
|
+ image_holder_->setFocus();
|
|
|
+ //image_holder_->setScaledContents(true);
|
|
|
+ image_holder_->setFrameStyle(QFrame::Box | QFrame::Plain);
|
|
|
+ image_holder_->setLineWidth(0);
|
|
|
+
|
|
|
+ list_label_ = new QListWidget(central_widget_);
|
|
|
+ list_label_->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
+ list_areas_ = new QListWidget(central_widget_);
|
|
|
+ list_areas_->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
+// addLabel(0, false, "BACKGROUND");
|
|
|
+// list_label_->item(0)->setFlags(Qt::ItemIsSelectable);
|
|
|
+ //QListWidgetItem *background = list_label_->item(0);
|
|
|
+ //qDebug() << background;
|
|
|
+ //background->setFlags(Qt::ItemIsSelectable);
|
|
|
+
|
|
|
+ label_toolbox_ = new QLabel(tr("Tool box"), frame_toolbox_);
|
|
|
+ label_list_areas_ = new QLabel(tr("Selected areas"), central_widget_);
|
|
|
+
|
|
|
+ /* buttons */
|
|
|
+ button_bound_box_tool_ = new QPushButton(frame_toolbox_);
|
|
|
+ button_bound_box_tool_->setText(tr("bbox"));
|
|
|
+ button_bound_box_tool_->setEnabled(false);
|
|
|
+ button_bound_box_tool_->setCheckable(true);
|
|
|
+ button_polygon_tool_ = new QPushButton(frame_toolbox_);
|
|
|
+ button_polygon_tool_->setText(tr("poly tool"));
|
|
|
+ button_polygon_tool_->setEnabled(false);
|
|
|
+ button_polygon_tool_->setCheckable(true);
|
|
|
+ button_tagging_tool_ = new QPushButton(frame_toolbox_);
|
|
|
+ button_tagging_tool_->setText(tr("tagging"));
|
|
|
+ button_tagging_tool_->setEnabled(false);
|
|
|
+ button_tagging_tool_->setCheckable(true);
|
|
|
+ button_clear_selection_tool_ = new QPushButton(frame_toolbox_);
|
|
|
+ button_clear_selection_tool_->setText(tr("clear selection"));
|
|
|
+ button_clear_selection_tool_->setEnabled(false);
|
|
|
+ button_generate_colors_ = new QPushButton(frame_toolbox_);
|
|
|
+ button_generate_colors_->setText(tr("generate label colors"));
|
|
|
+ button_generate_colors_->setEnabled(false);
|
|
|
+ button_delete_all_labels_ = new QPushButton(frame_toolbox_);
|
|
|
+ button_delete_all_labels_->setText(tr("delete all labels"));
|
|
|
+ button_delete_all_labels_->setEnabled(false);
|
|
|
+
|
|
|
+ group_tools_ = new QButtonGroup;
|
|
|
+ group_tools_->addButton(button_bound_box_tool_);
|
|
|
+ group_tools_->addButton(button_polygon_tool_);
|
|
|
+ group_tools_->addButton(button_tagging_tool_);
|
|
|
+
|
|
|
+ button_confirm_selection_ = new QPushButton(central_widget_);
|
|
|
+ button_confirm_selection_->setText(tr("Confirm selection"));
|
|
|
+ button_confirm_selection_->setEnabled(false);
|
|
|
+
|
|
|
+ button_add_label_ = new QPushButton(frame_labelbox_);
|
|
|
+ button_add_label_->setText(tr("Add label"));
|
|
|
+ button_add_label_->setEnabled(false);
|
|
|
+ button_remove_label_ = new QPushButton(frame_labelbox_);
|
|
|
+ button_remove_label_->setText(tr("Remove label"));
|
|
|
+ button_remove_label_->setEnabled(false);
|
|
|
+
|
|
|
+ button_prev_image_ = new QPushButton(central_widget_);
|
|
|
+ button_prev_image_->setText("←");
|
|
|
+ button_next_image_ = new QPushButton(central_widget_);
|
|
|
+ button_next_image_->setText("→");
|
|
|
+
|
|
|
+ /*
|
|
|
+ * layouts part begins
|
|
|
+ */
|
|
|
+ layout_main_ = new QHBoxLayout(central_widget_);
|
|
|
+ layout_left_ = new QVBoxLayout();
|
|
|
+ layout_toolbox_ = new QVBoxLayout();
|
|
|
+ layout_center_ = new QVBoxLayout();
|
|
|
+ layout_frame_image_ = new QVBoxLayout();
|
|
|
+ layout_image_widget_ = new QGridLayout();
|
|
|
+ layout_center_buttons_ = new QHBoxLayout();
|
|
|
+ layout_right_ = new QVBoxLayout();
|
|
|
+ layout_labelbox_ = new QVBoxLayout();
|
|
|
+ layout_labelbox_buttons_ = new QHBoxLayout();
|
|
|
+
|
|
|
+ layout_main_->addLayout(layout_left_);
|
|
|
+ layout_main_->addLayout(layout_center_);
|
|
|
+ layout_main_->addLayout(layout_right_);
|
|
|
+
|
|
|
+ /* making the center part stretchable */
|
|
|
+ layout_main_->setStretch(1, 1);
|
|
|
+
|
|
|
+ /* left part */
|
|
|
+ layout_left_->addWidget(frame_toolbox_);
|
|
|
+ frame_toolbox_->setLayout(layout_toolbox_);
|
|
|
+
|
|
|
+ layout_toolbox_->addWidget(label_toolbox_);
|
|
|
+ layout_toolbox_->addWidget(button_bound_box_tool_);
|
|
|
+ layout_toolbox_->addWidget(button_polygon_tool_);
|
|
|
+ layout_toolbox_->addWidget(button_tagging_tool_);
|
|
|
+ layout_toolbox_->addSpacing(10);
|
|
|
+ layout_toolbox_->addWidget(button_clear_selection_tool_);
|
|
|
+ layout_toolbox_->addWidget(button_delete_all_labels_);
|
|
|
+ layout_toolbox_->addSpacing(10);
|
|
|
+ layout_toolbox_->addWidget(button_generate_colors_);
|
|
|
+ /* stretch is for making toolbox as small as it can be */
|
|
|
+ layout_left_->addStretch(1);
|
|
|
+ layout_left_->addWidget(button_confirm_selection_);
|
|
|
+
|
|
|
+
|
|
|
+ /* central part */
|
|
|
+ layout_center_->addWidget(frame_center_);
|
|
|
+ frame_center_->setLayout(layout_frame_image_);
|
|
|
+
|
|
|
+ //layout_frame_image_->addWidget(image_holder_);
|
|
|
+ layout_frame_image_->setContentsMargins(0, 0, 0, 0);
|
|
|
+ layout_frame_image_->addWidget(frame_image_);
|
|
|
+
|
|
|
+ frame_image_->setLayout(layout_image_widget_);
|
|
|
+ layout_image_widget_->setRowStretch(0, 1);
|
|
|
+ layout_image_widget_->setColumnStretch(0, 1);
|
|
|
+ layout_image_widget_->addWidget(image_holder_, 1, 1);
|
|
|
+ layout_image_widget_->setRowStretch(2, 1);
|
|
|
+ layout_image_widget_->setColumnStretch(2, 1);
|
|
|
+
|
|
|
+ //layout_frame_image_->addStretch(1);
|
|
|
+ layout_frame_image_->addLayout(layout_center_buttons_);
|
|
|
+ layout_center_buttons_->addWidget(button_prev_image_);
|
|
|
+ layout_center_buttons_->addWidget(button_next_image_);
|
|
|
+
|
|
|
+ /* right part */
|
|
|
+ layout_right_->addWidget(frame_labelbox_);
|
|
|
+ frame_labelbox_->setFixedWidth(300);
|
|
|
+ frame_labelbox_->setLayout(layout_labelbox_);
|
|
|
+
|
|
|
+ layout_labelbox_->addLayout(layout_labelbox_buttons_);
|
|
|
+ layout_labelbox_buttons_->addWidget(button_add_label_);
|
|
|
+ layout_labelbox_buttons_->addWidget(button_remove_label_);
|
|
|
+
|
|
|
+ layout_labelbox_->addWidget(list_label_);
|
|
|
+ layout_labelbox_->addWidget(label_list_areas_);
|
|
|
+ layout_labelbox_->addWidget(list_areas_);
|
|
|
+
|
|
|
+ connect(
|
|
|
+ action_quit_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(close())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_open_images_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(loadImages())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_open_labeled_image_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(loadInfo())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_load_legend_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(loadLegendFromFile())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_save_legend_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(saveLegend())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_save_segmented_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(saveSegmentedPicture())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_save_labels_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(saveAllInfo())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_add_label_,
|
|
|
+ SIGNAL(clicked()),
|
|
|
+ this,
|
|
|
+ SLOT(addLabel())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_remove_label_,
|
|
|
+ SIGNAL(clicked()),
|
|
|
+ this, SLOT(removeLabel())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_next_image_,
|
|
|
+ SIGNAL(clicked()),
|
|
|
+ this,
|
|
|
+ SLOT(nextImage())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_prev_image_,
|
|
|
+ SIGNAL(clicked()),
|
|
|
+ this,
|
|
|
+ SLOT(prevImage())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_bound_box_tool_,
|
|
|
+ SIGNAL(toggled(bool)),
|
|
|
+ this,
|
|
|
+ SLOT(setBoundingBoxTool(bool))
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_polygon_tool_,
|
|
|
+ SIGNAL(toggled(bool)),
|
|
|
+ this,
|
|
|
+ SLOT(setPolygonTool(bool))
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_clear_selection_tool_,
|
|
|
+ SIGNAL(clicked()),
|
|
|
+ this,
|
|
|
+ SLOT(clearAllTool())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_generate_colors_,
|
|
|
+ SIGNAL(clicked()),
|
|
|
+ this,
|
|
|
+ SLOT(generateColors())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_delete_all_labels_,
|
|
|
+ SIGNAL(clicked()),
|
|
|
+ this,
|
|
|
+ SLOT(clearLabelList())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ button_confirm_selection_,
|
|
|
+ SIGNAL(clicked()),
|
|
|
+ this,
|
|
|
+ SLOT(confirmSelection())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ list_label_,
|
|
|
+ SIGNAL(itemChanged(QListWidgetItem *)),
|
|
|
+ this,
|
|
|
+ SLOT(editLabel(QListWidgetItem *))
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ list_label_,
|
|
|
+ SIGNAL(itemClicked(QListWidgetItem *)),
|
|
|
+ this,
|
|
|
+ SLOT(setLabelID(QListWidgetItem *))
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ list_areas_,
|
|
|
+ SIGNAL(itemDoubleClicked(QListWidgetItem *)),
|
|
|
+ image_holder_,
|
|
|
+ SLOT(focusOnArea(QListWidgetItem *))
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ list_areas_,
|
|
|
+ SIGNAL(customContextMenuRequested(const QPoint &)),
|
|
|
+ this,
|
|
|
+ SLOT(areaListPopupMenu(const QPoint &))
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ list_areas_,
|
|
|
+ SIGNAL(itemChanged(QListWidgetItem *)),
|
|
|
+ this,
|
|
|
+ SLOT(onAreaChange(QListWidgetItem *))
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ list_label_,
|
|
|
+ SIGNAL(customContextMenuRequested(const QPoint &)),
|
|
|
+ this,
|
|
|
+ SLOT(labelListPopupMenu(const QPoint &))
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_delete_area_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(deleteArea())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_edit_area_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(editArea())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_set_color_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(setLabelColor())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_toggle_priority_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(toggleLabelPriority())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_delete_label_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ this,
|
|
|
+ SLOT(removeLabel())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_add_description_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ &image_description_form_,
|
|
|
+ SLOT(show())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ action_options_,
|
|
|
+ SIGNAL(triggered()),
|
|
|
+ &options_form_,
|
|
|
+ SLOT(show())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ image_holder_,
|
|
|
+ SIGNAL(selectionStarted()),
|
|
|
+ this,
|
|
|
+ SLOT(onSelectionStarted())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ &image_description_form_,
|
|
|
+ SIGNAL(descriptionSet(QString)),
|
|
|
+ this,
|
|
|
+ SLOT(setDescription(QString))
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ image_holder_,
|
|
|
+ SIGNAL(imageScaled()),
|
|
|
+ this,
|
|
|
+ SLOT(onImageScaled())
|
|
|
+ );
|
|
|
+ connect(
|
|
|
+ &options_form_,
|
|
|
+ SIGNAL(optionsSet()),
|
|
|
+ this,
|
|
|
+ SLOT(onOptionsSet())
|
|
|
+ );
|
|
|
+
|
|
|
+
|
|
|
+ image_holder_->setBoundingBoxList(&list_bounding_box_);
|
|
|
+ image_holder_->setPolygonList(&list_polygon_);
|
|
|
+ image_holder_->setLabelColorList(&list_label_colors_);
|
|
|
+ image_holder_->setMainLabelNum(&main_label_);
|
|
|
+}
|
|
|
+
|
|
|
+ImageLabeler::~ImageLabeler()
|
|
|
+{
|
|
|
+ delete action_quit_;
|
|
|
+ delete action_open_labeled_image_;
|
|
|
+ delete action_open_images_;
|
|
|
+ delete action_load_legend_;
|
|
|
+ delete action_save_legend_;
|
|
|
+ delete action_save_segmented_;
|
|
|
+ delete action_save_labels_;
|
|
|
+ delete action_undo_;
|
|
|
+ delete action_redo_;
|
|
|
+ delete action_bound_box_tool_;
|
|
|
+ delete action_polygon_tool_;
|
|
|
+ delete action_tagging_tool_;
|
|
|
+ delete action_add_description_;
|
|
|
+ delete action_options_;
|
|
|
+ delete action_about_;
|
|
|
+ delete action_help_content_;
|
|
|
+
|
|
|
+ delete menu_file_;
|
|
|
+ delete menu_edit_;
|
|
|
+ delete menu_help_;
|
|
|
+
|
|
|
+ delete menu_bar_;
|
|
|
+
|
|
|
+ delete action_delete_area_;
|
|
|
+ delete action_edit_area_;
|
|
|
+
|
|
|
+ delete popup_area_list_;
|
|
|
+
|
|
|
+ delete action_toggle_priority_;
|
|
|
+ delete action_set_color_;
|
|
|
+ delete action_delete_label_;
|
|
|
+
|
|
|
+ delete popup_label_list_;
|
|
|
+
|
|
|
+ delete image_;
|
|
|
+ delete image_holder_;
|
|
|
+
|
|
|
+ delete button_add_label_;
|
|
|
+ delete button_remove_label_;
|
|
|
+ delete button_bound_box_tool_;
|
|
|
+ delete button_polygon_tool_;
|
|
|
+ delete button_tagging_tool_;
|
|
|
+ delete button_clear_selection_tool_;
|
|
|
+ delete button_generate_colors_;
|
|
|
+ delete button_delete_all_labels_;
|
|
|
+ delete button_next_image_;
|
|
|
+ delete button_prev_image_;
|
|
|
+
|
|
|
+ delete button_confirm_selection_;
|
|
|
+
|
|
|
+ delete label_list_areas_;
|
|
|
+ delete label_toolbox_;
|
|
|
+ delete list_areas_;
|
|
|
+ delete list_label_;
|
|
|
+
|
|
|
+ delete layout_toolbox_;
|
|
|
+ delete layout_right_;
|
|
|
+ delete layout_center_buttons_;
|
|
|
+ delete layout_frame_image_;
|
|
|
+ delete layout_center_;
|
|
|
+ delete layout_labelbox_buttons_;
|
|
|
+ delete layout_labelbox_;
|
|
|
+ delete layout_left_;
|
|
|
+ delete layout_main_;
|
|
|
+
|
|
|
+ delete frame_labelbox_;
|
|
|
+ delete frame_toolbox_;
|
|
|
+ delete frame_image_;
|
|
|
+ delete frame_center_;
|
|
|
+
|
|
|
+ delete central_widget_;
|
|
|
+
|
|
|
+ delete list_images_;
|
|
|
+ //delete current_image_;
|
|
|
+
|
|
|
+ if (pure_data_) {
|
|
|
+ delete[] *pure_data_;
|
|
|
+ delete pure_data_;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::addLabel()
|
|
|
+{
|
|
|
+ QListWidgetItem *newItem = new QListWidgetItem;
|
|
|
+
|
|
|
+ QString label;
|
|
|
+ int itemNum = list_label_->count();
|
|
|
+ label.append(QString("%1: ").arg(itemNum));
|
|
|
+
|
|
|
+ if (itemNum) {
|
|
|
+ newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
|
|
|
+ label.append("New label");
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ newItem->setFlags(
|
|
|
+ Qt::ItemIsUserCheckable | Qt::ItemIsSelectable |
|
|
|
+ Qt::ItemIsEnabled
|
|
|
+ );
|
|
|
+ label.append("BACKGROUND");
|
|
|
+ }
|
|
|
+ newItem->setText(label);
|
|
|
+
|
|
|
+ QPixmap iconPix = QPixmap(20, 20);
|
|
|
+ iconPix.fill(Qt::white);
|
|
|
+ QIcon icon(iconPix);
|
|
|
+ list_label_colors_.append(0xffffffff);
|
|
|
+
|
|
|
+ newItem->setIcon(icon);
|
|
|
+
|
|
|
+ list_label_->addItem(newItem);
|
|
|
+ list_label_->setItemSelected(newItem, true);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::addLabel(
|
|
|
+ int aLabelID,
|
|
|
+ bool isMain,
|
|
|
+ QString aLabel
|
|
|
+)
|
|
|
+{
|
|
|
+ QListWidgetItem *newItem = new QListWidgetItem;
|
|
|
+
|
|
|
+ if (0 == aLabelID) {
|
|
|
+ aLabel = QString("BACKGROUND");
|
|
|
+ newItem->setFlags(
|
|
|
+ Qt::ItemIsUserCheckable | Qt::ItemIsSelectable |
|
|
|
+ Qt::ItemIsEnabled
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ QString label;
|
|
|
+ label.append(QString("%1: %2").
|
|
|
+ arg(aLabelID).
|
|
|
+ arg(aLabel)
|
|
|
+ );
|
|
|
+
|
|
|
+ /* TODO: check if there is another main label and make it common */
|
|
|
+ if (isMain) {
|
|
|
+ main_label_ = aLabelID;
|
|
|
+ }
|
|
|
+
|
|
|
+ QPixmap iconPix = QPixmap(20, 20);
|
|
|
+ QColor color;
|
|
|
+ if (0 != aLabelID)
|
|
|
+ color = Qt::white;
|
|
|
+ else
|
|
|
+ color = Qt::black;
|
|
|
+ iconPix.fill(color);
|
|
|
+ QIcon icon(iconPix);
|
|
|
+ list_label_colors_.append(color.rgb());
|
|
|
+
|
|
|
+ newItem->setIcon(icon);
|
|
|
+
|
|
|
+ newItem->setText(label);
|
|
|
+ newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
|
|
|
+ list_label_->addItem(newItem);
|
|
|
+ list_label_->setItemSelected(newItem, true);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::editLabel(QListWidgetItem *anItem)
|
|
|
+{
|
|
|
+ QString label = anItem->text();
|
|
|
+ int itemRow = list_label_->row(anItem);
|
|
|
+
|
|
|
+ QString prefix = QString("%1: ").arg(itemRow);
|
|
|
+ if (-1 != label.indexOf(prefix)) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ label.prepend(QString("%1: ").arg(itemRow));
|
|
|
+
|
|
|
+ if (main_label_ == itemRow) {
|
|
|
+ label.append(" #main");
|
|
|
+ }
|
|
|
+
|
|
|
+ list_label_->blockSignals(true);
|
|
|
+ anItem->setText(label);
|
|
|
+ list_label_->blockSignals(false);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::removeLabel()
|
|
|
+{
|
|
|
+ if (0 == list_label_->count()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QListWidgetItem *current = list_label_->currentItem();
|
|
|
+
|
|
|
+ /* because we need to keep BACKGROUND category */
|
|
|
+ if (0 == list_label_->row(current)) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ int row = list_label_->row(current);
|
|
|
+ list_label_->takeItem(row);
|
|
|
+ list_label_colors_.takeAt(row);
|
|
|
+ delete current;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::setLabelID(
|
|
|
+ QListWidgetItem *anItem
|
|
|
+)
|
|
|
+{
|
|
|
+ Q_UNUSED(anItem)
|
|
|
+
|
|
|
+ if (!list_label_->count()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ label_ID_ = list_label_->row(anItem);
|
|
|
+}
|
|
|
+void
|
|
|
+ImageLabeler::addBBoxArea(
|
|
|
+ int anID,
|
|
|
+ BoundingBox aBBox
|
|
|
+)
|
|
|
+{
|
|
|
+ QListWidgetItem *newItem = new QListWidgetItem;
|
|
|
+
|
|
|
+ QString label;
|
|
|
+ label.append(QString("%1: ").arg(list_areas_->count()));
|
|
|
+
|
|
|
+ label.append(QString("BBox #%1; ").arg(anID));
|
|
|
+ label.append(QString("LabelID: %1; ").arg(aBBox.label_ID_));
|
|
|
+ label.append(
|
|
|
+ QString("points:%1;%2;%3;%4; ").
|
|
|
+ arg(aBBox.rect.topLeft().x()).
|
|
|
+ arg(aBBox.rect.topLeft().y()).
|
|
|
+ arg(aBBox.rect.bottomRight().x()).
|
|
|
+ arg(aBBox.rect.bottomRight().y())
|
|
|
+ );
|
|
|
+
|
|
|
+ newItem->setText(label);
|
|
|
+ //newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
|
|
|
+ list_areas_->addItem(newItem);
|
|
|
+ list_areas_->setItemSelected(newItem, true);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::addPolyArea(
|
|
|
+ int aPolyID,
|
|
|
+ Polygon aPoly
|
|
|
+)
|
|
|
+{
|
|
|
+ QListWidgetItem *newItem = new QListWidgetItem;
|
|
|
+
|
|
|
+ QString label;
|
|
|
+ label.append(QString("%1: ").arg(list_areas_->count()));
|
|
|
+
|
|
|
+ label.append(QString("Poly #%1; ").arg(aPolyID));
|
|
|
+ label.append(QString("LabelID: %1; ").arg(aPoly.label_ID_));
|
|
|
+ label.append("points:");
|
|
|
+ for (int i = 0; i < aPoly.poly.count(); i++) {
|
|
|
+ label.append(
|
|
|
+ QString("%1;%2;").
|
|
|
+ arg(aPoly.poly.point(i).x()).
|
|
|
+ arg(aPoly.poly.point(i).y())
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ newItem->setText(label);
|
|
|
+ //newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
|
|
|
+ list_areas_->addItem(newItem);
|
|
|
+ list_areas_->setItemSelected(newItem, true);
|
|
|
+}
|
|
|
+
|
|
|
+/* TODO: finish area editing */
|
|
|
+void
|
|
|
+ImageLabeler::editArea()
|
|
|
+{
|
|
|
+ bool oldState = list_areas_->blockSignals(true);
|
|
|
+ if (!list_areas_->currentItem() || !list_areas_->count()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QListWidgetItem *current = list_areas_->currentItem();
|
|
|
+
|
|
|
+ old_area_string_ = current->text();
|
|
|
+ current->setFlags(current->flags() | Qt::ItemIsEditable);
|
|
|
+ list_areas_->editItem(current);
|
|
|
+ list_areas_->blockSignals(oldState);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::onAreaChange(QListWidgetItem *anItem)
|
|
|
+{
|
|
|
+ list_areas_->blockSignals(true);
|
|
|
+ QString areaString = anItem->text();
|
|
|
+ int oldID = -1;
|
|
|
+ if (-1 != areaString.indexOf("Poly")) {
|
|
|
+ Polygon poly = polyFromString(&areaString, &oldID);
|
|
|
+
|
|
|
+ if (-1 < poly.label_ID_ && !poly.poly.isEmpty() &&
|
|
|
+ -1 < oldID) {
|
|
|
+ list_polygon_.takeAt(oldID);
|
|
|
+ list_polygon_.insert(oldID, poly);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ anItem->setText(old_area_string_);
|
|
|
+ }
|
|
|
+ else if (-1 != areaString.indexOf("BBox")) {
|
|
|
+ BoundingBox bbox = BBoxFromString(&areaString, &oldID);
|
|
|
+
|
|
|
+ if (-1 < bbox.label_ID_ && -1 < oldID) {
|
|
|
+ list_bounding_box_.takeAt(oldID);
|
|
|
+ list_bounding_box_.insert(oldID, bbox);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ anItem->setText(old_area_string_);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ showWarning(tr("record format is corrupted, try again"));
|
|
|
+ anItem->setText(old_area_string_);
|
|
|
+ }
|
|
|
+
|
|
|
+ anItem->setFlags(anItem->flags() ^ Qt::ItemIsEditable);
|
|
|
+ list_areas_->blockSignals(false);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::deleteArea()
|
|
|
+{
|
|
|
+ if (!list_areas_->currentItem() || !list_areas_->count()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QString text = list_areas_->currentItem()->text();
|
|
|
+
|
|
|
+ bool ok = 0;
|
|
|
+ //int labelID = getNumFromString(&text, "LabelID:", ";", &ok);
|
|
|
+
|
|
|
+// if (!ok) {
|
|
|
+// return;
|
|
|
+// /* NOTREACHED */
|
|
|
+// }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 0 - bbox
|
|
|
+ * 1 - poly
|
|
|
+ */
|
|
|
+ QString shape;
|
|
|
+ if (-1 != text.indexOf("BBox"))
|
|
|
+ shape = QString("BBox");
|
|
|
+ else if (-1 != text.indexOf("Poly"))
|
|
|
+ shape = QString("Poly");
|
|
|
+ else {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ int areaNum = getNumFromString(&text, "#", ";", &ok);
|
|
|
+
|
|
|
+ if (!ok) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ int currentItemRow = list_areas_->row(list_areas_->currentItem());
|
|
|
+
|
|
|
+ /* changing all shapes(depends on current) which are next in the list */
|
|
|
+ for (int i = list_areas_->count() - 1; i > currentItemRow; i--) {
|
|
|
+ QListWidgetItem item = *(list_areas_->item(i));
|
|
|
+ QString newText = item.text();
|
|
|
+
|
|
|
+ if (-1 == newText.indexOf(shape))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ int num = getNumFromString(&newText, "#", ";", &ok);
|
|
|
+ num--;
|
|
|
+ QString numString = QString("%1").arg(num);
|
|
|
+
|
|
|
+ int numPos = newText.indexOf("#") + 1;
|
|
|
+ newText.replace(numPos, numString.size(), numString);
|
|
|
+
|
|
|
+ list_areas_->takeItem(i);
|
|
|
+ list_areas_->insertItem(i, newText);
|
|
|
+ }
|
|
|
+
|
|
|
+ list_areas_->takeItem(currentItemRow);
|
|
|
+ if (shape == "BBox")
|
|
|
+ list_bounding_box_.removeAt(areaNum);
|
|
|
+ else
|
|
|
+ list_polygon_.removeAt(areaNum);
|
|
|
+
|
|
|
+ image_holder_->update();
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::toggleLabelPriority()
|
|
|
+{
|
|
|
+ if (!list_label_->count()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QListWidgetItem *item = list_label_->currentItem();
|
|
|
+
|
|
|
+ /* because we need to keep BACKGROUND category */
|
|
|
+ if (0 == list_label_->row(item)) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ int itemRow = list_label_->row(item);
|
|
|
+ QString text = item->text();
|
|
|
+
|
|
|
+ /* cleaning previous " #main" mark */
|
|
|
+ if (-1 != main_label_) {
|
|
|
+ QListWidgetItem *lastMain = list_label_->item(main_label_);
|
|
|
+ QString lastMainText = lastMain->text();
|
|
|
+ int mainPos = lastMainText.indexOf(" #main");
|
|
|
+ lastMainText = lastMainText.mid(0, mainPos);
|
|
|
+ list_label_->blockSignals(true);
|
|
|
+ lastMain->setText(lastMainText);
|
|
|
+ list_label_->blockSignals(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (main_label_ == itemRow) {
|
|
|
+ int mainPos = text.indexOf(" #main");
|
|
|
+ text = text.mid(0, mainPos);
|
|
|
+ main_label_ = -1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ text.append(" #main");
|
|
|
+ main_label_ = list_label_->row(item);
|
|
|
+ }
|
|
|
+
|
|
|
+ list_label_->blockSignals(true);
|
|
|
+ item->setText(text);
|
|
|
+ list_label_->blockSignals(false);
|
|
|
+
|
|
|
+ image_holder_->update();
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::getImagesFromDir(const QDir &dir)
|
|
|
+{
|
|
|
+ /* avoiding freezing during recursive search for files */
|
|
|
+ QApplication::processEvents();
|
|
|
+
|
|
|
+ QStringList filenameFilter;
|
|
|
+ filenameFilter <<
|
|
|
+ "*.jpeg" <<
|
|
|
+ "*.jpg" <<
|
|
|
+ "*.gif" <<
|
|
|
+ "*.png" <<
|
|
|
+ "*.bmp" <<
|
|
|
+ "*.tiff"
|
|
|
+ ;
|
|
|
+
|
|
|
+ QStringList listImages =
|
|
|
+ dir.entryList(filenameFilter, QDir::Files);
|
|
|
+
|
|
|
+ foreach (QString file, listImages)
|
|
|
+ list_images_->append(dir.absoluteFilePath(file));
|
|
|
+
|
|
|
+ QStringList listDir = dir.entryList(QDir::Dirs);
|
|
|
+ foreach (QString subdir, listDir) {
|
|
|
+ if ("." == subdir || ".." == subdir)
|
|
|
+ continue;
|
|
|
+ getImagesFromDir(QDir(dir.absoluteFilePath(subdir)));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::nextImage()
|
|
|
+{
|
|
|
+ if (list_images_->isEmpty()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (askForUnsavedData()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (list_images_->end() == current_image_ + 1)
|
|
|
+ current_image_ = list_images_->begin();
|
|
|
+ else
|
|
|
+ current_image_++;
|
|
|
+ image_->load(*current_image_);
|
|
|
+ image_holder_->setPixmap(*image_);
|
|
|
+ list_bounding_box_.clear();
|
|
|
+ list_polygon_.clear();
|
|
|
+ list_areas_->clear();
|
|
|
+ image_holder_->clearAll();
|
|
|
+
|
|
|
+ setWindowTitle(tr("ImageLabeler"));
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::prevImage()
|
|
|
+{
|
|
|
+ if (list_images_->isEmpty()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (askForUnsavedData()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (list_images_->begin() == current_image_)
|
|
|
+ current_image_ = list_images_->end() - 1;
|
|
|
+ else
|
|
|
+ current_image_--;
|
|
|
+ image_->load(*current_image_);
|
|
|
+ image_holder_->setPixmap(*image_);
|
|
|
+ list_bounding_box_.clear();
|
|
|
+ list_polygon_.clear();
|
|
|
+ list_areas_->clear();
|
|
|
+ image_holder_->clearAll();
|
|
|
+
|
|
|
+ setWindowTitle(tr("ImageLabeler"));
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::saveAllInfo()
|
|
|
+{
|
|
|
+ if (list_images_->isEmpty()) {
|
|
|
+ showWarning("You have not opened any image yet");
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ------------------------------------------------------------------------
|
|
|
+ * XML part
|
|
|
+ */
|
|
|
+ QDomDocument doc(tr("ImageLabeler"));
|
|
|
+ QDomElement root = doc.createElement(tr("pixelwise_labeling"));
|
|
|
+ doc.appendChild(root);
|
|
|
+
|
|
|
+ QDomElement image = doc.createElement(tr("image"));
|
|
|
+ root.appendChild(image);
|
|
|
+
|
|
|
+ QDomText pathToImage = doc.createTextNode(*current_image_);
|
|
|
+ image.appendChild(pathToImage);
|
|
|
+
|
|
|
+ QDomElement description = doc.createElement(tr("description"));
|
|
|
+ root.appendChild(description);
|
|
|
+
|
|
|
+ QDomText descriptionText = doc.createTextNode(image_description_);
|
|
|
+ description.appendChild(descriptionText);
|
|
|
+
|
|
|
+ legendToXml(&doc, &root);
|
|
|
+// QDomElement legend = doc.createElement(tr("legend"));
|
|
|
+// root.appendChild(legend);
|
|
|
+//
|
|
|
+// /* storing all labels made by user */
|
|
|
+// int labelCount = list_label_->count();
|
|
|
+// for (int i = 0; i < labelCount; i++) {
|
|
|
+// QDomElement label = doc.createElement(tr("label"));
|
|
|
+// label.setAttribute("color", QString("%1").arg(list_label_colors_.at(i), 0, 16));
|
|
|
+// label.setAttribute("id", i);
|
|
|
+//
|
|
|
+// QString priority;
|
|
|
+// if (main_label_ == i)
|
|
|
+// priority.append("1");
|
|
|
+// else
|
|
|
+// priority.append("0");
|
|
|
+// label.setAttribute("isMain", priority);
|
|
|
+//
|
|
|
+// QString labelText = list_label_->item(i)->text();
|
|
|
+//
|
|
|
+// /* removing the number prefix of label */
|
|
|
+// if (-1 != labelText.indexOf(QString("%1: ").arg(i))) {
|
|
|
+// labelText = labelText.mid(3, labelText.size() - 3);
|
|
|
+// }
|
|
|
+//
|
|
|
+// QDomText labelName = doc.createTextNode(labelText);
|
|
|
+// label.appendChild(labelName);
|
|
|
+// legend.appendChild(label);
|
|
|
+// }
|
|
|
+//
|
|
|
+// /* in case we have no labels */
|
|
|
+// if (0 == labelCount) {
|
|
|
+// QDomElement label = doc.createElement(tr("label"));
|
|
|
+// label.setAttribute(tr("id"), -1);
|
|
|
+// legend.appendChild(label);
|
|
|
+// }
|
|
|
+
|
|
|
+ /* objects - selected areas */
|
|
|
+ objectsToXml(&doc, &root);
|
|
|
+// QDomElement objects = doc.createElement(tr("objects"));
|
|
|
+// root.appendChild(objects);
|
|
|
+//
|
|
|
+// /* rects first */
|
|
|
+// for (int i = 0; i < list_bounding_box_.size(); i++) {
|
|
|
+// QDomElement rectData = doc.createElement(tr("bbox"));
|
|
|
+//
|
|
|
+// rectData.setAttribute("id", list_bounding_box_.at(i).label_ID_);
|
|
|
+//
|
|
|
+// QRect rect = list_bounding_box_.at(i).rect.normalized();
|
|
|
+//
|
|
|
+// QString rectDataString =
|
|
|
+// QString("%1;%2;%3;%4;").
|
|
|
+// arg(rect.x()).
|
|
|
+// arg(rect.y()).
|
|
|
+// arg(rect.width()).
|
|
|
+// arg(rect.height());
|
|
|
+//
|
|
|
+// QDomText rectDataText = doc.createTextNode(rectDataString);
|
|
|
+// rectData.appendChild(rectDataText);
|
|
|
+// objects.appendChild(rectData);
|
|
|
+// }
|
|
|
+//
|
|
|
+// /* polys next */
|
|
|
+// for (int i = 0; i < list_polygon_.size(); i++) {
|
|
|
+// QDomElement polyData = doc.createElement(tr("poly"));
|
|
|
+//
|
|
|
+// polyData.setAttribute("id", list_polygon_.at(i).label_ID_);
|
|
|
+//
|
|
|
+// QPolygon poly = list_polygon_.at(i).poly;
|
|
|
+//
|
|
|
+// QString polyDataString;
|
|
|
+// for (int j = 0; j < poly.count(); j++)
|
|
|
+// polyDataString.append(
|
|
|
+// QString("%1;%2;").
|
|
|
+// arg(poly.point(j).x()).
|
|
|
+// arg(poly.point(j).y())
|
|
|
+// );
|
|
|
+//
|
|
|
+//
|
|
|
+// QDomText polyDataText = doc.createTextNode(polyDataString);
|
|
|
+// polyData.appendChild(polyDataText);
|
|
|
+// objects.appendChild(polyData);
|
|
|
+// }
|
|
|
+
|
|
|
+ setPureData();
|
|
|
+ QDomElement pureData = doc.createElement(tr("pure_data"));
|
|
|
+ QSize imageSize = image_->size();
|
|
|
+ QString pixelValues;
|
|
|
+
|
|
|
+ for (int i = 0; i < imageSize.height(); i++) {
|
|
|
+ for (int j = 0; j < imageSize.width(); j++) {
|
|
|
+ pixelValues.append(QString("%1").arg(pure_data_[i][j]));
|
|
|
+ //pixelValues.append(QString(""));
|
|
|
+ }
|
|
|
+ pixelValues.append("\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ QDomText pureDataText = doc.createTextNode(pixelValues);
|
|
|
+ pureData.appendChild(pureDataText);
|
|
|
+ root.appendChild(pureData);
|
|
|
+
|
|
|
+ QString xml = doc.toString();
|
|
|
+ /* ------------------------------------------------------------------------
|
|
|
+ * XML part ends
|
|
|
+ */
|
|
|
+
|
|
|
+ QFileDialog fileDialog(0, tr("Save all info"));
|
|
|
+ fileDialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
+ fileDialog.setDefaultSuffix("dat");
|
|
|
+ fileDialog.setFileMode(QFileDialog::AnyFile);
|
|
|
+
|
|
|
+ /* altering the name of a new file */
|
|
|
+ QString newFileName = alterFileName(*current_image_, "_labeled");
|
|
|
+
|
|
|
+ fileDialog.selectFile(newFileName);
|
|
|
+
|
|
|
+ QString filename;
|
|
|
+ if (fileDialog.exec()) {
|
|
|
+ filename = fileDialog.selectedFiles().last();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //showWarning(tr("Can not open file dialog"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filename.isEmpty()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QFile file(filename);
|
|
|
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
|
+ showWarning(tr("Can not open file for writing"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ file.write(xml.toLocal8Bit());
|
|
|
+ file.close();
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::saveSegmentedPicture()
|
|
|
+{
|
|
|
+ if (list_bounding_box_.isEmpty() && list_polygon_.isEmpty()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ setPureData();
|
|
|
+
|
|
|
+// QString suffix = *current_image_;
|
|
|
+// int dotPos = suffix.lastIndexOf(".");
|
|
|
+// suffix.mid(dotPos + 1, suffix.size() - dotPos - 1);
|
|
|
+
|
|
|
+ QFileDialog fileDialog(0, tr("Save segmented picture"));
|
|
|
+ fileDialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
+ fileDialog.setDefaultSuffix("png");
|
|
|
+ fileDialog.setFileMode(QFileDialog::AnyFile);
|
|
|
+
|
|
|
+ /* altering the name of a new file */
|
|
|
+ QString newFileName = alterFileName(*current_image_, "_segmented");
|
|
|
+
|
|
|
+ fileDialog.selectFile(newFileName);
|
|
|
+
|
|
|
+ QString filename;
|
|
|
+ if (fileDialog.exec()) {
|
|
|
+ filename = fileDialog.selectedFiles().last();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QSize imageSize = image_holder_->pixmap()->size();
|
|
|
+ QImage newImage(imageSize, QImage::Format_RGB32);
|
|
|
+ bool generateColorsFlag = auto_color_generation_;
|
|
|
+ bool flag = 0;
|
|
|
+
|
|
|
+
|
|
|
+ /* checking if all the colors are are different from white(default) */
|
|
|
+ if (!generateColorsFlag) {
|
|
|
+ for (int i = 1; i < list_label_->count(); i++) {
|
|
|
+ if (list_label_colors_.at(i) == 0xffffffff && !flag)
|
|
|
+ flag = 1;
|
|
|
+ else if (list_label_colors_.at(i) == 0xffffffff && flag) {
|
|
|
+ QMessageBox msgBox;
|
|
|
+ msgBox.setText(tr("There are few labels with default white color."));
|
|
|
+ msgBox.setInformativeText(tr("Do you want to generate all colors automatically? Otherwise you'll have to do it manually."));
|
|
|
+ msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
|
+ msgBox.setDefaultButton(QMessageBox::Yes);
|
|
|
+ msgBox.setIcon(QMessageBox::Question);
|
|
|
+ int ret = msgBox.exec();
|
|
|
+
|
|
|
+ if (QMessageBox::Yes == ret) {
|
|
|
+ generateColorsFlag = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* generating colors for labels */
|
|
|
+ if (list_label_colors_.count() < list_label_->count() ||
|
|
|
+ generateColorsFlag) {
|
|
|
+ generateColors();
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < imageSize.height(); i++)
|
|
|
+ for (int j = 0; j < imageSize.width(); j++) {
|
|
|
+ newImage.setPixel(j, i, list_label_colors_.at(pure_data_[i][j]));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!newImage.save(filename, "png", 100))
|
|
|
+ showWarning(tr("An error occurred while saving the segmented image"));
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::saveLegend()
|
|
|
+{
|
|
|
+ if (!list_label_->count()) {
|
|
|
+ showWarning("You have not added any label yet");
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ------------------------------------------------------------------------
|
|
|
+ * XML part
|
|
|
+ */
|
|
|
+ QDomDocument doc(tr("ImageLabeler"));
|
|
|
+ QDomElement root = doc.createElement(tr("root"));
|
|
|
+ doc.appendChild(root);
|
|
|
+
|
|
|
+ legendToXml(&doc, &root);
|
|
|
+
|
|
|
+// QDomElement legend = doc.createElement(tr("legend"));
|
|
|
+// root.appendChild(legend);
|
|
|
+//
|
|
|
+// /* storing all labels made by user */
|
|
|
+// int labelCount = list_label_->count();
|
|
|
+// for (int i = 0; i < labelCount; i++) {
|
|
|
+// QDomElement label = doc.createElement(tr("label"));
|
|
|
+// label.setAttribute("color", QString("%1").arg(list_label_colors_.at(i), 0, 16));
|
|
|
+// label.setAttribute("id", i);
|
|
|
+//
|
|
|
+// QString priority;
|
|
|
+// if (main_label_ == i)
|
|
|
+// priority.append("1");
|
|
|
+// else
|
|
|
+// priority.append("0");
|
|
|
+// label.setAttribute("isMain", priority);
|
|
|
+//
|
|
|
+// QString labelText = list_label_->item(i)->text();
|
|
|
+//
|
|
|
+// /* removing the number prefix of label */
|
|
|
+// if (-1 != labelText.indexOf(QString("%1: ").arg(i))) {
|
|
|
+// labelText = labelText.mid(3, labelText.size() - 3);
|
|
|
+// }
|
|
|
+//
|
|
|
+// QDomText labelName = doc.createTextNode(labelText);
|
|
|
+// label.appendChild(labelName);
|
|
|
+// legend.appendChild(label);
|
|
|
+// }
|
|
|
+//
|
|
|
+// /* in case we have no labels */
|
|
|
+// if (0 == labelCount) {
|
|
|
+// QDomElement label = doc.createElement(tr("label"));
|
|
|
+// label.setAttribute(tr("id"), -1);
|
|
|
+// legend.appendChild(label);
|
|
|
+// }
|
|
|
+
|
|
|
+ QString xml = doc.toString();
|
|
|
+ /* ------------------------------------------------------------------------
|
|
|
+ * XML part ends
|
|
|
+ */
|
|
|
+
|
|
|
+ QFileDialog fileDialog(0, tr("Save legend"));
|
|
|
+ fileDialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
+ fileDialog.setDefaultSuffix("dat");
|
|
|
+ fileDialog.setFileMode(QFileDialog::AnyFile);
|
|
|
+
|
|
|
+ /* altering the name of a new file */
|
|
|
+ QString newFileName = alterFileName(*current_image_, "_legend");
|
|
|
+
|
|
|
+ fileDialog.selectFile(newFileName);
|
|
|
+
|
|
|
+ QString filename;
|
|
|
+ if (fileDialog.exec()) {
|
|
|
+ filename = fileDialog.selectedFiles().last();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //showWarning(tr("Can not open file dialog"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filename.isEmpty()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QFile file(filename);
|
|
|
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
|
+ showWarning(tr("Can not open file for writing"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ file.write(xml.toLocal8Bit());
|
|
|
+ file.close();
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::loadInfo()
|
|
|
+{
|
|
|
+ if (askForUnsavedData()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QFileDialog fileDialog(0, tr("Load file with info"));
|
|
|
+ fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
|
|
|
+ fileDialog.setDefaultSuffix("dat");
|
|
|
+ fileDialog.setFileMode(QFileDialog::AnyFile);
|
|
|
+
|
|
|
+ QString filename;
|
|
|
+ if (fileDialog.exec()) {
|
|
|
+ filename = fileDialog.selectedFiles().last();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //showWarning(tr("Can not open file dialog"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QDomDocument doc("Image Labeler");
|
|
|
+ QFile file(filename);
|
|
|
+ if (!file.open(QIODevice::ReadOnly)) {
|
|
|
+ showWarning(tr("Can not open such file"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QString errMsg;
|
|
|
+ if (!doc.setContent(&file, &errMsg)) {
|
|
|
+ showWarning(errMsg);
|
|
|
+ file.close();
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ file.close();
|
|
|
+
|
|
|
+ clearAll();
|
|
|
+ list_label_->clear();
|
|
|
+ enableTools();
|
|
|
+
|
|
|
+ /* getting all info */
|
|
|
+ QDomElement elements = doc.documentElement();
|
|
|
+ QDomNode rootNode = elements.firstChild();
|
|
|
+ QString string;
|
|
|
+
|
|
|
+ while(!rootNode.isNull()) {
|
|
|
+ QDomElement element = rootNode.toElement();
|
|
|
+ if(!element.isNull()) {
|
|
|
+ /* path to the image */
|
|
|
+ if (element.tagName() == "image") {
|
|
|
+ string = element.text();
|
|
|
+ if (string.isNull()) {
|
|
|
+ showWarning(
|
|
|
+ tr(
|
|
|
+ "The file with data doesn't contain path to the image"
|
|
|
+ )
|
|
|
+ );
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+ list_images_->append(string);
|
|
|
+ current_image_ = list_images_->end();
|
|
|
+ current_image_--;
|
|
|
+ image_->load(*current_image_);
|
|
|
+ image_holder_->setPixmap(*image_);
|
|
|
+ }
|
|
|
+ /* image description */
|
|
|
+ else if (element.tagName() == "description" &&
|
|
|
+ !element.text().isNull()) {
|
|
|
+ image_description_ = element.text();
|
|
|
+ }
|
|
|
+ /* legend */
|
|
|
+ else if (element.tagName() == "legend") {
|
|
|
+ loadLegendFromNode(&element);
|
|
|
+ }
|
|
|
+ /* objects */
|
|
|
+ else if (element.tagName() == "objects") {
|
|
|
+ QDomNode subNode = element.firstChild();
|
|
|
+ QDomElement subElement;
|
|
|
+
|
|
|
+ while(!subNode.isNull()) {
|
|
|
+ subElement = subNode.toElement();
|
|
|
+
|
|
|
+ if (subElement.isNull() || subElement.text().isNull()) {
|
|
|
+ subNode = subNode.nextSibling();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ string = subElement.attribute("id");
|
|
|
+ bool ok = 1;
|
|
|
+ int id = string.toInt(&ok, 10);
|
|
|
+
|
|
|
+ if (!ok) {
|
|
|
+ qDebug() <<
|
|
|
+ "while getting poly: "
|
|
|
+ "poly id format is corrupted";
|
|
|
+ subNode = subNode.nextSibling();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ string = subElement.text();
|
|
|
+
|
|
|
+ if (subElement.tagName() == "bbox") {
|
|
|
+ setBBoxFromData(&string, &id);
|
|
|
+ }
|
|
|
+ if (subElement.tagName() == "poly") {
|
|
|
+ setPolyFromData(&string, &id);
|
|
|
+ }
|
|
|
+
|
|
|
+ subNode = subNode.nextSibling();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rootNode = rootNode.nextSibling();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::loadImages()
|
|
|
+{
|
|
|
+ if (askForUnsavedData()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QFileDialog fileDialog(0, tr("Load images"));
|
|
|
+ fileDialog.setFileMode(QFileDialog::Directory);
|
|
|
+ QString dirName("");
|
|
|
+
|
|
|
+ if (fileDialog.exec()) {
|
|
|
+ /* TODO: make it possible to select multiple folders */
|
|
|
+ dirName = fileDialog.selectedFiles().last();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //showWarning(tr("Could not open file dialog"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ clearAll();
|
|
|
+
|
|
|
+ getImagesFromDir(QDir(dirName));
|
|
|
+
|
|
|
+ if (list_images_->isEmpty()) {
|
|
|
+ showWarning(tr("The folder you selected contains no images"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ current_image_ = list_images_->begin();
|
|
|
+
|
|
|
+ image_->load(list_images_->first());
|
|
|
+ image_holder_->setPixmap(*image_);
|
|
|
+
|
|
|
+ enableTools();
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::loadLegendFromFile()
|
|
|
+{
|
|
|
+ QFileDialog fileDialog(0, tr("Load legend"));
|
|
|
+ fileDialog.setFileMode(QFileDialog::AnyFile);
|
|
|
+ QString filename;
|
|
|
+
|
|
|
+ if (fileDialog.exec()) {
|
|
|
+ filename = fileDialog.selectedFiles().last();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //showWarning(tr("Could not open file dialog"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QDomDocument doc("Image Labeler");
|
|
|
+ QFile file(filename);
|
|
|
+ if (!file.open(QIODevice::ReadOnly)) {
|
|
|
+ showWarning(tr("Can not open such file"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QString errMsg;
|
|
|
+ if (!doc.setContent(&file, &errMsg)) {
|
|
|
+ showWarning(errMsg);
|
|
|
+ file.close();
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ file.close();
|
|
|
+
|
|
|
+ list_label_->clear();
|
|
|
+
|
|
|
+ /* getting legend */
|
|
|
+ QDomElement elements = doc.documentElement();
|
|
|
+ QDomNode rootNode = elements.firstChild();
|
|
|
+ QString string;
|
|
|
+
|
|
|
+ while(!rootNode.isNull()) {
|
|
|
+ QDomElement element = rootNode.toElement();
|
|
|
+ if(!element.isNull()) {
|
|
|
+ if (element.tagName() == "legend") {
|
|
|
+ loadLegendFromNode(&element);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rootNode = rootNode.nextSibling();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::loadLegendFromNode(QDomElement *anElement)
|
|
|
+{
|
|
|
+ if (!anElement) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+ QDomNode subNode = anElement->firstChild();
|
|
|
+ QDomElement subElement;
|
|
|
+ QString string;
|
|
|
+ int id = -1;
|
|
|
+ bool isMain;
|
|
|
+ uint color = 0xff000000;
|
|
|
+
|
|
|
+ while(!subNode.isNull()) {
|
|
|
+ subElement = subNode.toElement();
|
|
|
+
|
|
|
+ if (!subElement.isNull() && !subElement.text().isNull()) {
|
|
|
+ string = subElement.attribute("id");
|
|
|
+ bool ok = 0;
|
|
|
+ id = string.toInt(&ok, 10);
|
|
|
+
|
|
|
+ if (!ok) {
|
|
|
+ qDebug() <<
|
|
|
+ "while getting legend: "
|
|
|
+ "label id format is corrupted";
|
|
|
+ subNode = subNode.nextSibling();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ string = subElement.attribute("isMain");
|
|
|
+ isMain = string.toInt(&ok, 2);
|
|
|
+
|
|
|
+ if (!ok) {
|
|
|
+ qDebug() <<
|
|
|
+ "while getting legend: "
|
|
|
+ "label isMain flag format is corrupted";
|
|
|
+ subNode = subNode.nextSibling();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ string = subElement.attribute("color");
|
|
|
+ color = string.toUInt(&ok, 16);
|
|
|
+
|
|
|
+ if (!ok) {
|
|
|
+ qDebug() <<
|
|
|
+ "while getting legend: "
|
|
|
+ "label color format is corrupted";
|
|
|
+ subNode = subNode.nextSibling();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ string = subElement.text();
|
|
|
+
|
|
|
+ addLabel(id, isMain, string);
|
|
|
+ setLabelColor(id, color);
|
|
|
+ }
|
|
|
+
|
|
|
+ subNode = subNode.nextSibling();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::legendToXml(QDomDocument *aDoc, QDomElement *aRoot)
|
|
|
+{
|
|
|
+ QDomElement legend = aDoc->createElement(tr("legend"));
|
|
|
+ aRoot->appendChild(legend);
|
|
|
+
|
|
|
+ /* storing all labels made by user */
|
|
|
+ int labelCount = list_label_->count();
|
|
|
+ for (int i = 0; i < labelCount; i++) {
|
|
|
+ QDomElement label = aDoc->createElement(tr("label"));
|
|
|
+ label.setAttribute("color", QString("%1").arg(list_label_colors_.at(i), 0, 16));
|
|
|
+ label.setAttribute("id", i);
|
|
|
+
|
|
|
+ QString priority;
|
|
|
+ if (main_label_ == i)
|
|
|
+ priority.append("1");
|
|
|
+ else
|
|
|
+ priority.append("0");
|
|
|
+ label.setAttribute("isMain", priority);
|
|
|
+
|
|
|
+ QString labelText = list_label_->item(i)->text();
|
|
|
+
|
|
|
+ /* removing the number prefix of label */
|
|
|
+ if (-1 != labelText.indexOf(QString("%1: ").arg(i))) {
|
|
|
+ labelText = labelText.mid(3, labelText.size() - 3);
|
|
|
+ }
|
|
|
+
|
|
|
+ QDomText labelName = aDoc->createTextNode(labelText);
|
|
|
+ label.appendChild(labelName);
|
|
|
+ legend.appendChild(label);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* in case we have no labels */
|
|
|
+ if (0 == labelCount) {
|
|
|
+ QDomElement label = aDoc->createElement(tr("label"));
|
|
|
+ label.setAttribute(tr("id"), -1);
|
|
|
+ legend.appendChild(label);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::objectsToXml(QDomDocument *aDoc, QDomElement *aRoot)
|
|
|
+{
|
|
|
+ QDomElement objects = aDoc->createElement(tr("objects"));
|
|
|
+ aRoot->appendChild(objects);
|
|
|
+
|
|
|
+ /* rects first */
|
|
|
+ for (int i = 0; i < list_bounding_box_.size(); i++) {
|
|
|
+ QDomElement rectData = aDoc->createElement(tr("bbox"));
|
|
|
+
|
|
|
+ rectData.setAttribute("id", list_bounding_box_.at(i).label_ID_);
|
|
|
+
|
|
|
+ QRect rect = list_bounding_box_.at(i).rect.normalized();
|
|
|
+
|
|
|
+ QString rectDataString =
|
|
|
+ QString("%1;%2;%3;%4;").
|
|
|
+ arg(rect.x()).
|
|
|
+ arg(rect.y()).
|
|
|
+ arg(rect.width()).
|
|
|
+ arg(rect.height());
|
|
|
+
|
|
|
+ QDomText rectDataText = aDoc->createTextNode(rectDataString);
|
|
|
+ rectData.appendChild(rectDataText);
|
|
|
+ objects.appendChild(rectData);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* polys next */
|
|
|
+ for (int i = 0; i < list_polygon_.size(); i++) {
|
|
|
+ QDomElement polyData = aDoc->createElement(tr("poly"));
|
|
|
+
|
|
|
+ polyData.setAttribute("id", list_polygon_.at(i).label_ID_);
|
|
|
+
|
|
|
+ QPolygon poly = list_polygon_.at(i).poly;
|
|
|
+
|
|
|
+ QString polyDataString;
|
|
|
+ for (int j = 0; j < poly.count(); j++)
|
|
|
+ polyDataString.append(
|
|
|
+ QString("%1;%2;").
|
|
|
+ arg(poly.point(j).x()).
|
|
|
+ arg(poly.point(j).y())
|
|
|
+ );
|
|
|
+
|
|
|
+
|
|
|
+ QDomText polyDataText = aDoc->createTextNode(polyDataString);
|
|
|
+ polyData.appendChild(polyDataText);
|
|
|
+ objects.appendChild(polyData);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::generateColors()
|
|
|
+{
|
|
|
+ int labelCount = list_label_->count();
|
|
|
+
|
|
|
+ if (!labelCount) {
|
|
|
+ showWarning(tr("you have not added any labels yet"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ int coeff = (0xff / labelCount) * 3;
|
|
|
+ //QList< uint > colors;
|
|
|
+ list_label_colors_.clear();
|
|
|
+ list_label_colors_.append(0);
|
|
|
+ uchar red = 0xff;
|
|
|
+ uchar green = 0xff;
|
|
|
+ uchar blue = 0xff;
|
|
|
+ uchar iterationColor = coeff;
|
|
|
+ uint color = 0xffffffff;
|
|
|
+ int j = 1;
|
|
|
+ for (int i = 1; i < labelCount; i++) {
|
|
|
+ if (6 == j) {
|
|
|
+ iterationColor += coeff;
|
|
|
+ j = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (5 == j) {
|
|
|
+ red = 0xff - iterationColor;
|
|
|
+ green = 0xff - iterationColor;
|
|
|
+ blue = 0xff;
|
|
|
+ }
|
|
|
+ else if (4 == j) {
|
|
|
+ red = 0xff - iterationColor;
|
|
|
+ green = 0xff;
|
|
|
+ blue = 0xff - iterationColor;
|
|
|
+ }
|
|
|
+ else if (3 == j) {
|
|
|
+ red = 0xff - iterationColor;
|
|
|
+ green = 0xff;
|
|
|
+ blue = 0xff;
|
|
|
+ }
|
|
|
+ else if (2 == j) {
|
|
|
+ red = 0xff;
|
|
|
+ green = 0xff - iterationColor;
|
|
|
+ blue = 0xff;
|
|
|
+ }
|
|
|
+ else if (1 == j){
|
|
|
+ red = 0xff;
|
|
|
+ green = 0xff;
|
|
|
+ blue = 0xff - iterationColor;
|
|
|
+ }
|
|
|
+ j++;
|
|
|
+ color = red + (green * 0x100) + (blue * 0x10000) + 0xff000000;
|
|
|
+
|
|
|
+ int itemNo = list_label_colors_.count();
|
|
|
+
|
|
|
+ QPixmap iconPix = QPixmap(20, 20);
|
|
|
+ iconPix.fill(color);
|
|
|
+ QIcon icon(iconPix);
|
|
|
+
|
|
|
+ list_label_->item(itemNo)->setIcon(icon);
|
|
|
+ list_label_colors_.append(color);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::setBBoxFromData(
|
|
|
+ QString *aBBoxData,
|
|
|
+ int *ID
|
|
|
+)
|
|
|
+{
|
|
|
+ BoundingBox bbox = BBoxFromData(aBBoxData);
|
|
|
+ if (!bbox.rect.isValid() || !ID) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ bbox.label_ID_ = *ID;
|
|
|
+ list_bounding_box_.append(bbox);
|
|
|
+ addBBoxArea(list_bounding_box_.count() - 1, bbox);
|
|
|
+}
|
|
|
+
|
|
|
+BoundingBox
|
|
|
+ImageLabeler::BBoxFromData(
|
|
|
+ QString *aBBoxData
|
|
|
+)
|
|
|
+{
|
|
|
+ BoundingBox bbox;
|
|
|
+ QString buffer;
|
|
|
+ bbox.rect.setRect(-1, -1, -1, -1);
|
|
|
+ int startPos = 0;
|
|
|
+ bool ok = 1;
|
|
|
+
|
|
|
+ for (int i = 0; i < aBBoxData->size(); i++) {
|
|
|
+ if (';' != aBBoxData->at(i))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ buffer = aBBoxData->mid(startPos, i - startPos);
|
|
|
+
|
|
|
+ int bboxData = buffer.toInt(&ok, 10);
|
|
|
+ if (!ok) {
|
|
|
+ qDebug() <<
|
|
|
+ "while getting objects: "
|
|
|
+ "poly format is corrupted";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (-1 == bbox.rect.x()) {
|
|
|
+ bbox.rect.setX(bboxData);
|
|
|
+ bbox.rect.setWidth(-1);
|
|
|
+ }
|
|
|
+ else if (-1 == bbox.rect.y()) {
|
|
|
+ bbox.rect.setY(bboxData);
|
|
|
+ bbox.rect.setHeight(-1);
|
|
|
+ }
|
|
|
+ else if (-1 == bbox.rect.width()) {
|
|
|
+ bbox.rect.setWidth(bboxData);
|
|
|
+ }
|
|
|
+ else if (-1 == bbox.rect.height()) {
|
|
|
+ bbox.rect.setHeight(bboxData);
|
|
|
+ }
|
|
|
+
|
|
|
+ startPos = i + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!bbox.rect.isValid()) {
|
|
|
+ qDebug() <<
|
|
|
+ "BBoxFromData: "
|
|
|
+ "bbox format is corrupted";
|
|
|
+ bbox.rect.setRect(-1, -1, -1, -1);
|
|
|
+ }
|
|
|
+ else if (!ok) {
|
|
|
+ bbox.rect.setRect(-1, -1, -1, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ return bbox;
|
|
|
+}
|
|
|
+
|
|
|
+BoundingBox
|
|
|
+ImageLabeler::BBoxFromString(
|
|
|
+ QString *aString,
|
|
|
+ int *oldID
|
|
|
+)
|
|
|
+{
|
|
|
+ BoundingBox bbox;
|
|
|
+ bbox.label_ID_ = -1;
|
|
|
+ *oldID = -1;
|
|
|
+
|
|
|
+ if (!aString) {
|
|
|
+ return bbox;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (-1 == aString->indexOf("BBox")) {
|
|
|
+ return bbox;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* getting bbox id in the list(it cannot be changed) */
|
|
|
+ bool ok = 0;
|
|
|
+ int bboxID = getNumFromString(aString, "BBox #", ";", &ok);
|
|
|
+ if (!ok || -1 <= bboxID) {
|
|
|
+ qDebug() <<
|
|
|
+ "BBoxFromString: poly ID is corrupted";
|
|
|
+ return bbox;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* getting new label id */
|
|
|
+ int labelID = getNumFromString(aString, "LabelID: ", ";", &ok);
|
|
|
+ if (!ok || -1 <= labelID) {
|
|
|
+ showWarning(
|
|
|
+ tr("new LabelID is wrong, area can not be changed")
|
|
|
+ );
|
|
|
+ return bbox;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* getting new points */
|
|
|
+ int pointsPos = aString->indexOf("points:") + 7;
|
|
|
+ int pointsLen = aString->size() - pointsPos;
|
|
|
+ if (pointsLen <= 0) {
|
|
|
+ showWarning(
|
|
|
+ tr("new points data is wrong, area can not be changed")
|
|
|
+ );
|
|
|
+ return bbox;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+ QString pointsData = aString->mid(pointsPos, pointsLen);
|
|
|
+ bbox = BBoxFromData(&pointsData);
|
|
|
+ bbox.label_ID_ = labelID;
|
|
|
+
|
|
|
+
|
|
|
+ *oldID = bboxID;
|
|
|
+ return bbox;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::setPolyFromData(
|
|
|
+ QString *aPolyData,
|
|
|
+ int *ID
|
|
|
+)
|
|
|
+{
|
|
|
+ Polygon poly = polyFromData(aPolyData);
|
|
|
+
|
|
|
+ if (poly.poly.isEmpty() || !ID) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ poly.label_ID_ = *ID;
|
|
|
+ list_polygon_.append(poly);
|
|
|
+ addPolyArea(list_polygon_.count() - 1, poly);
|
|
|
+}
|
|
|
+
|
|
|
+Polygon
|
|
|
+ImageLabeler::polyFromData(
|
|
|
+ QString *aPolyData
|
|
|
+)
|
|
|
+{
|
|
|
+ Polygon poly;
|
|
|
+ poly.label_ID_ = -1;
|
|
|
+ QPoint point;
|
|
|
+ QString buffer;
|
|
|
+ int startPos = 0;
|
|
|
+ bool ok = 1;
|
|
|
+ bool evenFlag = 0;
|
|
|
+
|
|
|
+ for (int i = 0; i < aPolyData->size(); i++) {
|
|
|
+ if (';' != aPolyData->at(i))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ buffer = aPolyData->mid(startPos, i - startPos);
|
|
|
+
|
|
|
+ int polyCoor = buffer.toInt(&ok, 10);
|
|
|
+ if (!ok) {
|
|
|
+ qDebug() <<
|
|
|
+ "while getting objects: "
|
|
|
+ "poly format is corrupted";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!evenFlag) {
|
|
|
+ point.setX(polyCoor);
|
|
|
+ evenFlag = 1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ point.setY(polyCoor);
|
|
|
+ poly.poly.append(point);
|
|
|
+ evenFlag = 0;
|
|
|
+ }
|
|
|
+ startPos = i + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (evenFlag) {
|
|
|
+ qDebug() <<
|
|
|
+ "polyFromData: "
|
|
|
+ "poly format is corrupted";
|
|
|
+ poly.poly.clear();
|
|
|
+ }
|
|
|
+ else if (!ok) {
|
|
|
+ poly.poly.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ return poly;
|
|
|
+}
|
|
|
+
|
|
|
+Polygon
|
|
|
+ImageLabeler::polyFromString(
|
|
|
+ QString *aString,
|
|
|
+ int *oldID
|
|
|
+)
|
|
|
+{
|
|
|
+ Polygon poly;
|
|
|
+ poly.label_ID_ = -1;
|
|
|
+ *oldID = -1;
|
|
|
+
|
|
|
+ if (!aString) {
|
|
|
+ return poly;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (-1 == aString->indexOf("Poly")) {
|
|
|
+ return poly;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* getting poly id in the list(it cannot be changed) */
|
|
|
+ bool ok = 0;
|
|
|
+ int polyID = getNumFromString(aString, "Poly #", ";", &ok);
|
|
|
+ if (!ok || -1 <= polyID) {
|
|
|
+ qDebug() <<
|
|
|
+ "polyFromString: poly ID is corrupted";
|
|
|
+ return poly;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* getting new label id */
|
|
|
+ int labelID = getNumFromString(aString, "LabelID: ", ";", &ok);
|
|
|
+ if (!ok || -1 <= labelID) {
|
|
|
+ showWarning(
|
|
|
+ tr("new LabelID is wrong, area can not be changed")
|
|
|
+ );
|
|
|
+ return poly;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* getting new points */
|
|
|
+ int pointsPos = aString->indexOf("points:") + 7;
|
|
|
+ int pointsLen = aString->size() - pointsPos;
|
|
|
+ if (pointsLen <= 0) {
|
|
|
+ showWarning(
|
|
|
+ tr("new points data is wrong, area can not be changed")
|
|
|
+ );
|
|
|
+ return poly;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+ QString pointsData = aString->mid(pointsPos, pointsLen);
|
|
|
+ poly = polyFromData(&pointsData);
|
|
|
+ poly.label_ID_ = labelID;
|
|
|
+
|
|
|
+
|
|
|
+ *oldID = polyID;
|
|
|
+ return poly;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::showWarning(
|
|
|
+ const QString text
|
|
|
+)
|
|
|
+{
|
|
|
+ if (text.isEmpty()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ QMessageBox msgBox;
|
|
|
+ msgBox.setText(text);
|
|
|
+ msgBox.setIcon(QMessageBox::Warning);
|
|
|
+ msgBox.exec();
|
|
|
+}
|
|
|
+
|
|
|
+bool
|
|
|
+ImageLabeler::askForUnsavedData()
|
|
|
+{
|
|
|
+ if (!list_bounding_box_.isEmpty() ||
|
|
|
+ !list_polygon_.isEmpty())
|
|
|
+ {
|
|
|
+ QMessageBox msgBox;
|
|
|
+ msgBox.setText(tr("There is some unsaved data"));
|
|
|
+ msgBox.setInformativeText(tr("Do you want to save your progress?"));
|
|
|
+ msgBox.setStandardButtons(
|
|
|
+ QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
|
|
+ msgBox.setDefaultButton(QMessageBox::Save);
|
|
|
+ msgBox.setIcon(QMessageBox::Question);
|
|
|
+ int ret = msgBox.exec();
|
|
|
+
|
|
|
+ if (QMessageBox::Save == ret)
|
|
|
+ saveAllInfo();
|
|
|
+ else if (QMessageBox::Cancel == ret)
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::setBoundingBoxTool(bool aButtonPressed)
|
|
|
+{
|
|
|
+ if (aButtonPressed)
|
|
|
+ image_holder_->setTool(ImageHolder::BoundingBoxTool);
|
|
|
+ else {
|
|
|
+ image_holder_->setTool(ImageHolder::NoTool);
|
|
|
+ image_holder_->clearLast();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::setPolygonTool(bool aButtonPressed)
|
|
|
+{
|
|
|
+ if (aButtonPressed) {
|
|
|
+ image_holder_->setTool(ImageHolder::PolygonTool);
|
|
|
+ image_holder_->setFocus();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ image_holder_->setTool(ImageHolder::NoTool);
|
|
|
+ image_holder_->clearLast();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::onSelectionStarted()
|
|
|
+{
|
|
|
+ button_confirm_selection_->setEnabled(true);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::onImageScaled()
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::confirmSelection()
|
|
|
+{
|
|
|
+ if (!list_label_->count()) {
|
|
|
+ showWarning(tr("You haven't added any label"));
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ image_holder_->confirmSelection();
|
|
|
+
|
|
|
+ if (label_ID_ < 0)
|
|
|
+ label_ID_ = 0;
|
|
|
+
|
|
|
+ ImageHolder::Tool tool = image_holder_->tool();
|
|
|
+ switch (tool) {
|
|
|
+ case ImageHolder::BoundingBoxTool:
|
|
|
+ list_bounding_box_.last().label_ID_ = label_ID_;
|
|
|
+ addBBoxArea(
|
|
|
+ list_bounding_box_.count() - 1,
|
|
|
+ list_bounding_box_.last()
|
|
|
+ );
|
|
|
+ break;
|
|
|
+ case ImageHolder::PolygonTool:
|
|
|
+ list_polygon_.last().label_ID_ = label_ID_;
|
|
|
+ addPolyArea(
|
|
|
+ list_polygon_.count() - 1,
|
|
|
+ list_polygon_.last()
|
|
|
+ );
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ button_confirm_selection_->setEnabled(false);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::clearAll()
|
|
|
+{
|
|
|
+ clearLabelList();
|
|
|
+ list_areas_->clear();
|
|
|
+ list_bounding_box_.clear();
|
|
|
+ list_polygon_.clear();
|
|
|
+ list_images_->clear();
|
|
|
+ main_label_ = -1;
|
|
|
+ image_holder_->clearAll();
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::clearAllTool()
|
|
|
+{
|
|
|
+ list_areas_->clear();
|
|
|
+ list_bounding_box_.clear();
|
|
|
+ list_polygon_.clear();
|
|
|
+ main_label_ = -1;
|
|
|
+ image_holder_->clearAll();
|
|
|
+}
|
|
|
+
|
|
|
+void ImageLabeler::clearLabelList()
|
|
|
+{
|
|
|
+ list_label_->clear();
|
|
|
+ addLabel(0, false, "BACKGROUND");
|
|
|
+ list_label_->item(0)->setFlags(
|
|
|
+ Qt::ItemIsUserCheckable | Qt::ItemIsSelectable |
|
|
|
+ Qt::ItemIsEnabled
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::enableTools()
|
|
|
+{
|
|
|
+ action_save_labels_->setEnabled(true);
|
|
|
+ action_save_segmented_->setEnabled(true);
|
|
|
+ action_save_legend_->setEnabled(true);
|
|
|
+ action_bound_box_tool_->setEnabled(true);
|
|
|
+ action_polygon_tool_->setEnabled(true);
|
|
|
+ action_add_description_->setEnabled(true);
|
|
|
+ button_bound_box_tool_->setEnabled(true);
|
|
|
+ button_polygon_tool_->setEnabled(true);
|
|
|
+ button_add_label_->setEnabled(true);
|
|
|
+ button_remove_label_->setEnabled(true);
|
|
|
+ button_prev_image_->setEnabled(true);
|
|
|
+ button_next_image_->setEnabled(true);
|
|
|
+ button_clear_selection_tool_->setEnabled(true);
|
|
|
+ button_generate_colors_->setEnabled(true);
|
|
|
+ button_delete_all_labels_->setEnabled(true);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::disableTools()
|
|
|
+{
|
|
|
+ action_save_labels_->setEnabled(false);
|
|
|
+ action_save_segmented_->setEnabled(false);
|
|
|
+ action_save_legend_->setEnabled(false);
|
|
|
+ action_bound_box_tool_->setEnabled(false);
|
|
|
+ action_polygon_tool_->setEnabled(false);
|
|
|
+ action_add_description_->setEnabled(false);
|
|
|
+ button_bound_box_tool_->setEnabled(false);
|
|
|
+ button_polygon_tool_->setEnabled(false);
|
|
|
+ button_add_label_->setEnabled(false);
|
|
|
+ button_remove_label_->setEnabled(false);
|
|
|
+ button_prev_image_->setEnabled(false);
|
|
|
+ button_next_image_->setEnabled(false);
|
|
|
+ button_clear_selection_tool_->setEnabled(false);
|
|
|
+ button_generate_colors_->setEnabled(false);
|
|
|
+ button_delete_all_labels_->setEnabled(false);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::areaListPopupMenu(const QPoint &aPos)
|
|
|
+{
|
|
|
+ QPoint globalPos = list_areas_->mapToGlobal(aPos);
|
|
|
+ QModelIndex index = list_areas_->indexAt(aPos);
|
|
|
+
|
|
|
+ if (-1 == index.row()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ list_areas_->item(index.row())->setSelected(true);
|
|
|
+
|
|
|
+ popup_area_list_->exec(globalPos);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::labelListPopupMenu(const QPoint &aPos)
|
|
|
+{
|
|
|
+ QPoint globalPos = list_label_->mapToGlobal(aPos);
|
|
|
+ QModelIndex index = list_label_->indexAt(aPos);
|
|
|
+
|
|
|
+ if (-1 == index.row() || !index.row()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ list_label_->item(index.row())->setSelected(true);
|
|
|
+
|
|
|
+ popup_label_list_->exec(globalPos);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::setDescription(QString aDescription)
|
|
|
+{
|
|
|
+ image_description_ = aDescription;
|
|
|
+ setWindowTitle(image_description_);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::setPureData()
|
|
|
+{
|
|
|
+ /* initializing array */
|
|
|
+ if (pure_data_) {
|
|
|
+ delete[] *pure_data_;
|
|
|
+ delete pure_data_;
|
|
|
+ }
|
|
|
+
|
|
|
+ QSize imageSize = image_->size();
|
|
|
+ pure_data_ = new int *[imageSize.height()];
|
|
|
+ if (!pure_data_) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+ for (int i = 0; i < imageSize.height(); i++) {
|
|
|
+ pure_data_[i] = new int[imageSize.width()];
|
|
|
+ if (!pure_data_[i]) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ int bboxCnt = list_bounding_box_.count();
|
|
|
+ int polyCnt = list_polygon_.count();
|
|
|
+ for (int i = 0; i < imageSize.height(); i++)
|
|
|
+ for (int j = 0; j < imageSize.width(); j++) {
|
|
|
+ pure_data_[i][j] = 0;
|
|
|
+ /* bboxes first */
|
|
|
+ for (int cnt = 0; cnt < bboxCnt; cnt++) {
|
|
|
+ BoundingBox bbox = list_bounding_box_.at(cnt);
|
|
|
+ if (bbox.rect.contains(j, i)) {
|
|
|
+ pure_data_[i][j] = bbox.label_ID_;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* polys next */
|
|
|
+ for (int cnt = 0; cnt < polyCnt; cnt++) {
|
|
|
+ Polygon poly = list_polygon_.at(cnt);
|
|
|
+ if (poly.poly.containsPoint(QPoint(j, i), Qt::OddEvenFill)) {
|
|
|
+ pure_data_[i][j] = poly.label_ID_;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::setLabelColor()
|
|
|
+{
|
|
|
+ if (list_label_colors_.count() < list_label_->count()) {
|
|
|
+ generateColors();
|
|
|
+ }
|
|
|
+
|
|
|
+ QListWidgetItem *current = list_label_->currentItem();
|
|
|
+
|
|
|
+ int labelID = list_label_->row(current);
|
|
|
+ QColor defaultColor;
|
|
|
+ defaultColor.setRgb(list_label_colors_.at(labelID));
|
|
|
+ QColor newColor = QColorDialog::getColor(
|
|
|
+ defaultColor,
|
|
|
+ list_label_
|
|
|
+ );
|
|
|
+
|
|
|
+ if (!newColor.isValid()) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+ list_label_colors_.takeAt(labelID);
|
|
|
+ list_label_colors_.insert(labelID, newColor.rgb());
|
|
|
+
|
|
|
+ QPixmap iconPix = QPixmap(20, 20);
|
|
|
+ iconPix.fill(newColor);
|
|
|
+ QIcon icon(iconPix);
|
|
|
+
|
|
|
+ current->setIcon(icon);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::setLabelColor(int anID, QColor aColor)
|
|
|
+{
|
|
|
+ if (anID < 0) {
|
|
|
+ return;
|
|
|
+ /* NOTREACHED */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (list_label_colors_.count() < list_label_->count()) {
|
|
|
+ generateColors();
|
|
|
+ }
|
|
|
+
|
|
|
+ QListWidgetItem *item = list_label_->item(anID);
|
|
|
+ list_label_colors_.takeAt(anID);
|
|
|
+ list_label_colors_.insert(anID, aColor.rgb());
|
|
|
+
|
|
|
+ QPixmap iconPix = QPixmap(20, 20);
|
|
|
+ iconPix.fill(aColor);
|
|
|
+ QIcon icon(iconPix);
|
|
|
+
|
|
|
+ item->setIcon(icon);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::onOptionsSet()
|
|
|
+{
|
|
|
+ auto_color_generation_ = options_form_.autoColorGeneration();
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::resizeEvent (QResizeEvent *anEvent)
|
|
|
+{
|
|
|
+ QWidget::resizeEvent(anEvent);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::mousePressEvent(QMouseEvent *anEvent)
|
|
|
+{
|
|
|
+ QWidget::mousePressEvent(anEvent);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+ImageLabeler::keyPressEvent(QKeyEvent *anEvent)
|
|
|
+{
|
|
|
+ if (Qt::Key_Left == anEvent->key() &&
|
|
|
+ Qt::NoModifier == anEvent->modifiers()) {
|
|
|
+ prevImage();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Qt::Key_Right == anEvent->key() &&
|
|
|
+ Qt::NoModifier == anEvent->modifiers()) {
|
|
|
+ nextImage();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Qt::Key_Enter == anEvent->key() &&
|
|
|
+ // Qt::NoModifier == anEvent->modifiers() &&
|
|
|
+ ImageHolder::NewSelection == image_holder_->state()) {
|
|
|
+ confirmSelection();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Qt::Key_Escape == anEvent->key()) {
|
|
|
+ image_holder_->clearLast();
|
|
|
+ image_holder_->clearFocusOnArea();
|
|
|
+ }
|
|
|
+
|
|
|
+ QWidget::keyPressEvent(anEvent);
|
|
|
+}
|
|
|
+
|
|
|
+/* TODO: finish scaling */
|
|
|
+void
|
|
|
+ImageLabeler::wheelEvent(QWheelEvent *anEvent)
|
|
|
+{
|
|
|
+ /* zoomin */
|
|
|
+ if (0 < anEvent->delta()) {
|
|
|
+ //image_holder_->scaleImage(ZoomIn, 1.1);
|
|
|
+ }
|
|
|
+ /* zoomout */
|
|
|
+ else if (anEvent->delta() < 0) {
|
|
|
+ //image_holder_->scaleImage(ZoomOut, 1.1);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ *
|
|
|
+ */
|