Skip to content

Commit

Permalink
add coco importer
Browse files Browse the repository at this point in the history
  • Loading branch information
jveitchmichaelis committed May 9, 2020
1 parent 757ecc4 commit 902de2a
Show file tree
Hide file tree
Showing 13 changed files with 292 additions and 68 deletions.
6 changes: 4 additions & 2 deletions DeepLabel.pro
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ SOURCES += \
src/pascalvocexporter.cpp \
detection/detectoropencv.cpp \
detection/detectorsetupdialog.cpp \
src/refinerangedialog.cpp
src/refinerangedialog.cpp \
src/cocoimporter.cpp

HEADERS += \
mainwindow.h \
Expand All @@ -113,7 +114,8 @@ HEADERS += \
src/pascalvocexporter.h \
detection/detectoropencv.h \
detection/detectorsetupdialog.h \
src/refinerangedialog.h
src/refinerangedialog.h \
src/cocoimporter.h

FORMS += \
src/importdialog.ui \
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ A typical workflow for DeepLabel is:
4. Label the images
5. Export data in the desired format

## Data import

Currently you can import data in the following formats:

* Darknet (provide image list and names)
* COCO (provide an annotation .json file)

## Data export

Currently you can export in:
Expand Down
2 changes: 1 addition & 1 deletion src/baseimporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class BaseImporter : public QObject
Q_OBJECT
public:
explicit BaseImporter(QObject *parent = nullptr);
virtual void import(QString input_file, QString label_file) = 0;
void import(){};

void setRootFolder(QString folder);
void setImportUnlabelled(bool import);
Expand Down
120 changes: 120 additions & 0 deletions src/cocoimporter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "cocoimporter.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <boundingbox.h>

void CocoImporter::import(QString annotation_file){
// Load Json
qDebug() << "Loading JSON";
QFile loadFile(annotation_file);
loadFile.open(QIODevice::ReadOnly | QIODevice::Text);
QByteArray json_data = loadFile.readAll();
auto json = QJsonDocument::fromJson(json_data);

// Load classes (categories)
auto categories = json["categories"];
if(categories == QJsonValue::Undefined){
qDebug() << "Categories not found";
return;
}

QMap<int, QString> classes;
QJsonValue item;
foreach(item, categories.toArray()){

auto item_name = item["name"];
if(item_name == QJsonValue::Undefined || !item_name.isString())
continue;

auto item_id = item["id"];
if(item_id == QJsonValue::Undefined || !item_id.isDouble())
continue;

classes.insert(item_id.toInt(), item_name.toString());
qDebug() << "added: " << item_id.toInt() << " " << item_name.toString();

project->addClass(item_name.toString());

}

// Load images
auto images = json["images"];
if(images == QJsonValue::Undefined){
qDebug() << "No images found";
return;
}

QJsonValue image;
QList<QString> image_list;
QList<QList<BoundingBox>> label_list;
QMap<int, int> image_index;
QMap<int, QString> image_map;
int i=0;
foreach(image, images.toArray()){
auto file_name = image["file_name"];
if(file_name == QJsonValue::Undefined || !file_name.isString())
continue;

auto file_id = image["id"];
if(file_id == QJsonValue::Undefined || !file_id.isDouble())
continue;

auto abs_file_name = QFileInfo(annotation_file).absoluteDir().filePath(file_name.toString());
image_map.insert(file_id.toInt(), abs_file_name);

image_list.append(abs_file_name);
label_list.append(QList<BoundingBox> {});
image_index.insert(file_id.toInt(), i++);
}

// Load labels
auto annotations = json["annotations"];
if(annotations == QJsonValue::Undefined){
qDebug() << "No annotations found";
return;
}

QJsonValue annotation;

foreach(annotation, annotations.toArray()){

auto image_id = annotation["image_id"];
if(image_id == QJsonValue::Undefined || !image_id.isDouble())
continue;

auto category_id = annotation["category_id"];
if(category_id == QJsonValue::Undefined || !category_id.isDouble())
continue;

auto image_filename = image_map[image_id.toInt()];

auto bbox = annotation["bbox"];
if(bbox == QJsonValue::Undefined || !bbox.isArray()){
qDebug() << "No bounding box found";
continue;
}

auto bbox_array = bbox.toArray();

if(bbox_array.size() != 4)
continue;

int x = bbox_array[0].toInt();
int y = bbox_array[1].toInt();
int w = bbox_array[2].toInt();
int h = bbox_array[3].toInt();

BoundingBox new_bbox;
new_bbox.rect.setX(x);
new_bbox.rect.setY(y);
new_bbox.rect.setWidth(w);
new_bbox.rect.setHeight(h);
new_bbox.classname = classes[category_id.toInt()];

label_list[image_index[image_id.toInt()]].push_back(new_bbox);
}

project->addLabelledAssets(image_list, label_list);

return;
}
18 changes: 18 additions & 0 deletions src/cocoimporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef COCOIMPORTER_H
#define COCOIMPORTER_H

