00001
00014 #include <iostream>
00015 #include <algorithm>
00016
00017 #include <QtGui>
00018 #include <QMessageBox>
00019 #include <QColor>
00020
00021 #include <color_table/classification_window.h>
00022
00023 namespace color_table {
00024
00025 using namespace Qt;
00026
00027 ClassificationWindow::ClassificationWindow(QWidget *parent) : QMainWindow(parent) {
00028 ui.setupUi(this);
00029
00030
00031 segColors[UNDEFINED] = qRgb(0,0,0);
00032 segColors[ORANGE] = qRgb(255,155,0);
00033 segColors[PINK] = qRgb(255,105,180);
00034 segColors[BLUE] = qRgb(0,0,255);
00035 segColors[GREEN] = qRgb(0,128,0);
00036 segColors[WHITE] = qRgb(255,255,255);
00037 segColors[YELLOW] = qRgb(255,255,0);
00038
00039 segColorNames[UNDEFINED] = "Undefined";
00040 segColorNames[ORANGE] = "Orange";
00041 segColorNames[PINK] = "Pink";
00042 segColorNames[BLUE] = "Blue";
00043 segColorNames[GREEN] = "Green";
00044 segColorNames[WHITE] = "White";
00045 segColorNames[YELLOW] = "Yellow";
00046
00047
00048 imageSelected = RGB;
00049
00050
00051 clickMode = ADD;
00052 ui.addRadio->setDown(true);
00053
00054
00055 currentColor = ORANGE;
00056 ui.orangeButton->setDown(true);
00057
00058 updateStatus();
00059 }
00060
00064 void ClassificationWindow::setColor(int color) {
00065 ui.orangeButton->setChecked(false);
00066 ui.pinkButton->setChecked(false);
00067 ui.blueButton->setChecked(false);
00068 ui.greenButton->setChecked(false);
00069 ui.whiteButton->setChecked(false);
00070 ui.yellowButton->setChecked(false);
00071
00072 switch(color) {
00073 case ORANGE:
00074 ui.orangeButton->setChecked(true);
00075 break;
00076 case PINK:
00077 ui.pinkButton->setChecked(true);
00078 break;
00079 case BLUE:
00080 ui.blueButton->setChecked(true);
00081 break;
00082 case GREEN:
00083 ui.greenButton->setChecked(true);
00084 break;
00085 case WHITE:
00086 ui.whiteButton->setChecked(true);
00087 break;
00088 case YELLOW:
00089 ui.yellowButton->setChecked(true);
00090 break;
00091 default:;
00092 };
00093
00094 ui.colorCombo->setCurrentIndex(color - 1);
00095 currentColor = (Color) color;
00096
00097 updateStatus();
00098 }
00099
00103 void ClassificationWindow::updateStatus() {
00104
00105 std::string status;
00106 switch(clickMode) {
00107 case ADD:
00108 status += "Adding";
00109 break;
00110 case DELETE:
00111 status += "Removing";
00112 break;
00113 }
00114
00115 status += " ";
00116 status += segColorNames[currentColor];
00117 status += " ";
00118 status += "pixels.";
00119
00120 ui.statusBar->showMessage(QString(status.c_str()));
00121 }
00122
00126 void ClassificationWindow::drawRgbImage(ImageWidget *widget) {
00127
00128 QRgb value;
00129 for (unsigned int i = 0; i < IMAGE_HEIGHT; i++) {
00130 for (unsigned int j = 0; j < IMAGE_WIDTH; j++) {
00131 value = qRgb(rgbImage[i][j].r, rgbImage[i][j].g, rgbImage[i][j].b);
00132 widget->img->setPixel(j,i,value);
00133 }
00134 }
00135
00136 widget->repaint();
00137
00138 }
00139
00143 void ClassificationWindow::drawSegImage(ImageWidget *widget) {
00144
00145 QRgb value;
00146 for (unsigned int i = 0; i < IMAGE_HEIGHT; i++) {
00147 for (unsigned int j = 0; j < IMAGE_WIDTH; j++) {
00148 value = segColors[segImage[i][j]];
00149 widget->img->setPixel(j,i,value);
00150 }
00151 }
00152
00153 widget->repaint();
00154
00155 }
00156
00160 void ClassificationWindow::changeImage(sensor_msgs::ImageConstPtr image) {
00161
00162 for (unsigned int i = 0; i < image->height; i++) {
00163 for (unsigned int j = 0; j < image->width; j++) {
00164 rgbImage[i][j].r = image->data[i * image->step + 3 * j + 0];
00165 rgbImage[i][j].g = image->data[i * image->step + 3 * j + 1];
00166 rgbImage[i][j].b = image->data[i * image->step + 3 * j + 2];
00167 }
00168 }
00169
00170 redrawImages();
00171 }
00172
00177 void ClassificationWindow::segmentImage(bool useTempColorTable) {
00178
00179 ColorTable *table = &colorTable;
00180 if (useTempColorTable) {
00181 table = &tempColorTable;
00182 }
00183
00184 for (unsigned int i = 0; i < IMAGE_HEIGHT; i++) {
00185 for (unsigned int j = 0; j < IMAGE_WIDTH; j++) {
00186 segImage[i][j] = (*table)[rgbImage[i][j].r / 2][rgbImage[i][j].g / 2][rgbImage[i][j].b / 2];
00187 }
00188 }
00189
00190 }
00191
00195 void ClassificationWindow::redrawImages(bool useTempColorTable) {
00196
00197 segmentImage(useTempColorTable);
00198
00199 drawRgbImage(ui.rawImage);
00200 drawSegImage(ui.segImage);
00201
00202 if (imageSelected == RGB) {
00203 drawRgbImage(ui.bigImage);
00204 } else {
00205 drawSegImage(ui.bigImage);
00206 }
00207
00208 }
00209
00214 void ClassificationWindow::closeEvent(QCloseEvent *event) {
00215 event->accept();
00216 }
00217
00221 bool ClassificationWindow::openColorTable() {
00222 FILE* f = fopen(colorTableFilename.c_str(), "rb");
00223 if (!f || ferror(f)) {
00224 return false;
00225 }
00226 size_t bytesRead = fread(tempColorTable, 128*128*128, 1, f);
00227 fclose(f);
00228 memcpy(colorTable, tempColorTable, 128*128*128);
00229 return bytesRead;
00230 }
00231
00235 void ClassificationWindow::openDefaultColorTable() {
00236 colorTableFilename = dataDirectory + "default.col";
00237 openColorTable();
00238 }
00239
00244 void ClassificationWindow::loadDataDirectory(std::string basePath) {
00245 dataDirectory = basePath;
00246 }
00247
00248 void ClassificationWindow::on_bigImage_clicked(int x, int y, int button) {
00249
00250 switch (button) {
00251
00252 case Qt::LeftButton: {
00253 memcpy(tempColorTable, colorTable, 128 * 128 * 128);
00254 int sen = ui.sensitivityDial->value();
00255 Rgb rgb = rgbImage[y][x];
00256 if (clickMode == ADD) {
00257 for (int r = std::max((int)rgb.r - sen * 5, 0); r <=std::min((int)rgb.r + sen * 5, 255); r+=2) {
00258 for (int g = std::max((int)rgb.g - sen * 5, 0); g <=std::min((int)rgb.g + sen * 5, 255); g+=2) {
00259 for (int b = std::max((int)rgb.b - sen * 5, 0); b <=std::min((int)rgb.b + sen * 5, 255); b+=2) {
00260 tempColorTable[r/2][g/2][b/2] = currentColor;
00261 }
00262 }
00263 }
00264 } else {
00265 for (int r = std::max((int)rgb.r - sen * 5, 0); r <=std::min((int)rgb.r + sen * 5, 255); r+=2) {
00266 for (int g = std::max((int)rgb.g - sen * 5, 0); g <=std::min((int)rgb.g + sen * 5, 255); g+=2) {
00267 for (int b = std::max((int)rgb.b - sen * 5, 0); b <=std::min((int)rgb.b + sen * 5, 255); b+=2) {
00268 tempColorTable[r/2][g/2][b/2] = (tempColorTable[r/2][g/2][b/2] == currentColor) ? (uint8_t)UNDEFINED : tempColorTable[r/2][g/2][b/2];
00269 }
00270 }
00271 }
00272 }
00273 redrawImages(true);
00274 break;
00275 }
00276
00277 case Qt::RightButton: {
00278 memcpy(colorTable, tempColorTable, 128 * 128 * 128);
00279 redrawImages();
00280 break;
00281 }
00282
00283 }
00284
00285 }
00286 void ClassificationWindow::on_bigImage_mouseXY(int x, int y) {
00287
00288 }
00289
00290 void ClassificationWindow::on_rawImage_clicked(int x, int y, int button) {
00291 imageSelected = RGB;
00292 redrawImages();
00293 }
00294
00295 void ClassificationWindow::on_segImage_clicked(int x, int y, int button) {
00296 imageSelected = SEG;
00297 redrawImages();
00298 }
00299
00300 void ClassificationWindow::on_addRadio_clicked() {
00301 clickMode = ADD;
00302 updateStatus();
00303 }
00304
00305 void ClassificationWindow::on_deleteRadio_clicked() {
00306 clickMode = DELETE;
00307 updateStatus();
00308 }
00309
00310 void ClassificationWindow::on_orangeButton_clicked() {
00311 setColor(ORANGE);
00312 }
00313
00314 void ClassificationWindow::on_pinkButton_clicked() {
00315 setColor(PINK);
00316 }
00317
00318 void ClassificationWindow::on_blueButton_clicked() {
00319 setColor(BLUE);
00320 }
00321
00322 void ClassificationWindow::on_greenButton_clicked() {
00323 setColor(GREEN);
00324 }
00325
00326 void ClassificationWindow::on_whiteButton_clicked() {
00327 setColor(WHITE);
00328 }
00329
00330 void ClassificationWindow::on_yellowButton_clicked() {
00331 setColor(YELLOW);
00332 }
00333
00334 void ClassificationWindow::on_colorCombo_currentIndexChanged(int index) {
00335 setColor(index + 1);
00336 }
00337
00338 void ClassificationWindow::on_actionNew_triggered() {
00339 colorTableFilename.empty();
00340 memset(colorTable, UNDEFINED, 128 * 128 * 128);
00341 memset(tempColorTable, UNDEFINED, 128 * 128 * 128);
00342 }
00343
00344 void ClassificationWindow::on_actionOpen_triggered() {
00345 QString fileName = QFileDialog::getOpenFileName(this, tr("Open Color Table"),
00346 QString(dataDirectory.c_str()),
00347 tr("Color Table (*.col)"));
00348 if (fileName.isNull()) {
00349 ui.statusBar->showMessage("User cancelled operation");
00350 return;
00351 }
00352
00353 colorTableFilename = fileName.toStdString();
00354
00355 bool colorTableRead = openColorTable();
00356 if (!colorTableRead) {
00357 ui.statusBar->showMessage("Error reading color table!!");
00358 return;
00359 }
00360
00361 ui.statusBar->showMessage("Color table read successfully!");
00362 redrawImages();
00363
00364 }
00365
00366 void ClassificationWindow::on_actionSave_triggered() {
00367
00368 if (colorTableFilename.empty()) {
00369 ui.actionSave_As->trigger();
00370 }
00371
00372 FILE* f = fopen(colorTableFilename.c_str(), "wb");
00373 size_t bytesWritten = fwrite(colorTable, 128*128*128, 1, f);
00374 fclose(f);
00375 if (!bytesWritten) {
00376 ui.statusBar->showMessage("Error writing color table!!");
00377 return;
00378 }
00379
00380 ui.statusBar->showMessage("Color table written successfully!!");
00381
00382 }
00383
00384 void ClassificationWindow::on_actionSave_As_triggered() {
00385 QString fileName = QFileDialog::getSaveFileName(this, tr("Save Color Table"),
00386 QString(dataDirectory.c_str()),
00387 tr("Color Table (*.col)"));
00388 if (fileName.isNull()) {
00389 ui.statusBar->showMessage("User cancelled operation");
00390 return;
00391 }
00392
00393 colorTableFilename = fileName.toStdString();
00394 ui.actionSave->trigger();
00395
00396 }
00397
00398 }