From: Ilya Lysenkov Date: Thu, 9 Jun 2011 11:07:08 +0000 (+0000) Subject: Simplified SimpleBlobDetector to make it simple) X-Git-Tag: accepted/tizen/6.0/unified/20201030.111113~7057 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f60d7fdfef53d428bc00f7a3746429c832596dac;p=platform%2Fupstream%2Fopencv.git Simplified SimpleBlobDetector to make it simple) --- diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index 50626e5..7783891 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -1566,20 +1566,23 @@ public: float thresholdStep; float minThreshold; float maxThreshold; - float maxCentersDist; - int defaultKeypointSize; size_t minRepeatability; - bool computeRadius; - bool isGrayscaleCentroid; - int centroidROIMargin; - - bool filterByArea, filterByInertia, filterByCircularity, filterByColor, filterByConvexity; - float minArea; - float maxArea; - float minCircularity; - float minInertiaRatio; - float minConvexity; + float minDistBetweenBlobs; + + bool filterByColor; uchar blobColor; + + bool filterByArea; + float minArea, maxArea; + + bool filterByCircularity; + float minCircularity, maxCircularity; + + bool filterByInertia; + float minInertiaRatio, maxInertiaRatio; + + bool filterByConvexity; + float minConvexity, maxConvexity; }; SimpleBlobDetector(const SimpleBlobDetector::Params ¶meters = SimpleBlobDetector::Params()); diff --git a/modules/features2d/src/blobdetector.cpp b/modules/features2d/src/blobdetector.cpp index d5ca39d..fce0a2b 100644 --- a/modules/features2d/src/blobdetector.cpp +++ b/modules/features2d/src/blobdetector.cpp @@ -59,30 +59,29 @@ SimpleBlobDetector::Params::Params() thresholdStep = 10; minThreshold = 50; maxThreshold = 220; - maxCentersDist = 10; - defaultKeypointSize = 1; minRepeatability = 2; - computeRadius = true; + minDistBetweenBlobs = 10; + filterByColor = true; blobColor = 0; - isGrayscaleCentroid = false; - centroidROIMargin = 2; - filterByArea = true; minArea = 25; maxArea = 5000; + filterByCircularity = false; + minCircularity = 0.8f; + maxCircularity = std::numeric_limits::max(); + filterByInertia = true; //minInertiaRatio = 0.6; minInertiaRatio = 0.1f; + maxInertiaRatio = std::numeric_limits::max(); filterByConvexity = true; //minConvexity = 0.8; minConvexity = 0.95f; - - filterByCircularity = false; - minCircularity = 0.8f; + maxConvexity = std::numeric_limits::max(); } SimpleBlobDetector::SimpleBlobDetector(const SimpleBlobDetector::Params ¶meters) : @@ -90,35 +89,6 @@ SimpleBlobDetector::SimpleBlobDetector(const SimpleBlobDetector::Params ¶met { } -Point2d SimpleBlobDetector::computeGrayscaleCentroid(const Mat &image, const vector &contour) const -{ - Rect rect = boundingRect(Mat(contour)); - rect.x -= params.centroidROIMargin; - rect.y -= params.centroidROIMargin; - rect.width += 2 * params.centroidROIMargin; - rect.height += 2 * params.centroidROIMargin; - - rect.x = rect.x < 0 ? 0 : rect.x; - rect.y = rect.y < 0 ? 0 : rect.y; - rect.width = rect.x + rect.width < image.cols ? rect.width : image.cols - rect.x; - rect.height = rect.y + rect.height < image.rows ? rect.height : image.rows - rect.y; - - Mat roi = image(rect); - assert( roi.type() == CV_8UC1 ); - - Mat invRoi = 255 - roi; - invRoi.convertTo(invRoi, CV_32FC1); - invRoi = invRoi.mul(invRoi); - - Moments moms = moments(invRoi); - - Point2d tl = rect.tl(); - Point2d roiCentroid(moms.m10 / moms.m00, moms.m01 / moms.m00); - - Point2d centroid = tl + roiCentroid; - return centroid; -} - void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryImage, vector
¢ers) const { centers.clear(); @@ -128,13 +98,13 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm findContours(tmpBinaryImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); #ifdef DEBUG_BLOB_DETECTOR - Mat keypointsImage; - cvtColor( binaryImage, keypointsImage, CV_GRAY2RGB ); - - Mat contoursImage; - cvtColor( binaryImage, contoursImage, CV_GRAY2RGB ); - drawContours( contoursImage, contours, -1, Scalar(0,255,0) ); - imshow("contours", contoursImage ); +// Mat keypointsImage; +// cvtColor( binaryImage, keypointsImage, CV_GRAY2RGB ); +// +// Mat contoursImage; +// cvtColor( binaryImage, contoursImage, CV_GRAY2RGB ); +// drawContours( contoursImage, contours, -1, Scalar(0,255,0) ); +// imshow("contours", contoursImage ); #endif for (size_t contourIdx = 0; contourIdx < contours.size(); contourIdx++) @@ -145,7 +115,7 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm if (params.filterByArea) { double area = moms.m00; - if (area < params.minArea || area > params.maxArea) + if (area < params.minArea || area >= params.maxArea) continue; } @@ -154,7 +124,7 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm double area = moms.m00; double perimeter = arcLength(Mat(contours[contourIdx]), true); double ratio = 4 * CV_PI * area / (perimeter * perimeter); - if (ratio < params.minCircularity) + if (ratio < params.minCircularity || ratio >= params.maxCircularity) continue; } @@ -179,7 +149,7 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm ratio = 1; } - if (ratio < params.minInertiaRatio) + if (ratio < params.minInertiaRatio || ratio >= params.maxInertiaRatio) continue; center.confidence = ratio * ratio; @@ -192,14 +162,11 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm double area = contourArea(Mat(contours[contourIdx])); double hullArea = contourArea(Mat(hull)); double ratio = area / hullArea; - if (ratio < params.minConvexity) + if (ratio < params.minConvexity || ratio >= params.maxConvexity) continue; } - if (params.isGrayscaleCentroid) - center.location = computeGrayscaleCentroid(image, contours[contourIdx]); - else - center.location = Point2d(moms.m10 / moms.m00, moms.m01 / moms.m00); + center.location = Point2d(moms.m10 / moms.m00, moms.m01 / moms.m00); if (params.filterByColor) { @@ -207,7 +174,7 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm continue; } - if (params.computeRadius) + //compute blob radius { vector dists; for (size_t pointIdx = 0; pointIdx < contours[contourIdx].size(); pointIdx++) @@ -222,12 +189,12 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm centers.push_back(center); #ifdef DEBUG_BLOB_DETECTOR - circle( keypointsImage, center.location, 1, Scalar(0,0,255), 1 ); +// circle( keypointsImage, center.location, 1, Scalar(0,0,255), 1 ); #endif } #ifdef DEBUG_BLOB_DETECTOR - imshow("bk", keypointsImage ); - waitKey(); +// imshow("bk", keypointsImage ); +// waitKey(); #endif } @@ -247,31 +214,37 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector curCenters; findBlobs(grayscaleImage, binarizedImage, curCenters); vector < vector
> newCenters; for (size_t i = 0; i < curCenters.size(); i++) { - //circle(keypointsImage, curCenters[i].location, 1, Scalar(0,0,255),-1); +#ifdef DEBUG_BLOB_DETECTOR +// circle(keypointsImage, curCenters[i].location, curCenters[i].radius, Scalar(0,0,255),-1); +#endif bool isNew = true; for (size_t j = 0; j < centers.size(); j++) { double dist = norm(centers[j][0].location - curCenters[i].location); - if (params.computeRadius) - isNew = dist >= centers[j][0].radius && dist >= curCenters[i].radius && dist >= params.maxCentersDist; - else - isNew = dist >= params.maxCentersDist; + isNew = dist >= params.minDistBetweenBlobs && dist >= centers[j][ centers[j].size() / 2 ].radius && dist >= curCenters[i].radius; if (!isNew) { centers[j].push_back(curCenters[i]); - // if( centers[j][0].radius < centers[j][ centers[j].size()-1 ].radius ) - // { - // std::swap( centers[j][0], centers[j][ centers[j].size()-1 ] ); - // } + + size_t k = centers[j].size() - 1; + while( k > 0 && centers[j][k].radius < centers[j][k-1].radius ) + { + centers[j][k] = centers[j][k-1]; + k--; + } + centers[j][k] = curCenters[i]; + break; } } @@ -283,8 +256,10 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector