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

问题:
原图中存在两个部分重叠的圆,多余的圆会影响边缘提取的正确度,所以需要从边缘中去掉另一个交叠圆上的点。
方法:
先使用边缘点计算出新的中心点的坐标B,保留相距中心点的最短距离radius。
如果中心点坐标A和B点的距离超过了radius,则认为当前图中存在两个相交的圆,需要对边
缘做进一步的处理。
依据中心点坐标A得到相对于B点的对称点A’即为交叠圆的圆心。
重新计算所有的边缘点距离新圆心A’的距离,如果该点距离A’比距离A更近,则认为该点在以
A’为圆心的圆形上,需要从边缘点集合中剔除掉该点。

#include<map>
#include<stack>
bool cvCircle(UCHAR *pContourMask, vector<Pt2D> & vecContour, int sWidth, int sHeight)
{
    int centerx=sWidth/2;
    int centery=sHeight/2;
    //先要依据边缘统计各个半径的数目,用map存储
    vector<int>distance;
    map<int,int>radius;
    int num=vecContour.size();
    int newx=0,newy=0;
    int mindis=sWidth*sWidth+sHeight*sHeight;
    for(int i=0;i<num;i++)
    {
        int diffx=vecContour[i].x-centerx;
        int diffy=vecContour[i].y-centery;
        int dis=diffx*diffx+diffy*diffy;
        distance.push_back(dis);
        if(dis<mindis)mindis=dis;
        //记录偏移的中心
        newx+=vecContour[i].x;
        newy+=vecContour[i].y;
        if(radius.find(dis)!=radius.end())
            radius[dis]++;
        else
            radius[dis]=1;
    }
    //计算整个边界的新的中心位置,和真正的中心位置的偏移量是否达到了最小半径
    newx /= num;
    newy /= num;
    int diffx = newx-centerx;
    int diffy = newy-centery;
    int dis = diffx*diffx+diffy*diffy;
    /*如果新的center与中心相距超过最小距离,
则认为存在第二个圆,否则直接退出不做处理*/
    if(dis<=mindis)  return false;
    //依据center计算另一个圆心
    int movx=newx+diffx;
    int movy=newy+diffy;
    //如果某个边缘点距离新圆心更近,则剔除掉此点
    stack<int>delPt;
    int label=0;
    vector<Pt2D>endpt;
    for(int i=0;i<num;i++)
    {
        int diffx=vecContour[i].x-movx;
        int diffy=vecContour[i].y-movy;
        int dis=diffx*diffx+diffy*diffy;
        if(dis<distance[i])
        {
            delPt.push(i);
            //如果Label==0,表示从边界起点开始,此处待改进
            if(label==0) printf("0需要移除\n");
            //如果等于1,表示此前是有带保留段的
            else if(label==1)
            {
                label=2;
                endpt.push_back(vecContour[i-1]);
            }
        }
        else
        {
            if(label==0)
            {
                label=1;
                if(i!=0)
                {
                    endpt.push_back(vecContour[i]);
                }
            }
            else if(label==2)
            {
                label=3;
                endpt.push_back(vecContour[i]);
            }
        }
    }
    while(!delPt.empty())
    {
        int i=delPt.top();
        delPt.pop();
        vecContour.erase(vecContour.begin()+i);
    }
    if(label==2)
    {//两个端点交换一下位置
        Pt2D temp=endpt[0];
        endpt[0]=endpt[1];
        endpt[1]=temp;
    }
    int insertindex=0;
    for(int i=0;i<vecContour.size();i++)
    {
        if(vecContour[i].x==endpt[0].x && vecContour[i].y==endpt[0].y)
            insertindex=i+1;
    }
    //三个点:endpt[0],{newx,newy},endpt[1]
    Pt2D newpt={newx,newy};
    endpt.insert(endpt.begin()+1,newpt);
    //三个点确定一段弧
    Pt2D temp=endpt[0];
    vector<Pt2D>insertpt;
    for(int j=0;j<2;j++)
    {
        temp.x=endpt[j].x;temp.y=endpt[j].y;
        diffx=endpt[j+1].x-endpt[j].x;
        diffy=endpt[j+1].y-endpt[j].y;
        int absx=0;
        int absy=0;
        if(diffx!=0)absx=diffx/abs(diffx);
        if(diffy!=0)absy=diffy/abs(diffy);
        int maxdis=max(abs(diffx),abs(diffy));
        for(int i=0;i<maxdis;i++)
        {
          if(temp.x!=endpt[j+1].x)
            temp.x=temp.x+absx;
          if(temp.y!=endpt[j+1].y)
            temp.y=temp.y+absy;
          insertpt.push_back(temp);
        }
        if(j==0)
            insertpt.push_back(newpt);
    }
    vecContour.insert(vecContour.begin()+insertindex,insertpt.begin(),insertpt.end());
    memset(pContourMask,0,sWidth*sHeight);
    for(vector<Pt2D>::iterator it=vecContour.begin();it!=vecContour.end();it++)
    {
        int pos=it->y*sWidth+it->x;
        pContourMask[pos]=1;
    }
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值