我正在尝试检测图像中的相邻圆圈。这些可以是 4 或 5。有没有办法在 opencv 中检测它。我尝试了很多方法,包括霍夫圆法。但我也检测到额外的圆圈。如果在任何情况下我能够检测到圆圈,那么相同的参数将不适用于其他图像。
请告诉我任何可能实现这一目标的事情。
我使用霍夫圆的代码是:
Mat img, gray;
img = imread("/Users/Development/Desktop/Images/IMG_0297.jpg");
cvtColor(img, gray, CV_BGR2GRAY);
// smooth it, otherwise a lot of false circles may be detected
GaussianBlur( gray, gray, Size(9, 9), 2, 2 );
vector<Vec3f> circles;
HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2, gray.rows/16,80,100,30,50 );
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the circle center
circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 );
// draw the circle outline
circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
namedWindow( "circles", 1 );
imshow( "circles", img );
waitKey(0);
return 0;
我想检测其中彼此相邻的刻度盘
最佳答案
您可以使用partition将相邻圆的圆聚类,即中心距离与其半径的 sim 相似的圆。您只需定义适当的等价谓词,此处在CirclesOnSameLine
中实现。您最终可以改进此谓词,仅将具有相似半径的圆视为相等。
此聚类的结果类似于(相同颜色表示相同的聚类):
通过这种方法,您可以安全地检测某些圆,因为您可以删除不属于超过 4-5 个圆的簇的圆。
代码:
#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
struct CirclesOnSameLine
{
float _tolerance;
CirclesOnSameLine(float tolerance) : _tolerance(tolerance) {};
bool operator()(const Vec3f& lhs, const Vec3f& rhs)
{
// [0] = x
// [1] = y
// [2] = radius
float center_distance = sqrt((lhs[0] - rhs[0])*(lhs[0] - rhs[0]) + (lhs[1] - rhs[1])*(lhs[1] - rhs[1]));
float sum_radii = lhs[2] + rhs[2];
if (sum_radii > center_distance)
{
return (sum_radii / center_distance) < _tolerance;
}
return (center_distance / sum_radii) < _tolerance;
}
};
int main()
{
Mat3b img = imread("path_to_image");
Mat1b gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, gray, Size(9, 9), 2, 2);
vector<Vec3f> circles;
HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2, gray.rows / 16, 80, 100, 10, 100);
// Cluster circles near each other
vector<int> labels;
int n_labels = partition(circles, labels, CirclesOnSameLine(1.1f));
vector<Scalar> colors;
for (int i = 0; i < n_labels; ++i)
{
Scalar color(rand() & 255, rand() & 255, rand() & 255);
colors.push_back(color);
}
Mat3b adjacent = img.clone();
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the circle outline
circle(adjacent, center, radius, colors[labels[i]], 3, 8, 0);
}
// Remove small clusters
vector<int> count(labels.size(), 0);
for (size_t i = 0; i < labels.size(); ++i)
{
count[labels[i]]++;
}
Mat3b big_clusters = img.clone();
for (size_t i = 0; i < circles.size(); i++)
{
if (count[labels[i]] < 4) continue;
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the circle outline
circle(big_clusters, center, radius, Scalar(0, 0, 255), 3, 8, 0);
}
imshow("Adjacent circles", adjacent);
imshow("Adjacent circles", big_clusters);
waitKey();
return 0;
}
关于c++ - 有没有办法使用opencv检测图像中的相邻圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36154312/