diff --git a/CMakeLists.txt b/CMakeLists.txt index 91cd0d3..08b1fb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,8 @@ endif() include_directories(${catkin_INCLUDE_DIRS} src/ ${QT5_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} /usr/include/eigen3) +add_compile_definitions(ASSETS_PATH="${CMAKE_CURRENT_SOURCE_DIR}/assets") + set(CMAKE_INCLUDE_CURRENT_DIR ON) # needs to be activated for qt generated files in build directory. set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_FLAGS "-std=c++11 -O3 -Wall ${CMAKE_CXX_FLAGS}") diff --git a/README.md b/README.md index 0ab99e6..2b10e4a 100644 --- a/README.md +++ b/README.md @@ -120,3 +120,7 @@ If you're using the tool in your research, it would be nice if you cite our [pap ``` We used the tool to label SemanticKITTI, which contains overall over 40.000 scans organized in 20 sequences. + +## Asset Attribution + +Camera icon made by [Ilham Fitrotul Hayat](https://www.flaticon.com/authors/ilham-fitrotul-hayat) from [www.flaticon.com](https://www.flaticon.com/). Dark/Light background toggle icon made by [Icon-Hubs](https://www.flaticon.com/authors/icon-hubs) from [www.flaticon.com](https://www.flaticon.com/). Image icon made by [feen](https://www.flaticon.com/authors/feen) from [www.flaticon.com](https://www.flaticon.com/). \ No newline at end of file diff --git a/assets/camera.png b/assets/camera.png new file mode 100644 index 0000000..c21f102 Binary files /dev/null and b/assets/camera.png differ diff --git a/assets/dark_mode.png b/assets/dark_mode.png new file mode 100644 index 0000000..e29d8aa Binary files /dev/null and b/assets/dark_mode.png differ diff --git a/assets/insert_picture_icon.png b/assets/insert_picture_icon.png new file mode 100644 index 0000000..2c742b1 Binary files /dev/null and b/assets/insert_picture_icon.png differ diff --git a/assets/insert_picture_icon_2.png b/assets/insert_picture_icon_2.png new file mode 100644 index 0000000..da6d0de Binary files /dev/null and b/assets/insert_picture_icon_2.png differ diff --git a/src/MainFrame.ui b/src/MainFrame.ui index 6e79d27..38ac454 100644 --- a/src/MainFrame.ui +++ b/src/MainFrame.ui @@ -361,7 +361,7 @@ 0 0 - 200 + 253 706 @@ -1466,6 +1466,7 @@ + @@ -1581,6 +1582,11 @@ screenshot + + + Toggle Dark Background + + diff --git a/src/labeler.cpp b/src/labeler.cpp index d7a73c3..8a2e7dc 100644 --- a/src/labeler.cpp +++ b/src/labeler.cpp @@ -11,7 +11,10 @@ int main(int argc, char** argv) { frame.show(); frame.resize(1200, 900); -// std::cout << glow::GlCapabilities::getInstance() << std::endl; + // QPalette pal = app.palette(); + // pal.setColor(QPalette::Window, Qt::black); + // app.setPalette(pal); +// std::cout << glow::GlCapabilities::getInstance() << std::endl; return app.exec(); } diff --git a/src/widget/KittiReader.cpp b/src/widget/KittiReader.cpp index 20f3ce9..47a3936 100644 --- a/src/widget/KittiReader.cpp +++ b/src/widget/KittiReader.cpp @@ -9,6 +9,9 @@ #include "rv/string_utils.h" #include +#include + +namespace fs = boost::filesystem; void KittiReader::initialize(const QString& directory) { velodyne_filenames_.clear(); @@ -37,8 +40,13 @@ void KittiReader::initialize(const QString& directory) { // create label dir, etc. QDir labels_dir(base_dir_.filePath("labels")); + // find corresponding label files. - if (!labels_dir.exists()) base_dir_.mkdir("labels"); + if (!labels_dir.exists()) + { + std::cout << "Found no labels. Creating labels directory\n"; + base_dir_.mkdir("labels"); + } for (uint32_t i = 0; i < velodyne_filenames_.size(); ++i) { QString filename = QFileInfo(QString::fromStdString(velodyne_filenames_[i])).baseName() + ".label"; @@ -55,18 +63,17 @@ void KittiReader::initialize(const QString& directory) { out.close(); } - label_filenames_.push_back(labels_dir.filePath(filename).toStdString()); } - std::string missing_img = QDir::currentPath().toStdString() + "/../assets/missing.png"; + fs::path missing_img = fs::path(ASSETS_PATH) / "missing.png"; QDir image_dir(base_dir_.filePath("image_2")); for (uint32_t i = 0; i < velodyne_filenames_.size(); ++i) { QString filename = QFileInfo(QString::fromStdString(velodyne_filenames_[i])).baseName() + ".png"; if (image_dir.exists(filename)) { image_filenames_.push_back(image_dir.filePath(filename).toStdString()); } else { - image_filenames_.push_back(missing_img); + image_filenames_.push_back(missing_img.string()); } } @@ -207,9 +214,13 @@ void KittiReader::initialize(const QString& directory) { uint32_t instanceId = (instance_label >> 16) & uint32_t(0xFFFF); uint32_t label = instance_label & uint32_t(0xFFFF); if (maxInstanceIds_.find(label) == maxInstanceIds_.end()) + { maxInstanceIds_[label] = instanceId; + } else + { maxInstanceIds_[label] = std::max(instanceId, maxInstanceIds_[label]); + } } } diff --git a/src/widget/Mainframe.cpp b/src/widget/Mainframe.cpp index eb6e02c..fed364b 100644 --- a/src/widget/Mainframe.cpp +++ b/src/widget/Mainframe.cpp @@ -16,8 +16,10 @@ #include #include +#include using namespace glow; +namespace fs = boost::filesystem; // see https://stackoverflow.com/a/24349347 template @@ -52,6 +54,9 @@ Mainframe::Mainframe() : mChangesSinceLastSave(false) { connect(ui.actionPolygonMode, &QAction::triggered, [this]() { changeMode(Viewport::POLYGON, ui.actionPolygonMode->isChecked()); }); + connect(ui.actionToggleDarkBackground, &QAction::triggered, + [this]() { ui.mViewportXYZ->toggleBackground(); }); + ui.btnOverwrite->setDefaultAction(ui.actionOverwrite); ui.btnFilter->setDefaultAction(ui.actionFilter); @@ -480,6 +485,7 @@ Mainframe::Mainframe() : mChangesSinceLastSave(false) { connect(ui.actionScreenshot, &QAction::triggered, [this]() { QImage img = ui.mViewportXYZ->grabFrameBuffer(); + std::cout << "-- Saving screenshot to screenshot.png" << std::endl; img.save("screenshot.png"); QApplication::clipboard()->setImage(img); }); @@ -1000,11 +1006,11 @@ void Mainframe::readConfig() { } void Mainframe::initializeIcons() { - std::string assertDir = QDir::currentPath().toStdString() + "/../assets/"; + fs::path assetDir = fs::path(ASSETS_PATH); std::cout << QDir::currentPath().toStdString() << std::endl; { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "brush.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "brush.png").string()))); ui.actionPaintMode->setIcon(icon); ui.btnBrushMode->setIcon(icon); @@ -1012,72 +1018,86 @@ void Mainframe::initializeIcons() { { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "polygon.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "polygon.png").string()))); ui.actionPolygonMode->setIcon(icon); ui.btnPolygonMode->setIcon(icon); } { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "filter.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "filter.png").string()))); ui.actionFilter->setIcon(icon); } { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "overwrite_on.png")), QIcon::Normal, QIcon::On); - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "overwrite_off.png")), QIcon::Normal, QIcon::Off); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "overwrite_on.png").string())), QIcon::Normal, QIcon::On); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "overwrite_off.png").string())), QIcon::Normal, QIcon::Off); ui.actionOverwrite->setIcon(icon); } { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "open.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "open.png").string()))); ui.actionOpen->setIcon(icon); } { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "save.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "save.png").string()))); ui.actionSave->setIcon(icon); } { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "reload.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "reload.png").string()))); ui.actionReload->setIcon(icon); } { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "centerview.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "centerview.png").string()))); ui.actionCenterView->setIcon(icon); } { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "image.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "insert_picture_icon_2.png").string()))); ui.actionShowImage->setIcon(icon); } { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "layoutA.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "layoutA.png").string()))); ui.btnButtonLayoutA->setIcon(icon); } { QIcon icon; - icon.addPixmap(QPixmap(QString::fromStdString(assertDir + "layoutB.png"))); + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "layoutB.png").string()))); ui.btnButtonLayoutB->setIcon(icon); } + + { + QIcon icon; + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "dark_mode.png").string()))); + + ui.actionToggleDarkBackground->setIcon(icon); + } + + { + QIcon icon; + icon.addPixmap(QPixmap(QString::fromStdString((assetDir / "camera.png").string()))); + + ui.actionScreenshot->setIcon(icon); + } } void Mainframe::keyPressEvent(QKeyEvent* event) { diff --git a/src/widget/Viewport.cpp b/src/widget/Viewport.cpp index 13b4c0d..7701132 100644 --- a/src/widget/Viewport.cpp +++ b/src/widget/Viewport.cpp @@ -23,6 +23,7 @@ Viewport::Viewport(QWidget* parent, Qt::WindowFlags f) contextInitialized_(initContext()), mAxis(XYZ), mMode(NONE), + mBackground(LIGHT), mFlags(FLAG_OVERWRITE), mCurrentLabel(0), mRadius(5), @@ -561,6 +562,17 @@ void Viewport::setMode(MODE mode) { updateGL(); } +void Viewport::toggleBackground() { + if (mBackground == BACKGROUND::LIGHT) + { + mBackground = BACKGROUND::DARK; + } else { + mBackground = BACKGROUND::LIGHT; + } + + updateGL(); +} + void Viewport::setFlags(int32_t flags) { mFlags = flags; } void Viewport::setOverwrite(bool value) { @@ -670,7 +682,7 @@ void Viewport::setLabelVisibility(uint32_t label, bool visible) { } void Viewport::initializeGL() { - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + applyBackground(); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glEnable(GL_LINE_SMOOTH); @@ -678,6 +690,14 @@ void Viewport::initializeGL() { mCamera->lookAt(5.0f, 5.0f, 5.0f, 0.0f, 0.0f, 0.0f); } +void Viewport::applyBackground() { + if (mBackground == LIGHT) { + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + } else { + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + } +} + void Viewport::resizeGL(int w, int h) { glViewport(0, 0, w, h); @@ -708,6 +728,7 @@ void Viewport::resizeGL(int w, int h) { void Viewport::paintGL() { glow::_CheckGlError(__FILE__, __LINE__); + applyBackground(); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPointSize(pointSize_); diff --git a/src/widget/Viewport.h b/src/widget/Viewport.h index 787cefe..7f74a0f 100644 --- a/src/widget/Viewport.h +++ b/src/widget/Viewport.h @@ -51,6 +51,8 @@ class Viewport : public QGLWidget { enum MODE { NONE, PAINT, POLYGON }; + enum BACKGROUND { LIGHT, DARK }; + enum FLAGS { FLAG_OVERWRITE = 1, FLAG_OTHER = 2 }; enum class CameraProjection { perspective, orthographic }; @@ -142,6 +144,7 @@ class Viewport : public QGLWidget { void setInstanceableLabels(const std::vector& labels); void setMode(MODE mode); + void toggleBackground(); void setFlags(int32_t flags); void setOverwrite(bool value); @@ -178,6 +181,7 @@ class Viewport : public QGLWidget { void initializeGL(); void resizeGL(int width, int height); void paintGL(); + void applyBackground(); void wheelEvent(QWheelEvent*); void mousePressEvent(QMouseEvent*); @@ -221,6 +225,7 @@ class Viewport : public QGLWidget { AXIS mAxis; MODE mMode; + BACKGROUND mBackground; int32_t mFlags; uint32_t mCurrentLabel;