图像中搜索圆(特别是残缺的圆)

 类似于下面的图像,寻找残缺的圆,用hough变换的话,反正我是搞不出来,自己写了一个,已知圆的大概半径,在图像上面遍历,对遍历的结果打分,分数最高的就是搜寻的圆,将对应的轮廓点拟合圆,即可求得

图像中搜索圆(特别是残缺的圆)_第1张图片

 以下是代码,亲自试了,可用:

#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

下面就是提取的效果 

图像中搜索圆(特别是残缺的圆)_第2张图片

你可能感兴趣的:(Algorithm)