EditDepthArea.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007     * Redistributions of source code must retain the above copyright
00008       notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright
00010       notice, this list of conditions and the following disclaimer in the
00011       documentation and/or other materials provided with the distribution.
00012     * Neither the name of the Universite de Sherbrooke nor the
00013       names of its contributors may be used to endorse or promote products
00014       derived from this software without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
00020 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 */
00027 
00028 #include <QWidget>
00029 #include <QPainter>
00030 #include <QMouseEvent>
00031 #include <QMenu>
00032 #include <QAction>
00033 #include <QInputDialog>
00034 
00035 #include "rtabmap/gui/EditDepthArea.h"
00036 #include <rtabmap/utilite/ULogger.h>
00037 #include <rtabmap/utilite/UCv2Qt.h>
00038 
00039 namespace rtabmap {
00040 
00041 EditDepthArea::EditDepthArea(QWidget *parent)
00042     : QWidget(parent)
00043 {
00044     setAttribute(Qt::WA_StaticContents);
00045     modified_ = false;
00046     scribbling_ = false;
00047     myPenWidth_ = 10;
00048 
00049     menu_ = new QMenu(tr(""), this);
00050     showRGB_ = menu_->addAction(tr("Show RGB Image"));
00051     showRGB_->setCheckable(true);
00052     showRGB_->setChecked(true);
00053     removeCluster_ = menu_->addAction(tr("Remove Cluster"));
00054         setPenWidth_ = menu_->addAction(tr("Set Pen Width..."));
00055         resetChanges_ = menu_->addAction(tr("Reset Changes"));
00056 }
00057 
00058 void EditDepthArea::setImage(const cv::Mat &depth, const cv::Mat & rgb)
00059 {
00060         UASSERT(!depth.empty());
00061         UASSERT(depth.type() == CV_32FC1 ||
00062                         depth.type() == CV_16UC1);
00063         originalImage_ = depth;
00064         image_ = uCvMat2QImage(depth).convertToFormat(QImage::Format_RGB32);
00065 
00066         imageRGB_ = QImage();
00067         if(!rgb.empty())
00068         {
00069                 imageRGB_ = uCvMat2QImage(rgb);
00070                 if( depth.cols != rgb.cols ||
00071                         depth.rows != rgb.rows)
00072                 {
00073                         // scale rgb to depth
00074                         imageRGB_ = imageRGB_.scaled(image_.size());
00075                 }
00076         }
00077         showRGB_->setEnabled(!imageRGB_.isNull());
00078         modified_ = false;
00079         update();
00080 }
00081 
00082 cv::Mat EditDepthArea::getModifiedImage() const
00083 {
00084         cv::Mat modifiedImage = originalImage_.clone();
00085         if(modified_)
00086         {
00087                 UASSERT(image_.width() == modifiedImage.cols &&
00088                                 image_.height() == modifiedImage.rows);
00089                 UASSERT(modifiedImage.type() == CV_32FC1 ||
00090                                 modifiedImage.type() == CV_16UC1);
00091                 for(int j=0; j<image_.height(); ++j)
00092                 {
00093                         for(int i=0; i<image_.width(); ++i)
00094                         {
00095                                 if(qRed(image_.pixel(i, j)) == 0 &&
00096                                    qGreen(image_.pixel(i, j)) == 0 &&
00097                                    qBlue(image_.pixel(i, j)) == 0)
00098                                 {
00099                                         if(modifiedImage.type() == CV_32FC1)
00100                                         {
00101                                                 modifiedImage.at<float>(j,i) = 0.0f;
00102                                         }
00103                                         else // CV_16UC1
00104                                         {
00105                                                 modifiedImage.at<unsigned short>(j,i) = 0;
00106                                         }
00107                                 }
00108                         }
00109                 }
00110         }
00111         return modifiedImage;
00112 }
00113 
00114 void EditDepthArea::setPenWidth(int newWidth)
00115 {
00116     myPenWidth_ = newWidth;
00117 }
00118 
00119 void EditDepthArea::resetChanges()
00120 {
00121     image_ = uCvMat2QImage(originalImage_).convertToFormat(QImage::Format_RGB32);
00122     modified_ = false;
00123     update();
00124 }
00125 
00126 void EditDepthArea::mousePressEvent(QMouseEvent *event)
00127 {
00128     if (event->button() == Qt::LeftButton) {
00129         float scale, offsetX, offsetY;
00130                 computeScaleOffsets(rect(), scale, offsetX, offsetY);
00131         lastPoint_.setX((event->pos().x()-offsetX)/scale);
00132         lastPoint_.setY((event->pos().y()-offsetY)/scale);
00133 
00134         scribbling_ = true;
00135     }
00136 }
00137 
00138 void EditDepthArea::mouseMoveEvent(QMouseEvent *event)
00139 {
00140     if ((event->buttons() & Qt::LeftButton) && scribbling_)
00141     {
00142         float scale, offsetX, offsetY;
00143                 computeScaleOffsets(rect(), scale, offsetX, offsetY);
00144                 QPoint to;
00145                 to.setX((event->pos().x()-offsetX)/scale);
00146                 to.setY((event->pos().y()-offsetY)/scale);
00147         drawLineTo(to);
00148     }
00149 }
00150 
00151 void EditDepthArea::mouseReleaseEvent(QMouseEvent *event)
00152 {
00153     if (event->button() == Qt::LeftButton && scribbling_) {
00154         float scale, offsetX, offsetY;
00155                 computeScaleOffsets(rect(), scale, offsetX, offsetY);
00156                 QPoint to;
00157                 to.setX((event->pos().x()-offsetX)/scale);
00158                 to.setY((event->pos().y()-offsetY)/scale);
00159                 drawLineTo(to);
00160         scribbling_ = false;
00161     }
00162 }
00163 
00164 void EditDepthArea::computeScaleOffsets(const QRect & targetRect, float & scale, float & offsetX, float & offsetY) const
00165 {
00166         scale = 1.0f;
00167         offsetX = 0.0f;
00168         offsetY = 0.0f;
00169 
00170         if(!image_.isNull())
00171         {
00172                 float w = image_.width();
00173                 float h = image_.height();
00174                 float widthRatio = float(targetRect.width()) / w;
00175                 float heightRatio = float(targetRect.height()) / h;
00176 
00177                 //printf("w=%f, h=%f, wR=%f, hR=%f, sW=%d, sH=%d\n", w, h, widthRatio, heightRatio, this->rect().width(), this->rect().height());
00178                 if(widthRatio < heightRatio)
00179                 {
00180                         scale = widthRatio;
00181                 }
00182                 else
00183                 {
00184                         scale = heightRatio;
00185                 }
00186 
00187                 //printf("ratio=%f\n",ratio);
00188 
00189                 w *= scale;
00190                 h *= scale;
00191 
00192                 if(w < targetRect.width())
00193                 {
00194                         offsetX = (targetRect.width() - w)/2.0f;
00195                 }
00196                 if(h < targetRect.height())
00197                 {
00198                         offsetY = (targetRect.height() - h)/2.0f;
00199                 }
00200                 //printf("offsetX=%f, offsetY=%f\n",offsetX, offsetY);
00201         }
00202 }
00203 
00204 void EditDepthArea::paintEvent(QPaintEvent *event)
00205 {
00206         //Scale
00207         float ratio, offsetX, offsetY;
00208         this->computeScaleOffsets(event->rect(), ratio, offsetX, offsetY);
00209         QPainter painter(this);
00210 
00211         painter.translate(offsetX, offsetY);
00212         painter.scale(ratio, ratio);
00213 
00214         if(showRGB_->isChecked() && !imageRGB_.isNull())
00215         {
00216                 painter.setOpacity(0.5);
00217                 painter.drawImage(QPoint(0,0), imageRGB_);
00218         }
00219 
00220         painter.drawImage(QPoint(0,0), image_);
00221 }
00222 
00223 void EditDepthArea::resizeEvent(QResizeEvent *event)
00224 {
00225     QWidget::resizeEvent(event);
00226 }
00227 
00228 void floodfill(QImage & image, const cv::Mat & depthImage, int x, int y, float lastDepthValue, float error)
00229 {
00230         if(x>=0 && x<depthImage.cols &&
00231            y>=0 && y<depthImage.rows)
00232         {
00233                 float currentValue;
00234                 if(depthImage.type() == CV_32FC1)
00235                 {
00236                         currentValue = depthImage.at<float>(y, x);
00237                 }
00238                 else
00239                 {
00240                         currentValue = float(depthImage.at<unsigned short>(y, x))/1000.0f;
00241                 }
00242 
00243                 QRgb rgb = image.pixel(x,y);
00244                 if(qRed(rgb) == 0 && qGreen(rgb) == 0 && qBlue(rgb) == 0)
00245                 {
00246                         return;
00247                 }
00248                 if(currentValue == 0.0f)
00249                 {
00250                         return;
00251                 }
00252                 if(lastDepthValue>=0.0f && fabs(lastDepthValue - currentValue) > error*lastDepthValue)
00253                 {
00254                         return;
00255                 }
00256 
00257                 image.setPixel(x, y, 0);
00258 
00259                 floodfill(image, depthImage, x, y+1, currentValue, error);
00260                 floodfill(image, depthImage, x, y-1, currentValue, error);
00261                 floodfill(image, depthImage, x-1, y, currentValue, error);
00262                 floodfill(image, depthImage, x+1, y, currentValue, error);
00263         }
00264 }
00265 
00266 void EditDepthArea::contextMenuEvent(QContextMenuEvent * e)
00267 {
00268         QAction * action = menu_->exec(e->globalPos());
00269         if(action == showRGB_)
00270         {
00271                 this->update();
00272         }
00273         else if(action == removeCluster_)
00274         {
00275                 float scale, offsetX, offsetY;
00276                 computeScaleOffsets(rect(), scale, offsetX, offsetY);
00277                 QPoint pixel;
00278                 pixel.setX((e->pos().x()-offsetX)/scale);
00279                 pixel.setY((e->pos().y()-offsetY)/scale);
00280                 if(pixel.x()>=0 && pixel.x() < originalImage_.cols &&
00281                    pixel.y()>=0 && pixel.y() < originalImage_.rows)
00282                 {
00283                         floodfill(image_, originalImage_, pixel.x(), pixel.y(), -1.0f, 0.02f);
00284                 }
00285                 modified_=true;
00286                 this->update();
00287         }
00288         else if(action == setPenWidth_)
00289         {
00290                 bool ok;
00291                 int width = QInputDialog::getInt(this, tr("Set Pen Width"), tr("Width:"), penWidth(), 1, 99, 1, &ok);
00292                 if(ok)
00293                 {
00294                         myPenWidth_ = width;
00295                 }
00296         }
00297         else if(action == resetChanges_)
00298         {
00299                 this->resetChanges();
00300         }
00301 }
00302 
00303 void EditDepthArea::drawLineTo(const QPoint &endPoint)
00304 {
00305     QPainter painter(&image_);
00306     painter.setPen(QPen(Qt::black, myPenWidth_, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
00307     painter.drawLine(lastPoint_, endPoint);
00308     modified_ = true;
00309 
00310     update();
00311     lastPoint_ = endPoint;
00312 }
00313 
00314 }


rtabmap
Author(s): Mathieu Labbe
autogenerated on Thu Jun 6 2019 21:59:19