void LocalEnhencementLabel::mouseReleaseEvent(QMouseEvent *ev) { InteractiveImageLabel::mouseReleaseEvent(ev); if(ev->button()==Qt::LeftButton&&startpos==ev->pos()) { resetRegionMask(); BasisOperation::regionExtraction(srcMat,regionMask,tolerance,region,ev->x(),ev->y()); paintCounters(); //Mat temp=Mat::zeros(regionMask->rows,regionMask->cols,CV_8UC1); //blur(*regionMask,temp,Size(featherRadius,featherRadius)); //for(int i=0;i<regionMask->cols;++i) // for(int j=0;j<regionMask->rows;++j) // { // if(regionMask->at<uchar>(j,i)==PIXEL_SELECTED_VALUE) // regionMask->at<uchar>(j,i)=temp.at<uchar>(j,i); // } } else { if(ev->button()==Qt::LeftButton) { resetRegionMask(); emit interactiveLocalEnhencementFinished(); } } }
/** * Resets the region mask by resetting the last selected region. * @returns true, if there are still regions selected afterwards * \sa DkMagicCut resetRegionMask(int) **/ bool DkMagicCut::undoSelection() { if (label_history.empty()) { return false; } int region = label_history.back(); label_history.pop_back(); resetRegionMask(region); return !label_history.empty(); }
/** * The actual magic wand function performing an OpenCV flood filling starting from a seed point * @param xy The seed point within the image * @returns false, if the selected area is too big - otherwise true * \sa DkMagicCut::calculateContours() **/ bool DkMagicCut::magicwand(QPoint xy) { //Rect bRect; int area; int connectivity = 8; int flags = connectivity + (label_it << 8) + (CV_FLOODFILL_FIXED_RANGE | CV_FLOODFILL_MASK_ONLY); // get the color of the point //QColor col = imgStorage.getImage().pixel(xy); // The Flood Fill approach if (label_it < 255) label_it++; else label_it = 1; area = cv::floodFill(imgUC3, mask, cv::Point(xy.x(), xy.y()), label_it, 0 /*&bRect*/, cv::Scalar(tolerance, tolerance, tolerance), cv::Scalar(tolerance, tolerance, tolerance), flags); if(area >= maxSize) { // area is too big - reset the mask and give a message label_it--; resetRegionMask(label_it, false); return false; } else { label_history.push_back(label_it-1); calculateContours(); } return true; /* The RECURSIVE approach */ /*label_it++; seededRegionGrowing(xy.x(), xy.y(), col.redF()*255, col.greenF()*255, col.blueF()*255); // dilate the found blobs to receive better results cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); cv::dilate(mask, mask, element); calculateContours();*/ // DEBUG /*std::cout << "Region mask: " << std::endl; uchar *ptr; for (int i=0; i < mask.rows; i++) { for (int j=0; j <mask.cols; j++) { ptr = mask.data + mask.step * i; std::cout << (int)(ptr[j]) << " ; "; } std::cout << std::endl; }*/ }
/** * Resets the region mask according to the label at point xy * @param xy image point where to reset the area **/ void DkMagicCut::resetRegionMask(QPoint xy) { uchar *ptr; // mask is bigger, therefore x+1 and y+1 ptr = mask.data + mask.step * (xy.y()+1); int region = (int) (ptr[xy.x()+1]); if (region != 0) // find element in history vector and remove it int position = 0; for(std::vector<int>::size_type i = 0; i != label_history.size(); i++) { if (region == label_history[i]) { label_history.erase(label_history.begin() + i); break; } } resetRegionMask(region); }
/** * Sets the image for magic cut selection * @param img The image * @param imgMat Pointer to the corresponding Qt image matrix **/ void DkMagicCut::setImage(cv::Mat img, QTransform *imgMat) { qDebug() << "Image Channels: " << img.channels(); if (img.channels() <= 2) { // image does not have 3 channels (RGB) -> convert gray to RGB image cv::cvtColor(img, img, CV_GRAY2BGR); } // flood Fill function fails when having a 4 channel matrix - create 3 channel mat imgUC3.create(img.rows, img.cols, CV_8UC3); int from_to[] = { 0,0 , 1,1 , 2,2 }; cv::mixChannels(&img, 1, &imgUC3, 1, from_to, 3); mask.create(img.rows+2, img.cols+2, CV_8UC1); // reset the regions mask resetRegionMask(); imgMatrix = imgMat; maxSize = (int)(0.4 * img.rows * img.cols); }