#include<baseimporter.h>

class CocoImporter : public BaseImporter
{
public:
using BaseImporter::import;

explicit CocoImporter(LabelProject *project, QObject *parent = nullptr) : BaseImporter(parent){
this->project = project;
}

void import(QString annotations_file);
};

#endif // COCOIMPORTER_H
2 changes: 2 additions & 0 deletions src/darknetimporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
class DarknetImporter : public BaseImporter
{
public:
using BaseImporter::import;

explicit DarknetImporter(LabelProject *project, QObject *parent = nullptr) : BaseImporter(parent){
this->project = project;
}
Expand Down
55 changes: 55 additions & 0 deletions src/importdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ ImportDialog::ImportDialog(QWidget *parent) :
connect(ui->namesFilePushButton, SIGNAL(clicked()), this, SLOT(setNamesFile()));
connect(ui->inputListLineEdit, SIGNAL(textEdited(QString)), SLOT(setInputFile(QString)));
connect(ui->inputListPushButton, SIGNAL(clicked()), this, SLOT(setInputFile()));
connect(ui->annotationLineEdit, SIGNAL(textEdited(QString)), SLOT(setAnnotationFile(QString)));
connect(ui->annotationPushButton, SIGNAL(clicked()), this, SLOT(setAnnotationFile()));

settings = new QSettings("DeepLabel", "DeepLabel");

Expand All @@ -34,6 +36,13 @@ ImportDialog::ImportDialog(QWidget *parent) :
}
}

if(settings->contains("annotation_file")){
auto path = settings->value("annotation_file").toString();
if(path != ""){
setAnnotationFile(path);
}
}

}

ImportDialog::~ImportDialog()
Expand Down Expand Up @@ -97,6 +106,30 @@ void ImportDialog::setNamesFile(QString path){
checkOK();
}

void ImportDialog::setAnnotationFile(QString path){

if(path == ""){
QString openDir;

if(annotation_file == ""){
openDir = QDir::homePath();
}else{
openDir = QFileInfo(annotation_file).absoluteDir().absolutePath();
}

path = QFileDialog::getOpenFileName(this, tr("Select darknet names file"),
openDir);
}

if(path != ""){
annotation_file = path;
ui->annotationLineEdit->setText(annotation_file);
settings->setValue("annotation_file", annotation_file);
}

checkOK();
}

bool ImportDialog::checkOK(){

ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(true);
Expand All @@ -107,7 +140,28 @@ bool ImportDialog::checkOK(){
return false;
}

if(ui->importSelectComboBox->currentText() == "Coco"){
ui->namesFileLineEdit->setDisabled(true);
ui->namesFilePushButton->setDisabled(true);
ui->inputListLineEdit->setDisabled(true);
ui->inputListPushButton->setDisabled(true);
ui->annotationLineEdit->setEnabled(true);
ui->annotationPushButton->setEnabled(true);

if(!QFile::exists(annotation_file)){
qDebug() << "Names file doesn't exist";
return false;
}
}

if(ui->importSelectComboBox->currentText() == "Darknet"){
ui->namesFileLineEdit->setEnabled(true);
ui->namesFilePushButton->setEnabled(true);
ui->inputListLineEdit->setEnabled(true);
ui->inputListPushButton->setEnabled(true);
ui->annotationLineEdit->setDisabled(true);
ui->annotationPushButton->setDisabled(true);

// If we're using darknet, check the names
// file exists and contains something
if(!QFile::exists(names_file)){
Expand All @@ -134,6 +188,7 @@ bool ImportDialog::checkOK(){
}

ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
return true;
}


Expand Down
7 changes: 5 additions & 2 deletions src/importdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define IMPORTDIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QFile>
#include <QDir>
#include <QFileDialog>
Expand All @@ -21,13 +22,14 @@ class ImportDialog : public QDialog
QString getImporter(){return current_importer; }
QString getInputFile(){return input_file; }
QString getNamesFile(){return names_file; }
QString getAnnotationFile(){return annotation_file; }
bool getImportUnlabelled();
~ImportDialog();


private slots:
private slots:
void setNamesFile(QString path="");
void setInputFile(QString path="");
void setAnnotationFile(QString path="");
void toggleImporter();
void setImportUnlabelled(bool res);

Expand All @@ -38,6 +40,7 @@ private slots:
Ui::ImportDialog *ui;
QString input_file = "";
QString names_file = "";
QString annotation_file = "";
QString current_importer = "Darknet";
bool import_unlabelled;
};
Expand Down
Loading

0 comments on commit 902de2a

Please sign in to comment.