项目记录-处理两个相交圆方法探索3

问题:
原图中存在两个部分重叠的圆,多余的圆会影响边缘提取的正确度,所以需要从边缘中去掉另一个交叠圆上的点。
方法:
使用之前的方法删除错误的边缘点之后,余下的点中还存在偏离的点需要进一步修正。
由于边界的起点不一定正确,所以先遍历边界点,找出离中心最近的点,从该点出发来查找待
修正的点。
判断是否需要修正的条件:
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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值