void CirclesGridClusterFinder::hierarchicalClustering(const vector<Point2f> points, const Size &patternSize, vector<Point2f> &patternPoints)
{
- int i, j, n = (int)points.size();
- Mat dists(n, n, CV_32FC1, Scalar(0));
- Mat distsMask(dists.size(), CV_8UC1, Scalar(0));
- for(i = 0; i < n; i++)
- {
- for(j = i+1; j < n; j++)
+ int i, j, n = (int)points.size();
+ size_t pn = static_cast<size_t>(patternSize.area());
+
+ patternPoints.clear();
+ if (pn >= points.size())
{
- dists.at<float>(i, j) = (float)norm(points[i] - points[j]);
- distsMask.at<uchar>(i, j) = 255;
- //TODO: use symmetry
- distsMask.at<uchar>(j, i) = 255;//distsMask.at<uchar>(i, j);
- dists.at<float>(j, i) = dists.at<float>(i, j);
+ if (pn == points.size())
+ patternPoints = points;
+ return;
}
- }
- vector<std::list<size_t> > clusters(points.size());
- for(size_t i=0; i<points.size(); i++)
- {
- clusters[i].push_back(i);
- }
+ Mat dists(n, n, CV_32FC1, Scalar(0));
+ Mat distsMask(dists.size(), CV_8UC1, Scalar(0));
+ for(i = 0; i < n; i++)
+ {
+ for(j = i+1; j < n; j++)
+ {
+ dists.at<float>(i, j) = (float)norm(points[i] - points[j]);
+ distsMask.at<uchar>(i, j) = 255;
+ //TODO: use symmetry
+ distsMask.at<uchar>(j, i) = 255;//distsMask.at<uchar>(i, j);
+ dists.at<float>(j, i) = dists.at<float>(i, j);
+ }
+ }
- int patternClusterIdx = 0;
- while(clusters[patternClusterIdx].size() < static_cast<size_t>(patternSize.area()) && countNonZero(distsMask) > 0)
- {
- Point minLoc;
- minMaxLoc(dists, 0, 0, &minLoc, 0, distsMask);
- int minIdx = std::min(minLoc.x, minLoc.y);
- int maxIdx = std::max(minLoc.x, minLoc.y);
-
- distsMask.row(maxIdx).setTo(0);
- distsMask.col(maxIdx).setTo(0);
- Mat newDists = cv::min(dists.row(minLoc.x), dists.row(minLoc.y));
- Mat tmpLine = dists.row(minIdx);
- newDists.copyTo(tmpLine);
- tmpLine = dists.col(minIdx);
- newDists.copyTo(tmpLine);
-
- clusters[minIdx].splice(clusters[minIdx].end(), clusters[maxIdx]);
- patternClusterIdx = minIdx;
- }
+ vector<std::list<size_t> > clusters(points.size());
+ for(size_t i=0; i<points.size(); i++)
+ {
+ clusters[i].push_back(i);
+ }
- patternPoints.clear();
+ int patternClusterIdx = 0;
+ while(clusters[patternClusterIdx].size() < pn)
+ {
+ Point minLoc;
+ minMaxLoc(dists, 0, 0, &minLoc, 0, distsMask);
+ int minIdx = std::min(minLoc.x, minLoc.y);
+ int maxIdx = std::max(minLoc.x, minLoc.y);
+
+ distsMask.row(maxIdx).setTo(0);
+ distsMask.col(maxIdx).setTo(0);
+ Mat tmpRow = dists.row(minIdx);
+ Mat tmpCol = dists.col(minIdx);
+ cv::min(dists.row(minLoc.x), dists.row(minLoc.y), tmpRow);
+ tmpRow.copyTo(tmpCol);
+
+ clusters[minIdx].splice(clusters[minIdx].end(), clusters[maxIdx]);
+ patternClusterIdx = minIdx;
+ }
- if(clusters[patternClusterIdx].size() != static_cast<size_t>(patternSize.area()))
- {
- return;
- }
- patternPoints.reserve(clusters[patternClusterIdx].size());
- for(std::list<size_t>::iterator it = clusters[patternClusterIdx].begin(); it != clusters[patternClusterIdx].end(); it++)
- {
- patternPoints.push_back(points[*it]);
- }
+ patternPoints.reserve(clusters[patternClusterIdx].size());
+ for(std::list<size_t>::iterator it = clusters[patternClusterIdx].begin(); it != clusters[patternClusterIdx].end(); it++)
+ {
+ patternPoints.push_back(points[*it]);
+ }
}
void CirclesGridClusterFinder::findGrid(const std::vector<cv::Point2f> points, cv::Size _patternSize, vector<Point2f>& centers)