项目记录-处理两个相交圆方法探索3
来源:互联网 发布:e盾网络验证价格 编辑:程序博客网 时间:2024/04/29 13:57
问题:
原图中存在两个部分重叠的圆,多余的圆会影响边缘提取的正确度,所以需要从边缘中去掉另一个交叠圆上的点。
方法:
使用之前的方法删除错误的边缘点之后,余下的点中还存在偏离的点需要进一步修正。
由于边界的起点不一定正确,所以先遍历边界点,找出离中心最近的点,从该点出发来查找待
修正的点。
判断是否需要修正的条件:
1)如果当前点和前面一个点相距太大,则当前点需要向中心点平移一段距离才行
2)如果当前点和前一个点相距偏大,且当前点、前一点、中心点三点形成的角度是钝角,则认为
当前点严重偏离中心点,需要作进一步修正。
修正的方法也依照上述两种情况分开处理:
1)如果当前点和前面点的距离太大,则前一点无法作为当前点的参考点,
考虑从中心点出发,向当前点方 向移动,找到最后一个掩膜标记的点作为替换点;
2)否则,直接参考前面点和中心点的距离dis,将当前点向中心点方向移动,
当距离中心点小于等于dis 时,则认为可以停止移动了。
为了加快修正的速度,对于需要修正的一段圆弧,弧上的每个点的移动步数都参考圆弧起点的
移动步数,而不用每个点都使用上面的两个判断来结束移动。
最终的实践效果较好。
代码如下:
int beginid=0; vector<int>centerdis; int cx=centerx-vecResult[0].x; int cy=centery-vecResult[0].y; int cdis=cx*cx+cy*cy; centerdis.push_back(cdis); int dx,dy,dis; for(int i=1;i<size;i++) { cx=centerx-vecResult[i].x; cy=centery-vecResult[i].y; cdis=cx*cx+cy*cy; centerdis.push_back(cdis); if(cdis<centerdis[beginid]) beginid=i; } //最后一个点和起始点求距离 if(beginid==0){ centerdis.push_back(centerdis[0]); vecResult.push_back(vecResult[0]); } else{ centerdis.insert(centerdis.begin()+beginid,centerdis[beginid]); vecResult.insert(vecResult.begin()+beginid, vecResult[beginid]); } beginid++; queue<int>changeid; int newsize=size+1; for (int i = 1; i <= size; i++) { int cur=(beginid+i)%newsize; int prev=(cur+size)%newsize; //计算前后两点的距离 dx=vecResult[cur].x-vecResult[prev].x; dy=vecResult[cur].y-vecResult[prev].y; dis=dx*dx+dy*dy; //如果前后距离大于等于100,认为需要进行平移 if(dis>=200) { changeid.push(cur); } else if(dis>=100) { //再次判断前后两点与中心点的距离是否接近,如果相差不大,则认为可以接受 cx=vecResult[cur].x-centerx; cy=vecResult[cur].y-centery; cdis=cx*cx+cy*cy; cx=vecResult[prev].x-centerx; cy=vecResult[prev].y-centery; int cdis1=cx*cx+cy*cy; //如果前后两点与中心点的距离相差大于100,则需要进行平移 int abscdis=abs(cdis-cdis1); if(abscdis>=200) { changeid.push(cur); } else if(abscdis>100) { //以前一点为锚点,计算角度是否为钝角 int x1,y1; if(cur==beginid-1) { cx=centerx-vecResult[cur].x; cy=centery-vecResult[cur].y; x1=vecResult[prev].x-vecResult[cur].x; y1=vecResult[prev].y-vecResult[cur].y; } else { cx=centerx-vecResult[prev].x; cy=centery-vecResult[prev].y; x1=vecResult[cur].x-vecResult[prev].x; y1=vecResult[cur].y-vecResult[prev].y; } float cos=(cx*x1+cy*y1)/sqrt(1.0*(cx*cx+cy*cy)*(x1*x1+y1*y1)); if(cos<0.01)//为钝角 { changeid.push(cur); } } } } int step=MOVELEN; int changesize=changeid.size(); if(changesize==1) { int icur=changeid.front(); //反着,中心尝试向该点移动,第一次碰到 int i=1; int sx=centerx-vecResult[icur].x; int sy=centery-vecResult[icur].y; int maxmove=max(abs(sx),abs(sy)); if(sx!=0)sx=sx/abs(sx); if(sy!=0)sy=sy/abs(sy); int newx=centerx-sx; int newy=centery-sy; int pos=newy*sWidth+newx; while(pMaskBuf[pos] && i<=maxmove) { newx-=sx; newy-=sy; pos=newy*sWidth+newx; i++; } vecResult[icur].x=newx; vecResult[icur].y=newy; } else { while(!changeid.empty()) { int ibegin=changeid.front(); changeid.pop(); int iend=ibegin+1; if(!changeid.empty()) { int inext=changeid.front(); if((inext-ibegin)<size/2) { iend=inext; } } else break; step=MOVELEN; //要把<=换成!=,因为有可能起点的Id大于终点的id for(int icur=ibegin;icur!=iend;icur=(icur+1)%newsize) { //向中心点平移的单位位移stepx,stepy int sx=centerx-vecResult[icur].x; int sy=centery-vecResult[icur].y; int maxmove=max(abs(sx),abs(sy)); if(sx!=0)sx=sx/abs(sx); if(sy!=0)sy=sy/abs(sy); //计算前一个点距离中心点的距离 int iprev=(icur+size)%newsize; int dis1=centerdis[iprev]; //计算前后两点的初始距离 dx=vecResult[icur].x-vecResult[iprev].x; dy=vecResult[icur].y-vecResult[iprev].y; int dis0=dx*dx+dy*dy; bool isFar=false; if(dis0>=200) isFar=true; int newx,newy; if(step==MOVELEN) { //如果最开始的距离就大于200,认为相距太远,不做判断依据 //反着,中心尝试向该点移动,第一次碰到 if(isFar) { int i=1; newx=centerx-sx; newy=centery-sy; int pos=newy*sWidth+newx; // while(pMaskBuf[pos] && i<=maxmove) { newx-=sx; newy-=sy; pos=newy*sWidth+newx; i++; } step=maxmove-i; vecResult[icur].x=newx; vecResult[icur].y=newy; } else { newx=vecResult[icur].x + sx; newy=vecResult[icur].y + sy; while(step) { newx += sx; newy += sy; //重新计算和前一个点的距离,如果变得小于100了,则停止移动 dx=newx-vecResult[iprev].x; dy=newy-vecResult[iprev].y; dis=dx*dx+dy*dy; //计算到中心点的距离 cx=newx-centerx; cy=newy-centery; cdis=cx*cx+cy*cy; //如果最开始的距离就大于200,认为相距太远,不做判断依据 if((isFar && (centerdis[iprev]-cdis)<=100) || (!isFar && dis<=100 && (centerdis[iprev]-cdis)<=100)) { vecResult[icur].x = newx; vecResult[icur].y = newy; step=MOVELEN-step; break; } step--; } } } else { int i=step; newx=vecResult[icur].x + sx; newy=vecResult[icur].y + sy; while(i--) { newx += sx; newy += sy; } vecResult[icur].x = newx; vecResult[icur].y = newy; } } } } vecResult.erase(vecResult.begin()+beginid); out.close(); //再做一次凸包修正 vecResult = grahamScan(vecResult);
0 0
- 项目记录-处理两个相交圆方法探索3
- 项目记录-处理两个相交圆方法探索1
- 项目记录-处理两个相交圆方法探索2
- 项目记录-圆形边缘修正方法探索3
- 项目记录-圆形边缘修正方法探索1
- 项目记录-圆形边缘修正方法探索2
- 黑马程序员-两种方法做计算两个圆是否相交
- poj2546 求两个圆相交的面积
- 计算两个圆相交部分的面积
- java求两个圆相交坐标
- 判断两个矩形是否相交的4个方法
- 判断两个矩形是否相交的4个方法
- 检测两个三角形是否有重叠面积/相交的方法
- 两个单链表是否相交
- 两个矩形是否相交
- 判断两个线段相交
- 判断两个矩阵相交
- 两个单链表相交问题
- Android中标签TagLayout支持单选多选
- CentOS7最小安装之后安装xfce桌面
- Angular之控制器篇
- 罗斯基白话:TensorFlow+实战系列(四)变量管理
- 关于html 中div 填满另一个div
- 项目记录-处理两个相交圆方法探索3
- mysql 导入导出
- go单元测试进阶篇
- 线索二叉树的遍历与基本操作(史上最全)
- C++回炉(2)
- 史上最简单的 MySQL 教程(一)「数据库」
- 利用R语言编写量化投资策略
- Java IO一个简单问题
- EL(表达式语言)