给定数据中存在圆弧,是离散坐标,已知半径,拟合圆求圆心。

lcl8699 2012-12-06 11:07:30
给定数据中存在圆弧,是离散坐标,已知半径,拟合圆求圆心。之前是没有半径限制,用最小二乘法拟合得到圆心和半径的,现在加上半径的限制,不知道该怎么做了。
...全文
1123 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
gududeyhc 2013-06-15
  • 打赏
  • 举报
回复
SelfDistance和SelfConstructCircle需要包含什么头文件啊?
  • 打赏
  • 举报
回复
半径已知:207
  • 打赏
  • 举报
回复


void test()
{
Mat src = imread("./2.jpg", 1);
Mat binary;
cvtColor(src, binary, CV_BGR2GRAY);
for (int row = 0; row < src.rows; row++)
{
uchar* p = binary.ptr<uchar>(row);
for (int col = 0; col < src.cols; col++)
{
if (p[col] > 100)
{
p[col] = 255;
}
else
{
p[col] = 0;
}
}
}
double max_y = 0.0;
for (int row = 0; row < src.rows; row++)
{
uchar* p = binary.ptr<uchar>(row);
if (p[src.cols / 2] > 100)
{
max_y = row;
}
}
Point2d bottom(src.cols/2, max_y);
circle(src, bottom, 8, CV_RGB(255,0,0), -1);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours( binary, contours, hierarchy,
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );
int maxcontour = 0;
double maxarea = 0.0;
for(unsigned int idx = 0; idx < contours.size(); idx++)
{
double area_contour = contourArea(contours.at(idx));
if (area_contour > maxarea)
{
maxcontour = idx;
maxarea = area_contour;
}
}
vector<Point>::iterator iter = contours.at(maxcontour).begin();
vector<Point> r_pts;
vector<Point> g_pts;
while (iter != contours.at(maxcontour).end())
{
if (iter->y > src.rows/2)
{
circle(src, *iter, 1, CV_RGB(0,255,0), -1);
g_pts.push_back(*iter);
}
else
{
circle(src, *iter, 1, CV_RGB(255,0,0), -1);
r_pts.push_back(*iter);
}
iter++;
}
Point2d center;
const double std_r = 208;
double r;
Point2d pt1, pt2, pt3;
#if 0
pt1 = *r_pts.begin();
pt2 = *(r_pts.begin() + 10);
pt3 = *(r_pts.begin() + 200);
ConstructCircle(pt1, pt2, pt3, center, r);
circle(src, center, 3, CV_RGB(0,0,255), -1);
circle(src, center, r, CV_RGB(0,180,0), 1);
circle(src, pt1, 2, CV_RGB(0,0,255), -1);
circle(src, pt2, 2, CV_RGB(0,0,255), -1);
circle(src, pt3, 2, CV_RGB(0,0,255), -1);
stringstream r__char;
r__char.str("");
r__char << r;
putText(src, r__char.str().c_str(), center, FONT_HERSHEY_SIMPLEX, 1.0, CV_RGB(255,0,0), 2);
putText(src, "std_r:208", Point2i(center.x, center.y + 50), FONT_HERSHEY_SIMPLEX, 1.0, CV_RGB(255,0,0), 2);
imwrite("./result.jpg", src);
return;
#endif

int rand_1 = rand() % (r_pts.size() - 1);
int rand_2 = rand() % (r_pts.size() - 1);
int rand_3 = rand() % (r_pts.size() - 1);
pt1 = *(r_pts.begin() + rand_1);
pt2 = *(r_pts.begin() + rand_2);
pt3 = *(r_pts.begin() + rand_3);
double dis_12 = SelfDistance(pt1, pt2);
double dis_23 = SelfDistance(pt2, pt3);
const double cir_l = 2 * 3.14159 * std_r;
int valid_pts = 0;
vector<Point2d> cir_center;
Mat src_clone;
src.copyTo(src_clone);
while (1)
{
while (dis_12 < 0.05 * cir_l || dis_23 < 0.05 * cir_l)
{
rand_1 = rand() % (r_pts.size() - 1);
rand_2 = rand() % (r_pts.size() - 1);
rand_3 = rand() % (r_pts.size() - 1);
pt1 = *(r_pts.begin() + rand_1);
pt2 = *(r_pts.begin() + rand_2);
pt3 = *(r_pts.begin() + rand_3);
dis_12 = SelfDistance(pt1, pt2);
dis_23 = SelfDistance(pt2, pt3);
}
SelfConstructCircle(pt1, pt2, pt3, center, r);
if (fabs(r - std_r) < 0.1 && fabs(center.x - 400) < 5)
{
cir_center.push_back(center);
circle(src_clone, center, r, CV_RGB(0,180,0), 1);
circle(src_clone, center, r, CV_RGB(0,180,0), 1);
circle(src_clone, pt1, 2, CV_RGB(255,0,0), -1);
circle(src_clone, pt2, 2, CV_RGB(0,255,0), -1);
circle(src_clone, pt3, 2, CV_RGB(0,0,255), -1);
valid_pts++;
}
if (valid_pts > 50)
{
break;
}
rand_1 = rand() % r_pts.size();
rand_2 = rand() % r_pts.size();
rand_3 = rand() % r_pts.size();
pt1 = *(r_pts.begin() + rand_1);
pt2 = *(r_pts.begin() + rand_2);
pt3 = *(r_pts.begin() + rand_3);
dis_12 = SelfDistance(pt1, pt2);
dis_23 = SelfDistance(pt2, pt3);
}
imwrite("./result_all.jpg", src_clone);
vector<Point2d>::iterator cir_center_iter = cir_center.begin();
double max_dis = 0.0;
Point2d end_center;
while (cir_center_iter != cir_center.end())
{
if (bottom.y - cir_center_iter->y > max_dis)
{
max_dis = SelfDistance(bottom, *cir_center_iter);
end_center = *cir_center_iter;
}
cir_center_iter++;
}
circle(src, end_center, 3, CV_RGB(0,180,0), -1);
circle(src, end_center, r, CV_RGB(0,180,0), 1);
stringstream r_char;
r_char.str("");
r_char << r;
putText(src, r_char.str().c_str(), end_center, FONT_HERSHEY_SIMPLEX, 1.0, CV_RGB(255,0,0), 2);
putText(src, "std_r:207", Point2i(end_center.x, end_center.y + 50), FONT_HERSHEY_SIMPLEX, 1.0, CV_RGB(255,0,0), 2);
imwrite("./result.jpg", src);
}
  • 打赏
  • 举报
