数字图像处理成长之路9:轮廓提取c++版

简介


什么是图像的轮廓?在这里不去深入研究它的定义,简单的理解,当人站在太阳下,产生的影子的边界就是轮廓。大致是这样子吧。


轮廓提取的原理

做为一个初学者,试想如果提取轮廓?我首先想到的是沿着轮廓边界搜索。很显然,每个点有8个相邻点也就是8个方向,只要对每个点的8个方向做递归判断就可以了吧。这是我初次接触轮廓提取时的第一想法。当然,轮廓提取应该有很多算法,我是个学习者,并没有充足的时间去把每种轮廓算法研究一遍。我的做法是找到轮廓算法的大致原理,并尝试实现它。然后在学习数字图像处理的其他部分。

有一种算法原理是这样的



或许该称之为转体算法吧,这种算法每找到一个边界点,就以该点为当前点,检测它的8个临域。

c++版轮廓提取:

  ///find first boundry point
    vector<cqPoint> boundryPoints;
    int x;
    int y;
    int flag = 1;

    for (x = 1; x < width; x++)
        {
            for (y = height -1; y > 0; y --)
            {
              if (dst.at<uchar>(y,x)== 255 )
              {
                  boundryPoints.push_back(cqPoint(x, y));
                  globleX = x;
                  globleY = y;
                  mydebug (x<<"::"<<y);
                  goto end;
              }
            }
       }

    ///first boundry point is  x,y. begin scan from postion of 2
    end:cqBackTrace(x, y, 2, dst, boundryPoints, flag);

找到第一个边界点后,用递归搜索下一个边界点:

///
/// \brief cqAlgorithm::cqBackTrace
/// \param x:   x of current boundry point
/// \param y:   y of current boundry point
/// \param pos: the postion of boundry point's neighbor
/// 4- 5- 6
/// 3 -P -7
/// 2 -1- 8
/// \param srcMat:  image
/// \param boundryPoints:   all found boundry points are stored in here
///
void cqAlgorithm::cqBackTrace(int x, int y, int pos, cv::Mat srcMat, vector<cqPoint> boundryPoints, int& flag)
{
    ///
    ///flag 0 means to stop the backtrace,otherwise continue
    ///
    if (flag)
    {
        cq8Neighbor neighbor (x, y);//create neighbor of current boundry x,y
        cqPoint curPoint = neighbor.getPointByPosition(pos);
        int curPointX = curPoint.getX();
        int curPointY = curPoint.getY();
        int value = srcMat.at<uchar>(curPointY, curPointX);
        ///
        ///boundry point is fond;
        ///
        if (value)
        {
            mydebug ("boundry is fond");
            ///
            ///if back to start point, then boundry search has been finished
            ///
            if (globleX == curPointX and globleY == curPointY)
            {
                mydebug (curPointX<< ":"<< curPointY);
                mydebug ("is start point");
                flag = 0;
            }
            ///
            ///if not return to the start point, then continue our search
            ///
            else
            {
                mydebug ("not start point");

                ///add boundry point to boundryPoints vector
                boundryPoints.push_back(curPoint);

                ///change the value to let us see succeed in find a bountry point
                srcMat.at<uchar>(curPointY, curPointX) = 50;
                mydebug (curPointX<< ":"<< curPointY);

                ///since new boundry is found, this point will set to be the current point, and we are going to search the
                /// neighbor of this point, the index of neighbor is given by pos

                if (pos == 1 or pos == 2)
                cqBackTrace(curPointX, curPointY, 7, srcMat, boundryPoints, flag);
                if (pos == 3 or pos == 4)
                    cqBackTrace(curPointX, curPointY, 1, srcMat, boundryPoints, flag);
                if (pos == 5 or pos == 6)
                    cqBackTrace(curPointX, curPointY, 3, srcMat, boundryPoints, flag);
                if (pos == 7 or pos == 8)
                    cqBackTrace(curPointX, curPointY, 5,  srcMat, boundryPoints, flag);
            }
        }
        ///
        ///boundry point is not found,move to next pos and check again
        ///
        else
        {
            if (8 == pos)
                cqBackTrace(x, y, 1, srcMat, boundryPoints, flag);
            else
                cqBackTrace(x, y, pos + 1, srcMat, boundryPoints, flag);
        }
    }
}





在我的QT程序中显示的寻找边界的结果,找到边界后,把该边界点像素值降低,用来告诉我们成功找到。


其中比较有意思的一个问题是:当找到一个新的边界点后,以这个新边界点为中心,搜索临域,但是每个点有8个临域,该从哪个临域开始搜索呢?


这个图可以帮助我们理解上面的问题,只要自己动手实践,所有的问题都会迎刃而解。


所以,关于轮廓提取的原理和c++实现,就谈到这里。



  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
数字图像处理与机器视觉是两个相关领域,旨在通过计算机对图像进行处理和分析,以实现各种目标。Visual C和Matlab都是常用的编程工具,可以用来实现数字图像处理和机器视觉的算法。 Visual C是由微软公司开发的集成开发环境(IDE),它支持C语言C++语言。通过Visual C,我们可以使用其内置的图像处理库和函数,编写和调试数字图像处理和机器视觉算法。Visual C提供了丰富的功能和工具,包括图像读取、显示、滤波、分割、特征提取等等。它也支持硬件加速,可用于处理实时图像或视频。 Matlab是一种高级的数值计算和编程语言,也是一个功能强大的环境,适用于各种科学和工程应用。Matlab具有丰富的图像处理和机器视觉的工具箱,包括图像增强、分割、目标检测、特征提取等等。使用Matlab,我们可以方便地进行图像处理算法的开发和实验,快速验证算法的效果。 在实际应用中,我们可以根据不同的需求和实际情况选择使用Visual C或Matlab来实现图像处理和机器视觉算法。如果我们需要编写底层算法或进行实时图像处理,我们可以选择使用Visual C;如果我们更注重快速原型开发、算法验证和实验,我们可以选择使用Matlab。当然,Visual C和Matlab也可以结合使用,根据具体需求进行开发。 总的来说,数字图像处理和机器视觉是非常重要的技术领域,通过Visual C和Matlab等工具的使用,我们可以更便捷地实现各种图像处理和机器视觉算法,为实际应用和科学研究提供支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆腐白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值