椭圆检测之边缘点合并

在做椭圆检测时,首先需要对灰度图像进行边缘检测,得到离散的边缘点。本文旨在介绍一种连通域标记算法,对边缘点进行合并,并去除较短的边,得到包含椭圆弧段的轮廓集合。

函数如下:

void Labeling(Mat1b& image, vector<vector<Point>>& segments, int iMinLength)
{

// 定义栈区
#define RG_STACK_SIZE 2048
    int stack2[RG_STACK_SIZE];// 保存边缘点序号
#define RG_PUSH2(a) (stack2[sp2]=(a),sp2++)
#define RG_POP2(a) (sp2--, (a) = stack2[sp2])

    Point stack3[RG_STACK_SIZE];// 保存边缘点坐标
#define RG_PUSH3(a) (stack3[sp3] = (a), sp3++)
#define RG_POP3(a) (sp3--, (a) = stack3[sp3])

    int i, w, h, iDim;
    int x, y;
    int x2, y2;
    int sp2;// 栈指针
    int sp3;

    Mat_<uchar> src = image.clone();
    w = src.cols;
    h = src.rows;
    iDim = w*h;

    Point point;
    for (y = 0; y < h; ++y){
        for (x = 0; x < w; ++x){
            if ((src(y, x)) != 0){
                sp2 = 0;
                i = x + y*w;
                RG_PUSH2(i);

                sp3 = 0;
                while (sp2 > 0){
                    RG_POP2(i);
                    x2 = i%w;
                    y2 = i / w;

                    point.x = x2;
                    point.y = y2;

                    if (src(y2, x2)){
                        RG_PUSH3(point);
                        src(y2, x2) = 0;
                    }

                    // 检测八连通区域
                    if (x2 > 0 && (src(y2, x2 - 1) != 0))
                        RG_PUSH2(i - 1);// 保存左点
                    if (y2 > 0 && (src(y2 - 1, x2) != 0))
                        RG_PUSH2(i - w);// 上点
                    if (y2 < h - 1 && (src(y2 + 1, x2) != 0))
                        RG_PUSH2(i + w);// 下点
                    if (x2 < w - 1 && (src(y2, x2 + 1) != 0))
                        RG_PUSH2(i + 1);// 右点
                    if (x2>0 && y2>0 && (src(y2 - 1, x2 - 1) != 0))
                        RG_PUSH2(i - w - 1);// 左上
                    if (x2 > 0 && y2 < h - 1 && (src(y2 + 1, x2 - 1) != 0))
                        RG_PUSH2(i + w - 1);// 左下
                    if (x2 < w - 1 && y2>0 && (src(y2 - 1, x2 + 1) != 0))
                        RG_PUSH2(i - w + 1);// 右上
                    if (x2 < w - 1 && y2 < h - 1 && (src(y2 + 1, x2 + 1) != 0))
                        RG_PUSH2(i + w + 1);// 右下

                // 去除短边
                if (sp3 >= iMinLength){
                    vector<Point> component;
                    component.reserve(sp3);
                    for (i = 0; i < sp3; ++i)
                    {
                        component.push_back(stack3[i]);// 轮廓压栈
                    }
                    segments.push_back(component);// 轮廓组压栈
                }
            }
        }
    }
};

本方法的特别之处在于利用栈来处理,具有更快的处理速度,但占用内存空间更大。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值