回复
RANSAC思想差不多可以做吧
andyboliu 2012-12-22
  • 打赏
  • 举报
回复
把圆弧上的点坐标依次进行Hough圆检测统计,统计后,会得到圆心坐标的
zhoujk 2012-12-18
  • 打赏
  • 举报
回复
任何三个不共线的点,就可以定义一个圆。如果你的给定数据全是一个圆上的点,随便找三个就可以计算出圆。 圆的定义应该是圆点坐标加半径或直径。如果这个已知半径和求出来的数据不对,以哪个为准?没有搞懂这个内容。
libralibra 2012-12-11
  • 打赏
  • 举报
回复
引用 3 楼 lcl8699 的回复:
引用 2 楼 libralibra 的回复:设有一系列点Pi = {P0,P1,P2,...Pn-1}是n个数据点,已知半径为r,求圆心O 用hough变换的思想,既然数据点中肯定存在圆弧,半径又已知, 分别以给定点为圆心,r为半径画圆,求出这些圆通过次数最多的那个点就是,你可以设置一个tolerance来判定只要在容差之内就认为通过了同一个点来提高效率. 本来ho……
貌似只有计算所有的点才行
lcl8699 2012-12-07
  • 打赏
  • 举报
回复
引用 2 楼 libralibra 的回复:
设有一系列点Pi = {P0,P1,P2,...Pn-1}是n个数据点,已知半径为r,求圆心O 用hough变换的思想,既然数据点中肯定存在圆弧,半径又已知, 分别以给定点为圆心,r为半径画圆,求出这些圆通过次数最多的那个点就是,你可以设置一个tolerance来判定只要在容差之内就认为通过了同一个点来提高效率. 本来hough变换检测圆在投票阶段需要遍历其中两个,……
给定点为圆心,r为半径画圆,设置一个tolerance,是不是要计算一系列点到所画圆心的距离与半径的差值是否小于tolerance?这样每换一个圆心,就要重新计算一遍,会不会运行很慢?差不多有2千个点。。。
libralibra 2012-12-06
  • 打赏
  • 举报
回复
设有一系列点Pi = {P0,P1,P2,...Pn-1}是n个数据点,已知半径为r,求圆心O 用hough变换的思想,既然数据点中肯定存在圆弧,半径又已知, 分别以给定点为圆心,r为半径画圆,求出这些圆通过次数最多的那个点就是,你可以设置一个tolerance来判定只要在容差之内就认为通过了同一个点来提高效率. 本来hough变换检测圆在投票阶段需要遍历其中两个,搜索峰值在三维参数空间进行.不过你的这个问题半径已知,等于是在三维空间的一个r平面内搜索,参数又退化为2个,很简单的.
lcl8699 2012-12-06
  • 打赏
  • 举报
回复
自己顶一下\(^o^)/~

4,445

社区成员

发帖
与我相关
我的任务
社区描述
图形图像/机器视觉
社区管理员
  • 机器视觉
  • 迪菲赫尔曼
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