类似于下面的图像,寻找残缺的圆,用hough变换的话,反正我是搞不出来,自己写了一个,已知圆的大概半径,在图像上面遍历,对遍历的结果打分,分数最高的就是搜寻的圆,将对应的轮廓点拟合圆,即可求得
以下是代码,亲自试了,可用:
#include
#include
#include
#include
using namespace std;
using namespace cv;
bool circleLeastFit(vector &points, double ¢er_x, double ¢er_y, double &radius)
{
center_x = 0.0f;
center_y = 0.0f;
radius = 0.0f;
if (points.size() < 3)
{
return false;
}
double sum_x = 0.0f, sum_y = 0.0f;
double sum_x2 = 0.0f, sum_y2 = 0.0f;
double sum_x3 = 0.0f, sum_y3 = 0.0f;
double sum_xy = 0.0f, sum_x1y2 = 0.0f, sum_x2y1 = 0.0f;
int N = points.size();
for (int i = 0; i < N; i++)
{
double x = points[i].x;
double y = points[i].y;
double x2 = x * x;
double y2 = y * y;
sum_x += x;
sum_y += y;
sum_x2 += x2;
sum_y2 += y2;
sum_x3 += x2 * x;
sum_y3 += y2 * y;
sum_xy += x * y;
sum_x1y2 += x * y2;
sum_x2y1 += x2 * y;
}
double C, D, E, G, H;
double a, b, c;
C = N * sum_x2 - sum_x * sum_x;
D = N * sum_xy - sum_x * sum_y;
E = N * sum_x3 + N * sum_x1y2 - (sum_x2 + sum_y2) * sum_x;
G = N * sum_y2 - sum_y * sum_y;
H = N * sum_x2y1 + N * sum_y3 - (sum_x2 + sum_y2) * sum_y;
a = (H * D - E * G) / (C * G - D * D);
b = (H * C - E * D) / (D * D - G * C);
c = -(a * sum_x + b * sum_y + sum_x2 + sum_y2) / N;
center_x = a / (-2);
center_y = b / (-2);
radius = sqrt(a * a + b * b - 4 * c) / 2;
return true;
}
void main()
{
//circle_src1:R=420,r=15
Mat img_src = imread("1.bmp"); //路径自己设定
int s_height = img_src.rows;
int s_width = img_src.cols;
Mat img_pro = img_src.clone();
vector planes;
split(img_pro, planes);
Mat img_gray = planes[0];
int radius = 420;
int change = 15;
Canny(img_gray, img_gray, 200, 180, 3);//视图像,可以自己决定
vector> contours;
vector hierarchy;
findContours(img_gray, contours, hierarchy, RETR_LIST, CHAIN_APPROX_NONE, Point());
int D = 2 * (radius + change) + 1;
int d = 2 * (radius - change) - 1;
int R = radius + change;
int r = radius - change;
Mat cir(D, D, CV_8UC1, Scalar(0));
circle(cir, Point(radius + change, radius + change), radius + change, Scalar(255), 1, 1, 0);
circle(cir, Point(radius + change, radius + change), radius, Scalar(255), 1, 1, 0);
vector p_cir(2 * (radius + change) + 1);
for (int i = 0; i < 2 * (radius + change) + 1; i++)
{
vector temp;
Vec4i current_v;
uchar* ptr0 = cir.ptr(i);
int inti0 = 0;
for (int j = 0; j p0;
for (int i = 0; i < contours.size(); i++)
{
for (int j = 0; j < contours[i].size(); j += 10)
{
p0.push_back(contours[i][j]);
}
}
Mat img_test1(s_height, s_width, CV_8UC1, Scalar(0));
for (int i = 0; i < p0.size(); i++)
{
img_test1.at(p0[i].y, p0[i].x) = 255;
}
//Mat img_test(D, D, CV_8UC1, Scalar(0));
//for (int i = 0; i < p_cir.size();i++)
//{
// Vec4f v0;
// v0 = p_cir[i];
// img_test.at(i,v0[0]) = 255;
// img_test.at(i,v0[1]) = 255;
// img_test.at(i,v0[2]) = 255;
// img_test.at(i,v0[3]) = 255;
//}
Point c0;
float r0;
int size_p0 = p0.size();
int max_score = 0;
Mat Score(s_height, s_width, CV_32F, Scalar(0));
Mat img_empty(s_height, s_width, CV_8UC1, Scalar(0));
Point p_current(0, 0);
vector p_good;
for (int i = R; i < s_height - R; i++)
{
float* ptr0 = Score.ptr(i);
for (int j = R; j < s_width - R; j++)
{
Rect rect(j - R, i - R, j + R, i + R);
rectangle(img_empty, rect, Scalar(255), 4, 1);
Point2i cd0(j - R, i - R);
int count = 0;
vector p_good_cur;
for (int c = 0; c < size_p0; c++)
{
//img_empty.at(p0[c].y, p0[c].x) = 255;
Point p1 = p0[c] - cd0;
if (p1.x >= 0 && p1.x= v0[0] && p1.y <= v0[1] || p1.y >= v0[2] && p1.y <= v0[3])
{
img_empty.at(p0[c].y, p0[c].x) = 255;
p_current = p0[c];
p_good_cur.push_back(p0[c]); //最优点集合
count++;
}
}
}
ptr0[j] = count;
if (max_score());
p_good.swap(p_good_cur);
max_score = count;
c0.x = j;
c0.y = i;
r0 = sqrt(pow(p_current.x - j, 2) + pow(p_current.y - i, 2));
}
circle(img_empty, Point(j, i), R, Scalar(255), 1, 3);
circle(img_empty, Point(j, i), r, Scalar(255), 1, 3);
img_empty = Mat::zeros(s_height, s_width, 0);
}
}
double centre_x0, centre_y0, radius0;
circleLeastFit(p_good, centre_x0, centre_y0, radius0);
r0 = radius0;
c0.x = centre_x0, c0.y = centre_y0;
normalize(Score, Score, 0, 255, NORM_MINMAX, CV_32F, Mat());
convertScaleAbs(Score, Score);
circle(img_gray, c0, r0, Scalar(255), 1, 1);
circle(img_gray, c0, R, Scalar(100), 1, 5);
circle(img_gray, c0, r, Scalar(100), 1, 5);
vector planes1;
Mat img_result;
planes1.push_back(img_empty);
planes1.push_back(planes[0]);
planes1.push_back(img_empty);
merge(planes1, img_result);
circle(img_pro, c0, r0, Scalar(0, 0, 255), 1, 1);
circle(img_pro, c0, R, Scalar(255, 0, 0), 1, 1);
circle(img_pro, c0, r, Scalar(255, 0, 0), 1, 1);
imwrite("img_result.bmp", img_result);
}
//测试了几组数据,还可以,有BUG的话,QQ:1920628443
下面就是提取的效果