项目记录-圆形边缘修正方法探索1

问题:目前分割得到的圆形边缘和理想边缘相比,部分向外偏离,需要向内收缩

探索方法1:
假设在理想情况下,圆形物体的掩膜是绝对正确的。此时可以遍历当前的边缘点,判断每个边缘点的两侧的掩膜标记是否不同。如果两侧的邻域点掩膜都为0,说明该边缘点偏外,需要向内收缩,使用最近的掩膜点来替换掉越界了的点。

但是此方法在项目中行不通,因为项目中的掩膜文件是有误差的,不能表示正确的圆形。
下面记录一下此方法的实现代码:

//找出两侧都是0的点,说明此处需要收缩
while (i < vecCurContour.size() - 1)
{
    Pt2D curPos(vecCurContour[i]);
    Pt2D nextPos(vecCurContour[i + 1]);
    int diffx = nextPos.x - curPos.x;
    int diffy = nextPos.y - curPos.y;
    Pt2D sideA = { curPos.x + diffy, curPos.y - diffx };
    Pt2D sideB = { curPos.x - diffy, curPos.y + diffx };
    //检测两侧的邻域点是否都为0
    long a = sideA.y*sWidth + sideA.x;
    long b = sideB.y*sWidth + sideB.x;
    if (!(pMaskBuf[a] == 0 && pMaskBuf[b] == 0))
    {
        i++;
        continue;
    }
    else
    {
        //起点已找到
        int begin = i - 1;
        //从此点开始,寻找待处理的线段的终点
        while (i < vecCurContour.size() - 1)
        {
            curPos = vecCurContour[i];
            nextPos = vecCurContour[i + 1];
            diffx = nextPos.x - curPos.x;
            diffy = nextPos.y - curPos.y;
            Pt2D sideA = { curPos.x + diffy, curPos.y - diffx };
            Pt2D sideB = { curPos.x - diffy, curPos.y + diffx };
            //检测两侧的邻域点是否都为0
            a = sideA.y*sWidth + sideA.x;
            b = sideB.y*sWidth + sideB.x;
            if ((pMaskBuf[a] == 0 && pMaskBuf[b] == 1) || 
                 (pMaskBuf[a] == 1 && pMaskBuf[b] == 0))    
                 break;
            i++;
        }
        //终点已找到
        int end = i;
        if (begin < 0)  continue;
        int Neb[8][2] = EIGHT_NEIGHBORHOOD2;
        int dir = 0;
        /*接着继续查找下一段的起点(在前一段圆弧修正之后,下一段正确的圆弧也需要跟着做些微调整,
          以保证整个圆形边缘的光滑度*/
        int newend = end;
        int nextstart = end;
        while (i < vecCurContour.size() - 2)
        {
            i++;
            curPos = vecCurContour[i];
            nextPos = vecCurContour[i + 1];
            diffx = nextPos.x - curPos.x;
            diffy = nextPos.y - curPos.y;
            Pt2D sideA = { curPos.x + diffy, curPos.y - diffx };
            Pt2D sideB = { curPos.x - diffy, curPos.y + diffx };
            //检测两侧的邻域点是否都为0
            a = sideA.y*sWidth + sideA.x;
            b = sideB.y*sWidth + sideB.x;
            if (pMaskBuf[a] == 0 && pMaskBuf[b] == 0)
            {
                if (i - end > 3)
                    break;
                else
                    end = i;
            }
        }
        nextstart = i - 1;
        //方法:使用最近的初始边缘点来替换掉越界了的点
        dir = 0;
        queue<Pt2D>addPt;//用来替换的点
        //需要确保起点是和初始的边缘重合的
        bool isFind = false;
        int findnum = begin > 6 ? 6 : begin;
        int findindex;
        for (findindex = 1; findindex < findnum; findindex++)
        {
            int pos = vecCurContour[begin - findindex].y*sWidth +
                      vecCurContour[begin - findindex].x;
            if (pContourMask[pos]){ isFind = true; break; }
        }
        if (!isFind)
        {
            //如果没有找到,则用宽度优先,寻找最近的初始边缘点
            queue<Pt2D>qfindpt;
            qfindpt.push(vecCurContour[begin]);
            while (!qfindpt.empty() && !isFind)
            {
                Pt2D pt = qfindpt.front();
                qfindpt.pop();
                for (int i = 0; i < 8; i++)
                {
                    int x = pt.x + Neb[i][1];
                    int y = pt.y + Neb[i][0];
                    int pos = y*sWidth + x;
                    if (x >= 0 && x < sWidth && y >= 0 && y < sHeight)
                    {
                        if (pContourMask[pos])
                        {
                            Pt2D temp = { x, y };
                            addPt.push(temp);
                            isFind = true;
                            break;
                        }
                        Pt2D temp = { x, y };
                        qfindpt.push(temp);
                    }
                }
            }
        }
        else
        {
            begin -= findindex;
            addPt.push(vecCurContour[begin]);
        }
        int dir = 0;
        for (int index = begin; index < end; index++)
        {
            Pt2D curPt;
            Pt2D newPt;
            if (index == begin)
            {
                curPt = vecCurContour[index];
                //计算初始方向
                int diffx = vecCurContour[index + 1].x - vecCurContour[index].x;
                int diffy = vecCurContour[index + 1].y - vecCurContour[index].y;
                if (diffy == -1)
                    dir = diffx + 2;
                else if (diffy == 0)
                    dir = (diffx == -1) ? 0 : 4;
                else if (diffy == 1)
                    dir = 6 - diffx;
            }
            for (int i = 0; i < 8; i++)
            {
                int xx = curPt.x + Neb[dir][1];
                int yy = curPt.y + Neb[dir][0];
                long lNewOff = yy * sWidth + xx;
                if (xx >= 0 && xx < sWidth && yy >= 0 && yy < sHeight)
                {
                    if (pContourMask[lNewOff])
                    {
                        newPt.x = (SINT)xx;
                        newPt.y = (SINT)yy;
                        addPt.push(newPt);
                        curPt = newPt;
                        if (dir % 2 == 0)
                        {
                            dir = (dir + 7) % 8;
                        }
                        else
                        {
                            dir = (dir + 6) % 8;
                        }
                        break;
                    }
                    else
                        dir = (dir + 1) % 8;
                }
                else
                    dir = (dir + 1) % 8;
            }
        }
        //替换点
        for (int index = begin; index <= end; index++)
        {
            vecCurContour[index].x = addPt.front().x;
            vecCurContour[index].y = addPt.front().y;
            addPt.pop();
        }
        //计算nextstart和endpt之间的新线段,保证圆弧的光滑
        //两个点之间连线
        if (nextstart - end > 3)
        {
            Pt2D temp = vecCurContour[end];
            vector<Pt2D>insertpt;
            int diffx = vecCurContour[end].x - vecCurContour[nextstart].x;
            int diffy = vecCurContour[end].y - vecCurContour[nextstart].y;
            int absx = 0, 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 != vecCurContour[nextstart].x)
                    temp.x = temp.x + absx;
                if (temp.y != vecCurContour[nextstart].y)
                    temp.y = temp.y + absy;
                insertpt.push_back(temp);
            }
            //替换点
            vecCurContour.erase(vecCurContour.begin()+end+1,
                                vecCurContour.begin()+nextstart);   
            vecCurContour.insert(vecCurContour.begin()+end+1,
                                 insertpt.begin(),insertpt.end());
            i += (end - begin + insertpt.size() + 1);
        }
        else
            i += end - begin + 1;
        break;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值