Yolo_Label/mainwindow.cpp
Trenton Schulz 189006399a Add a newline on every line.
Text files should have a newline as their last character. This isn't
strictly required (many tools will work), but it makes parsing of
these files easier, plus it keeps the txt files similar with other
image datasets.
2020-08-05 10:44:24 +02:00

456 lines
13 KiB
C++

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QColorDialog>
#include <QKeyEvent>
#include <QDebug>
#include <QShortcut>
#include <iomanip>
using std::cout;
using std::endl;
using std::ofstream;
using std::ifstream;
using std::string;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_S), this), SIGNAL(activated()), this, SLOT(save_label_data()));
connect(new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), this), SIGNAL(activated()), this, SLOT(clear_label_data()));
connect(new QShortcut(QKeySequence(Qt::Key_S), this), SIGNAL(activated()), this, SLOT(next_label()));
connect(new QShortcut(QKeySequence(Qt::Key_W), this), SIGNAL(activated()), this, SLOT(prev_label()));
connect(new QShortcut(QKeySequence(Qt::Key_A), this), SIGNAL(activated()), this, SLOT(prev_img()));
connect(new QShortcut(QKeySequence(Qt::Key_D), this), SIGNAL(activated()), this, SLOT(next_img()));
connect(new QShortcut(QKeySequence(Qt::Key_Space), this), SIGNAL(activated()), this, SLOT(next_img()));
init_table_widget();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_open_files_clicked()
{
bool bRetImgDir = false;
bool bRetObjFile = false;
open_img_dir(bRetImgDir);
if (!bRetImgDir) return ;
open_obj_file(bRetObjFile);
if (!bRetObjFile) return ;
init();
}
void MainWindow::on_pushButton_change_dir_clicked()
{
bool bRetImgDir = false;
bool bRetObjFile = false;
open_img_dir(bRetImgDir);
if (!bRetImgDir) return ;
init();
}
void MainWindow::init()
{
ui->label_image->init();
init_button_event();
init_horizontal_slider();
set_label(0);
goto_img(0);
}
void MainWindow::set_label_progress(const int fileIndex)
{
QString strCurFileIndex = QString::number(fileIndex);
QString strEndFileIndex = QString::number(m_imgList.size() - 1);
ui->label_progress->setText(strCurFileIndex + " / " + strEndFileIndex);
}
void MainWindow::set_focused_file(const int fileIndex)
{
ui->label_file->setText("File: " + m_imgList.at(fileIndex));
}
void MainWindow::goto_img(const int fileIndex)
{
bool bIndexIsOutOfRange = (fileIndex < 0 || fileIndex > m_imgList.size() - 1);
if (bIndexIsOutOfRange) return;
m_imgIndex = fileIndex;
bool bImgOpened;
ui->label_image->openImage(m_imgList.at(m_imgIndex), bImgOpened);
ui->label_image->loadLabelData(get_labeling_data(m_imgList.at(m_imgIndex)));
ui->label_image->showImage();
set_label_progress(m_imgIndex);
set_focused_file(m_imgIndex);
//it blocks crash with slider change
ui->horizontalSlider_images->blockSignals(true);
ui->horizontalSlider_images->setValue(m_imgIndex);
ui->horizontalSlider_images->blockSignals(false);
}
void MainWindow::next_img(bool bSavePrev)
{
if(bSavePrev && ui->label_image->isOpened()) save_label_data();
goto_img(m_imgIndex + 1);
}
void MainWindow::prev_img(bool bSavePrev)
{
if(bSavePrev) save_label_data();
goto_img(m_imgIndex - 1);
}
void MainWindow::save_label_data()const
{
if(m_imgList.size() == 0) return;
QString qstrOutputLabelData = get_labeling_data(m_imgList.at(m_imgIndex));
ofstream fileOutputLabelData(qstrOutputLabelData.toStdString());
if(fileOutputLabelData.is_open())
{
for(int i = 0; i < ui->label_image->m_objBoundingBoxes.size(); i++)
{
ObjectLabelingBox objBox = ui->label_image->m_objBoundingBoxes[i];
if(ui->checkBox_cropping->isChecked())
{
QImage cropped = ui->label_image->crop(ui->label_image->cvtRelativeToAbsoluteRectInImage(objBox.box));
if(!cropped.isNull())
{
string strImgFile = m_imgList.at(m_imgIndex).toStdString();
strImgFile = strImgFile.substr( strImgFile.find_last_of('/') + 1,
strImgFile.find_last_of('.') - strImgFile.find_last_of('/') - 1);
cropped.save(QString().fromStdString(strImgFile) + "_cropped_" + QString::number(i) + ".png");
}
}
double midX = objBox.box.x() + objBox.box.width() / 2.;
double midY = objBox.box.y() + objBox.box.height() / 2.;
double width = objBox.box.width();
double height = objBox.box.height();
fileOutputLabelData << objBox.label;
fileOutputLabelData << " ";
fileOutputLabelData << std::fixed << std::setprecision(6) << midX;
fileOutputLabelData << " ";
fileOutputLabelData << std::fixed << std::setprecision(6) << midY;
fileOutputLabelData << " ";
fileOutputLabelData << std::fixed << std::setprecision(6) << width;
fileOutputLabelData << " ";
fileOutputLabelData << std::fixed << std::setprecision(6) << height << std::endl;
}
fileOutputLabelData.close();
ui->textEdit_log->setText(qstrOutputLabelData + " saved.");
}
}
void MainWindow::clear_label_data()
{
ui->label_image->m_objBoundingBoxes.clear();
ui->label_image->showImage();
}
void MainWindow::next_label()
{
set_label(m_objIndex + 1);
}
void MainWindow::prev_label()
{
set_label(m_objIndex - 1);
}
void MainWindow::load_label_list_data(QString qstrLabelListFile)
{
ifstream inputLabelListFile(qstrLabelListFile.toStdString());
if(inputLabelListFile.is_open())
{
for(int i = 0 ; i <= ui->tableWidget_label->rowCount(); i++)
ui->tableWidget_label->removeRow(ui->tableWidget_label->currentRow());
m_objList.clear();
ui->tableWidget_label->setRowCount(0);
ui->label_image->m_drawObjectBoxColor.clear();
string strLabel;
int fileIndex = 0;
while(getline(inputLabelListFile, strLabel))
{
int nRow = ui->tableWidget_label->rowCount();
std::cout << nRow << endl;
QString qstrLabel = QString().fromStdString(strLabel);
QColor labelColor = label_img::BOX_COLORS[(fileIndex++)%10];
m_objList << qstrLabel;
ui->tableWidget_label->insertRow(nRow);
ui->tableWidget_label->setItem(nRow, 0, new QTableWidgetItem(qstrLabel));
ui->tableWidget_label->item(nRow, 0)->setFlags(ui->tableWidget_label->item(nRow, 0)->flags() ^ Qt::ItemIsEditable);
ui->tableWidget_label->setItem(nRow, 1, new QTableWidgetItem(QString().fromStdString("")));
ui->tableWidget_label->item(nRow, 1)->setBackgroundColor(labelColor);
ui->tableWidget_label->item(nRow, 1)->setFlags(ui->tableWidget_label->item(nRow, 1)->flags() ^ Qt::ItemIsEditable ^ Qt::ItemIsSelectable);
ui->label_image->m_drawObjectBoxColor.push_back(labelColor);
}
}
}
QString MainWindow::get_labeling_data(QString qstrImgFile)const
{
string strImgFile = qstrImgFile.toStdString();
string strLabelData = strImgFile.substr(0, strImgFile.find_last_of('.')) + ".txt";
return QString().fromStdString(strLabelData);
}
void MainWindow::set_label(const int labelIndex)
{
bool bIndexIsOutOfRange = (labelIndex < 0 || labelIndex > m_objList.size() - 1);
if(!bIndexIsOutOfRange)
{
m_objIndex = labelIndex;
ui->label_image->setFocusObjectLabel(m_objIndex);
ui->label_image->setFocusObjectName(m_objList.at(m_objIndex));
ui->tableWidget_label->setCurrentCell(m_objIndex, 0);
}
}
void MainWindow::set_label_color(const int index, const QColor color)
{
ui->label_image->m_drawObjectBoxColor.replace(index, color);
}
void MainWindow::pjreddie_style_msgBox(QMessageBox::Icon icon, QString title, QString content)
{
QMessageBox msgBox(icon, title, content, QMessageBox::Ok);
QFont font;
font.setBold(true);
msgBox.setFont(font);
msgBox.button(QMessageBox::Ok)->setFont(font);
msgBox.button(QMessageBox::Ok)->setStyleSheet("border-style: outset; border-width: 2px; border-color: rgb(0, 255, 0); color : rgb(0, 255, 0);");
msgBox.button(QMessageBox::Ok)->setFocusPolicy(Qt::ClickFocus);
msgBox.setStyleSheet("background-color : rgb(34, 0, 85); color : rgb(0, 255, 0);");
msgBox.exec();
}
void MainWindow::open_img_dir(bool& ret)
{
pjreddie_style_msgBox(QMessageBox::Information,"Help", "Step 1. Open Your Data Set Directory");
QString imgDir = QFileDialog::getExistingDirectory(
nullptr,
tr("Open Dataset Directory"),
"./",QFileDialog::ShowDirsOnly);
QDir dir(imgDir);
QStringList fileList = dir.entryList(
QStringList() << "*.jpg" << "*.JPG" << "*.png",
QDir::Files);
if(fileList.empty())
{
ret = false;
pjreddie_style_msgBox(QMessageBox::Critical,"Error", "This folder is empty");
}
else
{
ret = true;
m_imgDir = imgDir;
m_imgList = fileList;
for(QString& str: m_imgList)
str = m_imgDir + "/" + str;
}
}
void MainWindow::open_obj_file(bool& ret)
{
pjreddie_style_msgBox(QMessageBox::Information,"Help", "Step 2. Open Your Label List File(*.txt or *.names)");
QString fileLabelList = QFileDialog::getOpenFileName(
nullptr,
tr("Open LabelList file"),
"./",
tr("LabelList Files (*.txt *.names)"));
if(fileLabelList.size() == 0)
{
ret = false;
pjreddie_style_msgBox(QMessageBox::Critical,"Error", "LabelList file is not opened()");
}
else
{
ret = true;
load_label_list_data(fileLabelList);
}
}
void MainWindow::reupdate_img_list()
{
}
void MainWindow::wheelEvent(QWheelEvent *ev)
{
if(ev->delta() > 0) // up Wheel
prev_img();
else if(ev->delta() < 0) //down Wheel
next_img();
}
void MainWindow::on_pushButton_prev_clicked()
{
prev_img();
}
void MainWindow::on_pushButton_next_clicked()
{
next_img();
}
void MainWindow::keyPressEvent(QKeyEvent * event)
{
cout << "key pressed" <<endl;
int nKey = event->key();
bool graveAccentKeyIsPressed = (nKey == Qt::Key_QuoteLeft);
bool numKeyIsPressed = (nKey >= Qt::Key_0 && nKey <= Qt::Key_9 );
if(graveAccentKeyIsPressed)
{
set_label(0);
}
else if(numKeyIsPressed)
{
int asciiToNumber = nKey - Qt::Key_0;
if(asciiToNumber < m_objList.size() )
{
set_label(asciiToNumber);
}
}
}
void MainWindow::on_pushButton_save_clicked()
{
save_label_data();
}
void MainWindow::on_pushButton_remove_clicked()
{
//remove a image
QFile::remove(m_imgList.at(m_imgIndex));
//remove a txt file
QString qstrOutputLabelData = get_labeling_data(m_imgList.at(m_imgIndex));
QFile::remove(qstrOutputLabelData);
m_imgList.removeAt(m_imgIndex);
if(m_imgList.size() == 0)
{
pjreddie_style_msgBox(QMessageBox::Information,"End", "In directory, there are not any image. program quit.");
QCoreApplication::quit();
}
else if( m_imgIndex == m_imgList.size())
{
m_imgIndex --;
}
goto_img(m_imgIndex);
}
void MainWindow::on_tableWidget_label_cellDoubleClicked(int row, int column)
{
bool bColorAttributeClicked = (column == 1);
if(bColorAttributeClicked)
{
QColor color = QColorDialog::getColor(Qt::white,nullptr,"Set Label Color");
if(color.isValid())
{
set_label_color(row, color);
ui->tableWidget_label->item(row, 1)->setBackgroundColor(color);
}
set_label(row);
ui->label_image->showImage();
}
}
void MainWindow::on_tableWidget_label_cellClicked(int row, int column)
{
set_label(row);
}
void MainWindow::on_horizontalSlider_images_sliderMoved(int position)
{
goto_img(position);
}
void MainWindow::init_button_event()
{
ui->pushButton_change_dir->setEnabled(true);
ui->pushButton_next->setEnabled(true);
ui->pushButton_prev->setEnabled(true);
ui->pushButton_save->setEnabled(true);
ui->pushButton_remove->setEnabled(true);
}
void MainWindow::init_horizontal_slider()
{
ui->horizontalSlider_images->setEnabled(true);
ui->horizontalSlider_images->setRange(0, m_imgList.size() - 1);
ui->horizontalSlider_images->blockSignals(true);
ui->horizontalSlider_images->setValue(0);
ui->horizontalSlider_images->blockSignals(false);
}
void MainWindow::init_table_widget()
{
ui->tableWidget_label->horizontalHeader()->setVisible(true);
ui->tableWidget_label->horizontalHeader()->setStyleSheet("");
ui->tableWidget_label->horizontalHeader()->setStretchLastSection(true);
disconnect(ui->tableWidget_label->horizontalHeader(), SIGNAL(sectionPressed(int)),ui->tableWidget_label, SLOT(selectColumn(int)));
}