/* * ImageLabeler.cpp * * Created on: Oct 4, 2011 * Author: Gapchich Vladislav */ #include "ImageLabeler.h" #include "functions.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ImageLabeler::ImageLabeler(QWidget *aParent, QString aSettingsPath) : QMainWindow(aParent) { /* * Variables */ list_images_ = new QList< Image >; main_label_ = -1; pure_data_ = 0; //label_ID_ = -1; /* options */ auto_color_generation_ = 0; /* flags */ interrupt_search_ = 0; unsaved_data_ = 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_pascal_ = new QMenu(menu_bar_); menu_pascal_->setTitle(tr("&Pascal")); menu_view_ = new QMenu(menu_bar_); menu_view_->setTitle(tr("&View")); menu_edit_ = new QMenu(menu_bar_); menu_edit_->setTitle(tr("&Edit")); menu_help_ = new QMenu(menu_bar_); menu_help_->setTitle(tr("&Help")); /* menu file */ action_open_image_ = new QAction(this); action_open_image_->setText(tr("&Load image")); action_open_images_ = new QAction(this); action_open_images_->setText(tr("&Load images(recursively)")); action_open_labeled_image_ = new QAction(this); action_open_labeled_image_->setText(tr("&Load 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_quit_ = new QAction(this); action_quit_->setText(tr("&Quit")); /* menu pascal */ action_load_pascal_file_ = new QAction(this); action_load_pascal_file_->setText(tr("&Load pascal file")); action_load_pascal_poly_ = new QAction(this); action_load_pascal_poly_->setText(tr("&Load poly info")); /* menu view */ action_view_normal_ = new QAction(this); action_view_normal_->setText(tr("&Normal")); action_view_normal_->setEnabled(false); action_view_segmented_ = new QAction(this); action_view_segmented_->setText(tr("&Segmented")); action_view_segmented_->setEnabled(false); /* menu edit */ 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")); /* menu help */ 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); /* ------------------ */ menu_file_->addAction(action_open_image_); menu_file_->addAction(action_open_images_); menu_file_->addAction(action_open_labeled_image_); menu_file_->addAction(action_load_legend_); menu_file_->addAction(menu_pascal_->menuAction()); menu_file_->addSeparator(); menu_file_->addAction(action_save_segmented_); menu_file_->addAction(action_save_legend_); menu_file_->addAction(action_save_labels_); menu_file_->addSeparator(); menu_file_->addAction(action_quit_); menu_pascal_->addAction(action_load_pascal_file_); menu_pascal_->addAction(action_load_pascal_poly_); menu_view_->addAction(action_view_normal_); menu_view_->addAction(action_view_segmented_); menu_edit_->addAction(action_undo_); menu_edit_->addAction(action_redo_); menu_edit_->addSeparator(); menu_edit_->addAction(action_bound_box_tool_); menu_edit_->addAction(action_polygon_tool_); menu_edit_->addAction(action_tagging_tool_); menu_edit_->addSeparator(); menu_edit_->addAction(action_add_description_); menu_edit_->addAction(action_options_); menu_help_->addAction(action_help_content_); menu_help_->addAction(action_about_); menu_bar_->addAction(menu_file_->menuAction()); menu_bar_->addAction(menu_view_->menuAction()); menu_bar_->addAction(menu_edit_->menuAction()); menu_bar_->addAction(menu_help_->menuAction()); /* * 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_); popup_images_list_ = new QMenu; action_remove_image_ = new QAction(this); action_remove_image_->setText(tr("&remove image")); popup_images_list_->addAction(action_remove_image_); /* * 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 QScrollArea(frame_center_); //frame_image_->setStyleSheet("QWidget {background: #888888;}"); frame_image_->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); frame_image_->setLineWidth(0); frame_image_->setMidLineWidth(0); frame_image_->setWidgetResizable(false); frame_image_->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); frame_image_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 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::Minimum, QSizePolicy::Minimum); image_holder_->setScaledContents(true); image_holder_->setFrameStyle(QFrame::Box | QFrame::Plain); image_holder_->setLineWidth(0); frame_image_->setWidget(image_holder_); list_label_ = new QListWidget(central_widget_); list_label_->setContextMenuPolicy(Qt::CustomContextMenu); list_areas_ = new QListWidget(central_widget_); list_areas_->setContextMenuPolicy(Qt::CustomContextMenu); list_images_widget_ = new QListWidget(central_widget_); list_images_widget_->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_); label_list_images_ = new QLabel(tr("Loaded images:"), 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_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_); 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_->addSpacing(10); 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_toolbox_->addSpacing(10); layout_left_->addWidget(label_list_images_); layout_left_->addWidget(list_images_widget_); list_images_widget_->setFixedWidth(200); 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(200); 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_image_, SIGNAL(triggered()), this, SLOT(loadImage()) ); connect( action_open_labeled_image_, SIGNAL(triggered()), this, SLOT(loadInfo()) ); connect( action_load_legend_, SIGNAL(triggered()), this, SLOT(loadLegendFromFile()) ); connect( action_load_pascal_file_, SIGNAL(triggered()), this, SLOT(loadPascalFile()) ); connect( action_load_pascal_poly_, SIGNAL(triggered()), this, SLOT(loadPascalPolys()) ); 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( action_view_normal_, SIGNAL(triggered()), this, SLOT(viewNormal()) ); connect( action_view_segmented_, SIGNAL(triggered()), this, SLOT(viewSegmented()) ); connect( action_undo_, SIGNAL(triggered()), image_holder_, SLOT(undo()) ); connect( action_redo_, SIGNAL(triggered()), image_holder_, SLOT(redo()) ); connect( action_add_description_, SIGNAL(triggered()), &line_edit_form_, SLOT(setDescription()) ); connect( action_options_, SIGNAL(triggered()), &options_form_, SLOT(showOptions()) ); 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_tagging_tool_, SIGNAL(clicked()), &line_edit_form_, SLOT(setTags()) ); 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(onAreaItemChange(QListWidgetItem *)) ); connect( list_label_, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(labelListPopupMenu(const QPoint &)) ); connect( list_images_widget_, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(selectImage(QListWidgetItem *)) ); connect( list_images_widget_, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(imageListPopupMenu(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_remove_image_, SIGNAL(triggered()), this, SLOT(removeImage()) ); connect( image_holder_, SIGNAL(selectionStarted()), this, SLOT(onSelectionStarted()) ); connect( &line_edit_form_, SIGNAL(dataSet(QString)), this, SLOT(setDataFromForm(QString)) ); connect( image_holder_, SIGNAL(imageScaled()), this, SLOT(onImageScaled()) ); connect( image_holder_, SIGNAL(areaEdited()), this, SLOT(onAreaEdit()) ); connect( &options_form_, SIGNAL(optionsSet()), this, SLOT(onOptionsSet()) ); QString settingsPath = aSettingsPath; if (settingsPath.isEmpty()) settingsPath = QString("ImageLabeler.ini"); settings_ = new QSettings(settingsPath, QSettings::IniFormat, this); readSettings(settings_); image_holder_->setBoundingBoxList(&list_bounding_box_); image_holder_->setPolygonList(&list_polygon_); image_holder_->setLabelColorList(&list_label_colors_); image_holder_->setMainLabelNum(&main_label_); image_holder_->setImage(image_); options_form_.setPASCALpath(&PASCALpath_); } ImageLabeler::~ImageLabeler() { delete action_quit_; delete action_open_labeled_image_; delete action_open_image_; delete action_open_images_; delete action_load_legend_; delete action_load_pascal_file_; delete action_load_pascal_poly_; delete action_save_legend_; delete action_save_segmented_; delete action_save_labels_; delete action_view_normal_; delete action_view_segmented_; 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_pascal_; delete menu_file_; delete menu_view_; 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 action_remove_image_; delete popup_images_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 label_list_images_; delete list_areas_; delete list_label_; delete list_images_widget_; 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 current_image_; if (pure_data_) { delete[] *pure_data_; delete pure_data_; } delete list_images_; delete settings_; } bool ImageLabeler::readSettings(QSettings *aSettings) { aSettings->beginGroup("/global"); auto_color_generation_ = aSettings->value("/auto_label_color_generation", 0).toBool(); options_form_.setAutoColorGeneration(auto_color_generation_); PASCALpath_ = aSettings->value("/PASCAL_root_path", "").toString(); aSettings->endGroup(); qDebug() << PASCALpath_; return true; } bool ImageLabeler::writeSettings(QSettings *aSettings) { aSettings->beginGroup("/global"); aSettings->setValue("/auto_label_color_generation", auto_color_generation_); aSettings->setValue("/PASCAL_root_path", PASCALpath_); aSettings->endGroup(); return true; } void ImageLabeler::writeSettings() { writeSettings(settings_); } void ImageLabeler::addImage(Image *anImage) { QListWidgetItem *newItem = new QListWidgetItem; QString itemText = QString("%1: %2"). arg(list_images_widget_->count()). arg(getFilenameFromPath(&(anImage->image_))); if (anImage->labeled_) itemText.append(" #labeled"); if (anImage->pas_) itemText.append(" #pas"); newItem->setText(itemText); list_images_widget_->addItem(newItem); list_images_->append(*anImage); } 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); QColor color; if (0 != itemNum) color = Qt::white; else color = Qt::black; iconPix.fill(color); QIcon icon(iconPix); list_label_colors_.append(color.rgb()); newItem->setIcon(icon); list_label_->addItem(newItem); list_label_->setItemSelected(newItem, true); label_ID_ = list_label_->count() - 1; unsaved_data_ = 1; } 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); unsaved_data_ = 1; } 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); unsaved_data_ = 1; } void ImageLabeler::removeLabel() { if (0 == list_label_->count()) { return; /* NOTREACHED */ } //QListWidgetItem *current = list_label_->currentItem(); /* we need to keep BACKGROUND category */ if (label_ID_ < 1) { return; /* NOTREACHED */ } if (list_label_->count() <= label_ID_ || list_label_colors_.count() <= label_ID_) { return; /* NOTREACHED */ } list_label_->takeItem(label_ID_); list_label_colors_.takeAt(label_ID_); unsaved_data_ = 1; } 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, int itemID ) { QListWidgetItem *newItem = new QListWidgetItem; if (-1 == itemID) itemID = list_areas_->count(); QString label; label.append(QString("%1: ").arg(itemID)); label.append(QString("BBox #%1; ").arg(anID)); label.append(QString("LabelID: %1; ").arg(aBBox.label_ID_)); label.append( QString("data:%1;%2;%3;%4; "). arg(aBBox.rect.topLeft().x()). arg(aBBox.rect.topLeft().y()). arg(aBBox.rect.width()). arg(aBBox.rect.height()) ); newItem->setText(label); //newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); list_areas_->insertItem(itemID, newItem); list_areas_->setItemSelected(newItem, true); } void ImageLabeler::addPolyArea( int aPolyID, Polygon aPoly, int itemID ) { QListWidgetItem *newItem = new QListWidgetItem; if (-1 == itemID) itemID = list_areas_->count(); QString label; label.append(QString("%1: ").arg(itemID)); 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_->insertItem(itemID, newItem); list_areas_->setItemSelected(newItem, true); } 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::onAreaItemChange(QListWidgetItem *anItem) { list_areas_->blockSignals(true); QString areaString = anItem->text(); int oldID = -1; if (-1 != areaString.indexOf("Poly")) { Polygon *poly = new 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 = new 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); image_holder_->update(); unsaved_data_ = 1; } void ImageLabeler::onAreaEdit() { if (!list_areas_->count() || -1 == image_holder_->focusedSelection()) { //showWarning(tr("You haven't added any label")); return; /* NOTREACHED */ } int figureID = image_holder_->focusedSelection(); Figure figure = image_holder_->focusedSelectionType(); for (int i = 0; i < list_areas_->count(); i++) { QListWidgetItem *item = list_areas_->item(i); QString text = item->text(); if (RectFigure == figure && -1 != text.indexOf("BBox")) { bool ok = 0; int num = getNumFromString(&text, "BBox #", ";", &ok); if (ok && num == figureID) { list_areas_->takeItem(i); addBBoxArea(num, *list_bounding_box_.at(num), i); } } else if (PolyFigure == figure && -1 != text.indexOf("Poly")) { bool ok = 0; int num = getNumFromString(&text, "Poly #", ";", &ok); if (ok && num == figureID) { list_areas_->takeItem(i); addPolyArea(num, *list_polygon_.at(num), i); } } } unsaved_data_ = 1; } 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(); unsaved_data_ = 1; } 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(); unsaved_data_ = 1; } void ImageLabeler::getImagesFromDir(const QDir &dir) { /* avoiding freezing during recursive search for files */ QApplication::processEvents(); if (interrupt_search_) { clearAll(); return; } QStringList filenameFilter; filenameFilter << "*.jpeg" << "*.jpg" << "*.gif" << "*.png" << "*.bmp" << "*.tiff" << "*.dat" ; QStringList listImages = dir.entryList(filenameFilter, QDir::Files); QStringList ignoredFiles; foreach (QString file, listImages) { if (ignoredFiles.contains(file) || file.contains("_segmented", Qt::CaseInsensitive) || file.contains(".dat", Qt::CaseInsensitive)) { continue; } Image newImage; newImage.image_ = dir.absoluteFilePath(file); /* TODO: think about loading pascal files */ newImage.pas_ = 0; QString labeled = alterFileName(file, "_labeled"); labeled = removePath(labeled); labeled.append(".dat"); if (listImages.contains(labeled, Qt::CaseInsensitive)) newImage.labeled_ = 1; else { newImage.labeled_ = 0; } addImage(&newImage); } 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_widget_->count() - 1 == image_ID_) { //current_image_ = list_images_->at(0).image_; image_ID_ = 0; } else { image_ID_ ++; //current_image_ = list_images_->at(image_ID_).image_; } if (!selectImage(image_ID_)) { showWarning(tr("Next image is not available")); return; /* NOTREACHED */ } list_images_widget_->setCurrentRow(image_ID_); if (current_image_.isEmpty()) { return; /* NOTREACHED */ } QString winTitle; winTitle.append("ImageLabeler - "); winTitle.append(current_image_); setWindowTitle(winTitle); image_->load(current_image_); image_holder_->resize(image_->size()); image_holder_->setPixmap(*image_); list_bounding_box_.clear(); list_polygon_.clear(); list_areas_->clear(); image_holder_->clearAll(); segmented_image_.clear(); clearLabelColorList(); //setWindowTitle(tr("ImageLabeler")); } void ImageLabeler::prevImage() { if (!list_images_widget_->count()) { return; /* NOTREACHED */ } if (askForUnsavedData()) { return; /* NOTREACHED */ } if (!image_ID_) { image_ID_ = list_images_widget_->count() - 1; //current_image_ = list_images_->at(image_ID_).image_; } else { image_ID_--; //current_image_ = list_images_->at(image_ID_).image_; } list_images_widget_->setCurrentRow(image_ID_); if (!selectImage(image_ID_)) { showWarning(tr("Next image is not available")); return; /* NOTREACHED */ } QString winTitle; winTitle.append("ImageLabeler - "); winTitle.append(current_image_); setWindowTitle(winTitle); image_->load(current_image_); image_holder_->resize(image_->size()); image_holder_->setPixmap(*image_); list_bounding_box_.clear(); list_polygon_.clear(); list_areas_->clear(); image_holder_->clearAll(); segmented_image_.clear(); clearLabelColorList(); //setWindowTitle(tr("ImageLabeler")); } void ImageLabeler::saveAllInfo() { if (!list_images_widget_->count()) { 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); if (!segmented_image_.isEmpty()) { QDomElement segmentedImage = doc.createElement(tr("segmented")); root.appendChild(segmentedImage); QDomText pathToSegmented = doc.createTextNode(segmented_image_); segmentedImage.appendChild(pathToSegmented); } QDomElement description = doc.createElement(tr("description")); root.appendChild(description); QDomText descriptionText = doc.createTextNode(image_description_); description.appendChild(descriptionText); QDomElement tags = doc.createElement(tr("tags")); root.appendChild(tags); QDomText tagsText = doc.createTextNode(tags_); tags.appendChild(tagsText); legendToXml(&doc, &root); objectsToXml(&doc, &root); 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); QString dir = getDirFromPath(¤t_image_); /* altering the name of a new file */ QString newFileName = alterFileName(current_image_, "_labeled"); newFileName = removePath(newFileName); fileDialog.selectFile(newFileName); fileDialog.setDirectory(dir); 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(); unsaved_data_ = 0; } 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); QString dir = getDirFromPath(¤t_image_); /* altering the name of a new file */ QString newFileName = alterFileName(current_image_, "_segmented"); newFileName = removePath(newFileName); fileDialog.selectFile(newFileName); fileDialog.setDirectory(dir); 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")); return; /* NOTREACHED */ } segmented_image_ = filename; action_view_segmented_->setEnabled(true); } 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); QString xml = doc.toString(); /* ------------------------------------------------------------------------ * XML part ends */ QFileDialog fileDialog(0, tr("Save legend")); fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setDefaultSuffix("dat"); fileDialog.setFileMode(QFileDialog::AnyFile); QString dir = getDirFromPath(¤t_image_); /* altering the name of a new file */ QString newFileName = alterFileName(current_image_, "_legend"); newFileName = removePath(newFileName); fileDialog.selectFile(newFileName); fileDialog.setDirectory(dir); 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 */ } clearAllTool(); clearLabelList(); if (loadInfo(filename)) { enableTools(); Image newImage; newImage.image_ = current_image_; newImage.labeled_ = 1; newImage.pas_ = 0; addImage(&newImage); image_ID_ = list_images_widget_->count() - 1; list_images_widget_->setCurrentRow(image_ID_); } unsaved_data_ = 0; } bool ImageLabeler::loadInfo(QString filename) { QDomDocument doc("Image Labeler"); QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { showWarning(tr("Can not open such file")); return false; /* NOTREACHED */ } QString errMsg; if (!doc.setContent(&file, &errMsg)) { showWarning(errMsg); file.close(); return false; /* NOTREACHED */ } file.close(); //clearAll(); //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.isEmpty()) { showWarning( tr( "The file with data doesn't contain path to the image" ) ); return false; /* NOTREACHED */ } if (!image_->load(string)) { return false; /* NOTREACHED */ } // Image newImage; // newImage.image_ = string; // newImage.labeled_ = 1; // addImage(&newImage); current_image_ = string; // image_ID_ = list_images_widget_->count() - 1; // list_images_widget_->setCurrentRow(image_ID_); QString winTitle; winTitle.append("ImageLabeler - "); winTitle.append(current_image_); setWindowTitle(winTitle); image_holder_->resize(image_->size()); image_holder_->setPixmap(*image_); } /* path to the segmented image */ if (element.tagName() == "segmented") { string = element.text(); if (string.isEmpty()) { continue; } segmented_image_ = string; action_view_segmented_->setEnabled(true); } /* image description */ else if (element.tagName() == "description" && !element.text().isEmpty()) { 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().isEmpty()) { subNode = subNode.nextSibling(); continue; } string = subElement.attribute("id"); bool ok = 1; int id = string.toInt(&ok, 10); if (!ok) { qDebug() << "loadInfo: " "poly id format is corrupted"; subNode = subNode.nextSibling(); continue; } string = subElement.text(); if (subElement.tagName() == "bbox") { addBBoxFromData(&string, &id); } if (subElement.tagName() == "poly") { addPolyFromData(&string, &id); } subNode = subNode.nextSibling(); } } } rootNode = rootNode.nextSibling(); } unsaved_data_ = 0; return true; } void ImageLabeler::loadPascalFile() { if (askForUnsavedData()) { return; /* NOTREACHED */ } if (PASCALpath_.isEmpty()) { showWarning(tr("before opening first PASCAL file please choose \"root\" directory" " where a folder with segmentations," " a folder with polygons," " a folder with image descriptions and" " a folder with the pure images are.")); QFileDialog fileDialog(0, tr("root directory for the PASCAL files")); fileDialog.setFileMode(QFileDialog::Directory); if (fileDialog.exec()) PASCALpath_ = fileDialog.selectedFiles().last(); else { return; /* NOTREACHED */ } } QFileDialog fileDialog(0, tr("Load pascal file")); fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setDefaultSuffix("xml"); fileDialog.setFileMode(QFileDialog::AnyFile); QStringList filters; filters << "PASCAL xml data (*.xml)" << "Any files (*)"; fileDialog.setNameFilters(filters); QString filename; if (fileDialog.exec()) { filename = fileDialog.selectedFiles().last(); } else { //showWarning(tr("Can not open file dialog")); return; /* NOTREACHED */ } clearAllTool(); clearLabelList(); if (loadPascalFile(filename, PASCALpath_)) { enableTools(); Image newImage; newImage.image_ = current_image_; newImage.labeled_ = 1; newImage.pas_ = 1; addImage(&newImage); image_ID_ = list_images_widget_->count() - 1; list_images_widget_->setCurrentRow(image_ID_); } unsaved_data_ = 0; } bool ImageLabeler::loadPascalFile(QString aFilename, QString aPath) { QDomDocument doc; QFile file(aFilename); if (!file.open(QIODevice::ReadOnly)) { showWarning(tr("Can not open such file")); return false; /* NOTREACHED */ } QString errMsg; if (!doc.setContent(&file, &errMsg)) { showWarning(errMsg); file.close(); return false; /* NOTREACHED */ } file.close(); //clearAll(); //enableTools(); /* getting all info */ QDomElement elements = doc.documentElement(); QDomNode rootNode = elements.firstChild(); QString string; QString path; if (aPath.isEmpty()) path = getPathFromFilename(aFilename); else path = aPath + "/"; QString filename; QStringList labels; labels << "BACKGROUND"; int labelID; while(!rootNode.isNull()) { QDomElement element = rootNode.toElement(); if(!element.isNull()) { /* folder */ if (element.tagName() == "folder") { string = element.text(); if (!string.isEmpty()) { path.append(string); } } /* filename */ else if (element.tagName() == "filename") { string = element.text(); if (!string.isEmpty()) { filename = string; } } /* object */ else if (element.tagName() == "object") { QDomNode subNode = element.firstChild(); QDomElement subElement; while(!subNode.isNull()) { subElement = subNode.toElement(); if (subElement.isNull() || subElement.text().isEmpty()) { subNode = subNode.nextSibling(); continue; } /* label */ if (subElement.tagName() == "name") { string = subElement.text(); if (!string.isEmpty() && !labels.contains(string, Qt::CaseInsensitive)) { addLabel(list_label_->count(), 0, string); labelID = labels.count(); labels << string; } else if (labels.contains(string, Qt::CaseInsensitive)) { for (int i = 0; i < labels.count(); i++) { if (labels.at(i) == string) labelID = i; } } } if (subElement.tagName() == "bndbox") { /* 2 points */ QPoint topLeft; QPoint bottomRight; QDomNode bboxNode = subElement.firstChild(); QDomElement bboxElement; while(!bboxNode.isNull()) { bboxElement = bboxNode.toElement(); string.clear(); bool ok = 1; if (bboxElement.tagName() == "xmin") { string = bboxElement.text(); if (string.isEmpty()) ok = 0; double xmin = string.toDouble(&ok); if (ok) topLeft.setX(qRound(xmin)); } else if (bboxElement.tagName() == "ymin") { string = bboxElement.text(); if (string.isEmpty()) ok = 0; double ymin = string.toDouble(&ok); if (ok) topLeft.setY(qRound(ymin)); } else if (bboxElement.tagName() == "xmax") { string = bboxElement.text(); if (string.isEmpty()) ok = 0; double xmax = string.toDouble(&ok); if (ok) bottomRight.setX(qRound(xmax)); } else if (bboxElement.tagName() == "ymax") { string = bboxElement.text(); if (string.isEmpty()) ok = 0; double ymax = string.toDouble(&ok); if (ok) bottomRight.setY(qRound(ymax)); } if (string.isEmpty() || !ok) break; bboxNode = bboxNode.nextSibling(); if (bboxNode.isNull()) { BoundingBox *bbox = new BoundingBox; bbox->rect.setTopLeft(topLeft); bbox->rect.setBottomRight(bottomRight); bbox->label_ID_ = labelID; addBBox(bbox); } } } subNode = subNode.nextSibling(); } } } rootNode = rootNode.nextSibling(); } if (!image_->load(path + "/" + filename)) { return false; /* NOTREACHED */ } current_image_ = path + filename; QString winTitle; winTitle.append("ImageLabeler - "); winTitle.append(current_image_); setWindowTitle(winTitle); image_holder_->resize(image_->size()); image_holder_->setPixmap(*image_); unsaved_data_ = 0; return true; } void ImageLabeler::loadPascalPolys() { if (current_image_.isEmpty()) { return; /* NOTREACHED */ } QFileDialog fileDialog(0, tr("Load pascal polygons")); fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setDefaultSuffix("polygon"); fileDialog.setFileMode(QFileDialog::AnyFile); QStringList filters; filters << "PASCAL polygons (*.polygon)" << "Any files (*)"; fileDialog.setNameFilters(filters); QString filename; if (fileDialog.exec()) { filename = fileDialog.selectedFiles().last(); } else { //showWarning(tr("Can not open file dialog")); return; /* NOTREACHED */ } //clearAllTool(); //clearLabelList(); if (!loadPascalPolys(filename)) { showWarning(tr("File format is corrupted.")); } unsaved_data_ = 0; image_holder_->update(); } bool ImageLabeler::loadPascalPolys(QString aFilename) { QFile file(aFilename); if (!file.open(QIODevice::ReadOnly)) { showWarning(tr("Can not open such file")); return false; /* NOTREACHED */ } QByteArray data = file.readAll(); file.close(); QString label; int lastSpace = 0; int pointCount = 0; Polygon *poly = 0; QPoint point; bool evenFlag = 0; //for (int i = 0; i < data.length(); i++) { int i = 0; while (i < data.length()) { if (data.at(i) == ' ' && label.isEmpty() && !pointCount) { label = QString(data.mid(lastSpace, i - lastSpace)); lastSpace = i + 1; } else if (data.at(i) == ' ' && !label.isEmpty() && !pointCount) { QString num = QString(data.mid(lastSpace, i - lastSpace)); bool ok = 1; pointCount = num.toInt(&ok, 10); if (!ok) { return false; /* NOTREACHED */ } poly = new Polygon; poly->label_ID_ = -1; lastSpace = i + 1; } else if (data.at(i) == ' ' && !label.isEmpty() && pointCount && !evenFlag) { evenFlag = 1; QString num = QString(data.mid(lastSpace, i - lastSpace)); bool ok = 1; int coor = qRound(num.toDouble(&ok)); if (!ok) { return false; /* NOTREACHED */ } point.setX(coor); lastSpace = i + 1; } else if (data.at(i) == ' ' && !label.isEmpty() && pointCount && evenFlag) { evenFlag = 0; pointCount--; QString num = QString(data.mid(lastSpace, i - lastSpace)); bool ok = 1; int coor = qRound(num.toDouble(&ok)); if (!ok) { return false; /* NOTREACHED */ } point.setY(coor); lastSpace = i + 1; poly->poly << point; } else if (data.at(i) == '\n') { if (pointCount || !poly) { return false; /* NOTREACHED */ } lastSpace = i + 1; for (int j = 0; j < list_label_->count(); j++) { if (list_label_->item(j)->text().contains(label, Qt::CaseInsensitive)) { poly->label_ID_ = j; } } if (-1 == poly->label_ID_) { int labelID = list_label_->count(); addLabel(labelID, 0, label); poly->label_ID_ = labelID; } addPoly(poly); label.clear(); } i++; } //clearAll(); //enableTools(); return true; } void ImageLabeler::loadImage() { if (askForUnsavedData()) { return; /* NOTREACHED */ } QFileDialog fileDialog(0, tr("Load image")); fileDialog.setFileMode(QFileDialog::ExistingFile); QStringList filters; filters << "Image files (*.jpeg *.jpg *.gif *.png *.bmp *.tiff)" << "Any files (*)"; fileDialog.setNameFilters(filters); QString filename; if (fileDialog.exec()) { filename = fileDialog.selectedFiles().last(); } else { //showWarning(tr("Could not open file dialog")); return; /* NOTREACHED */ } if (filename.isEmpty()) { return; /* NOTREACHED */ } QString dirPath = getPathFromFilename(filename); QDir dir(dirPath); QStringList filter; filter << "*.dat"; QStringList fileList = dir.entryList(filter, QDir::Files); QString labeled = alterFileName(filename, "_labeled"); labeled = removePath(labeled); labeled.append(".dat"); if (fileList.contains(labeled, Qt::CaseInsensitive)) { labeled = dir.absoluteFilePath(labeled); loadInfo(labeled); Image *newImage = new Image; newImage->image_ = filename; newImage->labeled_ = 1; newImage->pas_ = 0; addImage(newImage); enableTools(); return; /* NOTREACHED */ } clearAllTool(); QString winTitle; winTitle.append("ImageLabeler - "); winTitle.append(current_image_); setWindowTitle(winTitle); if (!image_->load(filename)) { return; /* NOTREACHED */ } image_holder_->resize(image_->size()); image_holder_->setPixmap(*image_); current_image_ = filename; image_ID_ = list_images_widget_->count() - 1; list_images_widget_->setCurrentRow(image_ID_); Image *newImage = new Image; newImage->image_ = filename; newImage->labeled_ = 0; newImage->pas_ = 0; addImage(newImage); if (!list_images_widget_->count()) { return; /* NOTREACHED */ } enableTools(); } 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 */ } clearAllTool(); QWidget *searchInProgress = new QWidget(0); searchInProgress->setWindowTitle(tr("Loading images")); QLabel *info = new QLabel(searchInProgress); info->setText( tr("Program is looking for all image files in your directory recursively.")); QPushButton *cancel = new QPushButton(tr("Cancel"), searchInProgress); connect(cancel, SIGNAL(clicked()), this, SLOT(interruptSearch())); QVBoxLayout *layout = new QVBoxLayout(searchInProgress); searchInProgress->setLayout(layout); layout->addWidget(info); layout->addWidget(cancel); searchInProgress->adjustSize(); searchInProgress->move(QApplication::desktop()->screen()->rect().center() - rect().center()); searchInProgress->show(); getImagesFromDir(QDir(dirName)); cancel->disconnect(); searchInProgress->hide(); delete info; delete cancel; delete layout; delete searchInProgress; if (interrupt_search_) { interrupt_search_ = 0; return; /* NOTREACHED */ } if (!list_images_widget_->count()) { showWarning(tr("The folder you selected contains no images")); return; /* NOTREACHED */ } bool ret = 0; if (list_images_->at(0).labeled_) { QString labeled = alterFileName(list_images_->at(0).image_, "_labeled"); labeled.append(".dat"); ret = loadInfo(labeled); } else ret = image_->load(list_images_->at(0).image_); if (!ret) { return; /* NOTREACHED */ } current_image_ = list_images_->at(0).image_; image_ID_ = 0; list_images_widget_->setCurrentRow(image_ID_); QString winTitle; winTitle.append("ImageLabeler - "); winTitle.append(current_image_); setWindowTitle(winTitle); image_holder_->resize(image_->size()); 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().isEmpty()) { string = subElement.attribute("id"); bool ok = 0; id = string.toInt(&ok, 10); if (!ok) { qDebug() << "loadLegendFromNode: " "label id format is corrupted"; subNode = subNode.nextSibling(); continue; } string = subElement.attribute("isMain"); isMain = string.toInt(&ok, 2); if (!ok) { qDebug() << "loadLegendFromNode: " "label isMain flag format is corrupted"; subNode = subNode.nextSibling(); continue; } string = subElement.attribute("color"); color = string.toUInt(&ok, 16); if (!ok) { qDebug() << "loadLegendFromNode: " "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); } image_holder_->update(); } void ImageLabeler::addBBoxFromData( QString *aBBoxData, int *ID ) { BoundingBox *bbox = new 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() << "BBoxFromData: " "bbox 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 || bboxID <= -1) { qDebug() << "BBoxFromString: bboxID is corrupted"; return bbox; /* NOTREACHED */ } /* getting new label id */ int labelID = getNumFromString(aString, "LabelID: ", ";", &ok); if (!ok || labelID <= -1) { showWarning( tr("new LabelID is wrong, area can not be changed") ); return bbox; /* NOTREACHED */ } /* getting new points */ int pointsPos = aString->indexOf("data:") + 5; int pointsLen = aString->size() - pointsPos; if (pointsLen <= 0) { showWarning( tr("new 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::addPoly(Polygon *poly) { if (poly->poly.isEmpty() || poly->label_ID_ < 0) { return; /* NOTREACHED */ } list_polygon_.append(poly); addPolyArea(list_polygon_.count() - 1, *poly); } void ImageLabeler::addBBox(BoundingBox *bbox) { if (bbox->rect.isEmpty() || bbox->label_ID_ < 0) { return; /* NOTREACHED */ } list_bounding_box_.append(bbox); addBBoxArea(list_bounding_box_.count() - 1, *bbox); } void ImageLabeler::addPolyFromData( QString *aPolyData, int *labelID ) { Polygon *poly = new Polygon; *poly = polyFromData(aPolyData); if (poly->poly.isEmpty() || !labelID) { return; /* NOTREACHED */ } poly->label_ID_ = *labelID; 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() << "polyFromData: " "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 || polyID <= -1) { qDebug() << "polyFromString: poly ID is corrupted"; return poly; /* NOTREACHED */ } /* getting new label id */ int labelID = getNumFromString(aString, "LabelID: ", ";", &ok); if (!ok || labelID <= -1) { 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()) && unsaved_data_) { 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); unsaved_data_ = 1; } void ImageLabeler::clearAll() { clearLabelList(); list_areas_->clear(); list_bounding_box_.clear(); list_polygon_.clear(); list_images_->clear(); list_images_widget_->clear(); main_label_ = -1; image_holder_->clearAll(); segmented_image_.clear(); action_view_normal_->setEnabled(false); action_view_segmented_->setEnabled(false); } 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::clearLabelColorList() { list_label_colors_.clear(); list_label_colors_.append(0x0); } 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); action_undo_->setEnabled(true); action_redo_->setEnabled(true); button_bound_box_tool_->setEnabled(true); button_polygon_tool_->setEnabled(true); button_tagging_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); button_tagging_tool_->setEnabled(false); action_add_description_->setEnabled(false); action_undo_->setEnabled(false); action_redo_->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::setDataFromForm(QString aData) { if (ImageDescriptionPurpose == line_edit_form_.purpose()) { image_description_ = aData; setWindowTitle(image_description_); } else if (TaggingPurpose == line_edit_form_.purpose()) { tags_ = aData; } } 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); image_holder_->update(); } 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); image_holder_->update(); } void ImageLabeler::onOptionsSet() { auto_color_generation_ = options_form_.autoColorGeneration(); } void ImageLabeler::viewNormal() { if (current_image_.isEmpty()) { return; /* NOTREACHED */ } image_->load(current_image_); image_holder_->setPixmap(*image_); action_view_segmented_->setEnabled(true); action_view_normal_->setEnabled(false); } void ImageLabeler::viewSegmented() { if (segmented_image_.isEmpty()) { return; /* NOTREACHED */ } image_->load(segmented_image_); image_holder_->setPixmap(*image_); action_view_segmented_->setEnabled(false); action_view_normal_->setEnabled(true); } void ImageLabeler::interruptSearch() { interrupt_search_ = 1; } void ImageLabeler::selectImage(QListWidgetItem *anItem) { if (!anItem || list_images_widget_->row(anItem) < 0 || list_images_->isEmpty()) { return; /* NOTREACHED */ } clearAllTool(); clearLabelList(); clearLabelColorList(); image_ID_ = list_images_widget_->row(anItem); selectImage(image_ID_); // if (list_images_->at(image_ID_).labeled_ && // !list_images_->at(image_ID_).pas_) // { // list_label_->clear(); // QString labeled = // alterFileName(list_images_->at(image_ID_).image_, "_labeled"); // labeled.append(".dat"); // loadInfo(labeled); // } // else if (list_images_->at(image_ID_).labeled_ && // list_images_->at(image_ID_).pas_) // { // /* TODO: do the pascal file selecting */ // showWarning("this function doesn't work at the moment, sorry."); // } // else { // current_image_ = list_images_->at(image_ID_).image_; // image_->load(current_image_); // image_holder_->setPixmap(*image_); // image_holder_->resize(image_->size()); // } } bool ImageLabeler::selectImage(int anImageID) { if (anImageID < 0 || list_images_->isEmpty() || list_images_->count() <= anImageID) { return false; /* NOTREACHED */ } if (list_images_->at(anImageID).labeled_ && !list_images_->at(anImageID).pas_) { list_label_->clear(); QString labeled = alterFileName(list_images_->at(anImageID).image_, "_labeled"); labeled.append(".dat"); loadInfo(labeled); } else if (list_images_->at(anImageID).labeled_ && list_images_->at(anImageID).pas_) { /* TODO: do the pascal file selecting */ showWarning("this function doesn't work at the moment, sorry."); } else { current_image_ = list_images_->at(anImageID).image_; image_->load(current_image_); image_holder_->setPixmap(*image_); image_holder_->resize(image_->size()); } return true; } void ImageLabeler::imageListPopupMenu(const QPoint &aPos) { QPoint globalPos = list_images_widget_->mapToGlobal(aPos); QModelIndex index = list_images_widget_->indexAt(aPos); if (-1 == index.row()) { return; /* NOTREACHED */ } list_images_widget_->item(index.row())->setSelected(true); popup_images_list_->exec(globalPos); } void ImageLabeler::removeImage() { int num = list_images_widget_->currentRow(); list_images_widget_->takeItem(num); list_images_->takeAt(num); for (int i = num ; i < list_images_widget_->count(); i++) { QString newStr = getFilenameFromPath(&(list_images_->at(i).image_)); newStr.prepend(QString("%1: ").arg(i)); list_images_widget_->item(i)->setText(newStr); } } void ImageLabeler::resizeEvent (QResizeEvent *anEvent) { QWidget::resizeEvent(anEvent); } void ImageLabeler::mousePressEvent(QMouseEvent *anEvent) { QWidget::mousePressEvent(anEvent); } void ImageLabeler::keyPressEvent(QKeyEvent *anEvent) { keyboard_modifier_ = anEvent->modifiers(); if (Qt::Key_Left == anEvent->key() && Qt::ControlModifier == keyboard_modifier_) { prevImage(); } if (Qt::Key_Right == anEvent->key() && Qt::ControlModifier == keyboard_modifier_) { nextImage(); } if ((Qt::Key_Enter == anEvent->key() || Qt::Key_Return == anEvent->key()) && // Qt::NoModifier == anEvent->modifiers() && ImageHolder::NewSelection == image_holder_->state()) { confirmSelection(); } if ((Qt::Key_Enter == anEvent->key() || Qt::Key_Return == anEvent->key()) && // Qt::NoModifier == anEvent->modifiers() && -1 != image_holder_->focusedSelection()) { image_holder_->clearFocusOnArea(); image_holder_->clearEdition(); image_holder_->update(); } if (Qt::Key_Escape == anEvent->key()) { image_holder_->clearLast(); image_holder_->clearFocusOnArea(); image_holder_->clearEdition(); image_holder_->update(); } if (Qt::Key_Z == anEvent->key() && Qt::ControlModifier == anEvent->modifiers()) { image_holder_->undo(); } if (Qt::Key_Y == anEvent->key() && Qt::ControlModifier == anEvent->modifiers()) { image_holder_->redo(); } QWidget::keyPressEvent(anEvent); } void ImageLabeler::keyReleaseEvent(QKeyEvent *anEvent) { keyboard_modifier_ = anEvent->modifiers(); } void ImageLabeler::wheelEvent(QWheelEvent *anEvent) { /* zoomin */ if (0 < anEvent->delta() && Qt::ControlModifier == keyboard_modifier_) { image_holder_->scaleImage(ZoomIn, 1.1); } /* zoomout */ else if (anEvent->delta() < 0 && Qt::ControlModifier == keyboard_modifier_) { image_holder_->scaleImage(ZoomOut, 1.1); } } void ImageLabeler::closeEvent(QCloseEvent *anEvent) { Q_UNUSED(anEvent) writeSettings(); } /* * */