mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
Merge pull request #21942 from pglotov:add-blob-contours
added blob contours to blob detector * added blob contours * Fixed Java regression test after new parameter addition to SimpleBlobDetector. * Added stub implementation of SimpleBlobDetector::getBlobContours to presume source API compatibility.
This commit is contained in:
@@ -56,6 +56,12 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
// TODO: To be removed in 5.x branch
|
||||
const std::vector<std::vector<cv::Point> >& SimpleBlobDetector::getBlobContours() const
|
||||
{
|
||||
CV_Error(Error::StsNotImplemented, "Method SimpleBlobDetector::getBlobContours() is not implemented");
|
||||
}
|
||||
|
||||
class CV_EXPORTS_W SimpleBlobDetectorImpl : public SimpleBlobDetector
|
||||
{
|
||||
public:
|
||||
@@ -74,9 +80,12 @@ protected:
|
||||
};
|
||||
|
||||
virtual void detect( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) CV_OVERRIDE;
|
||||
virtual void findBlobs(InputArray image, InputArray binaryImage, std::vector<Center> ¢ers) const;
|
||||
virtual void findBlobs(InputArray image, InputArray binaryImage, std::vector<Center> ¢ers,
|
||||
std::vector<std::vector<Point> > &contours, std::vector<Moments> &moments) const;
|
||||
virtual const std::vector<std::vector<Point> >& getBlobContours() const CV_OVERRIDE;
|
||||
|
||||
Params params;
|
||||
std::vector<std::vector<Point> > blobContours;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -110,6 +119,8 @@ SimpleBlobDetector::Params::Params()
|
||||
//minConvexity = 0.8;
|
||||
minConvexity = 0.95f;
|
||||
maxConvexity = std::numeric_limits<float>::max();
|
||||
|
||||
collectContours = false;
|
||||
}
|
||||
|
||||
void SimpleBlobDetector::Params::read(const cv::FileNode& fn )
|
||||
@@ -139,6 +150,8 @@ void SimpleBlobDetector::Params::read(const cv::FileNode& fn )
|
||||
filterByConvexity = (int)fn["filterByConvexity"] != 0 ? true : false;
|
||||
minConvexity = fn["minConvexity"];
|
||||
maxConvexity = fn["maxConvexity"];
|
||||
|
||||
collectContours = (int)fn["collectContours"] != 0 ? true : false;
|
||||
}
|
||||
|
||||
void SimpleBlobDetector::Params::write(cv::FileStorage& fs) const
|
||||
@@ -168,6 +181,8 @@ void SimpleBlobDetector::Params::write(cv::FileStorage& fs) const
|
||||
fs << "filterByConvexity" << (int)filterByConvexity;
|
||||
fs << "minConvexity" << minConvexity;
|
||||
fs << "maxConvexity" << maxConvexity;
|
||||
|
||||
fs << "collectContours" << (int)collectContours;
|
||||
}
|
||||
|
||||
SimpleBlobDetectorImpl::SimpleBlobDetectorImpl(const SimpleBlobDetector::Params ¶meters) :
|
||||
@@ -186,13 +201,16 @@ void SimpleBlobDetectorImpl::write( cv::FileStorage& fs ) const
|
||||
params.write(fs);
|
||||
}
|
||||
|
||||
void SimpleBlobDetectorImpl::findBlobs(InputArray _image, InputArray _binaryImage, std::vector<Center> ¢ers) const
|
||||
void SimpleBlobDetectorImpl::findBlobs(InputArray _image, InputArray _binaryImage, std::vector<Center> ¢ers,
|
||||
std::vector<std::vector<Point> > &contoursOut, std::vector<Moments> &momentss) const
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat image = _image.getMat(), binaryImage = _binaryImage.getMat();
|
||||
CV_UNUSED(image);
|
||||
centers.clear();
|
||||
contoursOut.clear();
|
||||
momentss.clear();
|
||||
|
||||
std::vector < std::vector<Point> > contours;
|
||||
findContours(binaryImage, contours, RETR_LIST, CHAIN_APPROX_NONE);
|
||||
@@ -291,7 +309,11 @@ void SimpleBlobDetectorImpl::findBlobs(InputArray _image, InputArray _binaryImag
|
||||
}
|
||||
|
||||
centers.push_back(center);
|
||||
|
||||
if (params.collectContours)
|
||||
{
|
||||
contoursOut.push_back(contours[contourIdx]);
|
||||
momentss.push_back(moms);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BLOB_DETECTOR
|
||||
circle( keypointsImage, center.location, 1, Scalar(0,0,255), 1 );
|
||||
@@ -308,6 +330,8 @@ void SimpleBlobDetectorImpl::detect(InputArray image, std::vector<cv::KeyPoint>&
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
keypoints.clear();
|
||||
blobContours.clear();
|
||||
|
||||
CV_Assert(params.minRepeatability != 0);
|
||||
Mat grayscaleImage;
|
||||
if (image.channels() == 3 || image.channels() == 4)
|
||||
@@ -333,14 +357,19 @@ void SimpleBlobDetectorImpl::detect(InputArray image, std::vector<cv::KeyPoint>&
|
||||
}
|
||||
|
||||
std::vector < std::vector<Center> > centers;
|
||||
std::vector<Moments> momentss;
|
||||
for (double thresh = params.minThreshold; thresh < params.maxThreshold; thresh += params.thresholdStep)
|
||||
{
|
||||
Mat binarizedImage;
|
||||
threshold(grayscaleImage, binarizedImage, thresh, 255, THRESH_BINARY);
|
||||
|
||||
std::vector < Center > curCenters;
|
||||
findBlobs(grayscaleImage, binarizedImage, curCenters);
|
||||
std::vector<std::vector<Point> > curContours;
|
||||
std::vector<Moments> curMomentss;
|
||||
findBlobs(grayscaleImage, binarizedImage, curCenters, curContours, curMomentss);
|
||||
std::vector < std::vector<Center> > newCenters;
|
||||
std::vector<std::vector<Point> > newContours;
|
||||
std::vector<Moments> newMomentss;
|
||||
for (size_t i = 0; i < curCenters.size(); i++)
|
||||
{
|
||||
bool isNew = true;
|
||||
@@ -358,15 +387,37 @@ void SimpleBlobDetectorImpl::detect(InputArray image, std::vector<cv::KeyPoint>&
|
||||
centers[j][k] = centers[j][k-1];
|
||||
k--;
|
||||
}
|
||||
|
||||
if (params.collectContours)
|
||||
{
|
||||
if (curCenters[i].confidence > centers[j][k].confidence
|
||||
|| (curCenters[i].confidence == centers[j][k].confidence && curMomentss[i].m00 > momentss[j].m00))
|
||||
{
|
||||
blobContours[j] = curContours[i];
|
||||
momentss[j] = curMomentss[i];
|
||||
}
|
||||
}
|
||||
centers[j][k] = curCenters[i];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isNew)
|
||||
{
|
||||
newCenters.push_back(std::vector<Center> (1, curCenters[i]));
|
||||
if (params.collectContours)
|
||||
{
|
||||
newContours.push_back(curContours[i]);
|
||||
newMomentss.push_back(curMomentss[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::copy(newCenters.begin(), newCenters.end(), std::back_inserter(centers));
|
||||
if (params.collectContours)
|
||||
{
|
||||
std::copy(newContours.begin(), newContours.end(), std::back_inserter(blobContours));
|
||||
std::copy(newMomentss.begin(), newMomentss.end(), std::back_inserter(momentss));
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < centers.size(); i++)
|
||||
@@ -387,10 +438,21 @@ void SimpleBlobDetectorImpl::detect(InputArray image, std::vector<cv::KeyPoint>&
|
||||
|
||||
if (!mask.empty())
|
||||
{
|
||||
KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat());
|
||||
if (params.collectContours)
|
||||
{
|
||||
KeyPointsFilter::runByPixelsMask2VectorPoint(keypoints, blobContours, mask.getMat());
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<std::vector<Point> >& SimpleBlobDetectorImpl::getBlobContours() const {
|
||||
return blobContours;
|
||||
}
|
||||
|
||||
Ptr<SimpleBlobDetector> SimpleBlobDetector::create(const SimpleBlobDetector::Params& params)
|
||||
{
|
||||
return makePtr<SimpleBlobDetectorImpl>(params);
|
||||
|
||||
Reference in New Issue
Block a user