前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于积分图的二值图像膨胀算法实现

基于积分图的二值图像膨胀算法实现

作者头像
OpenCV学堂
发布2018-04-04 11:16:02
1.7K0
发布2018-04-04 11:16:02
举报

积分图来源与发展

积分图是Crow在1984年首次提出,是为了在多尺度透视投影中提高渲染速度。随后这种技术被应用到基于NCC的快速匹配、对象检测和SURF变换中、基于统计学的快速滤波器等方面。积分图是一种在图像中快速计算矩形区域和的方法,这种算法主要优点是一旦积分图首先被计算出来我们可以计算图像中任意大小矩形区域的和而且是在常量时间内。这样在图像模糊、边缘提取、对象检测的时候极大降低计算量、提高计算速度。第一个应用积分图像技术的应用是在Viola-Jones的对象检测框架中出现。

积分图概念

在积分图(Integral Image - ii)上任意位置(x, y)处的ii(x, y)表示该点左上角所有像素之和,表示如下:

膨胀介绍

膨胀操作是图像形态学两个最基本的操作之一,另外一个是腐蚀。主要应用在二值图像和灰度图像分析上,膨胀操作可以适当的根据结构元素的大小来扩张图像前景对象。对二值图像来说,看上去像似边缘增长一样。数学定义如下:

其中W表示窗口大小,OpenCV中定义为结构元素,常见的结构元素包括

  • 矩形
  • 十字交叉

假设有3x3结构元素

二值图像如下

使用3x3结构元素膨胀之后结果如下:

上述图像说明如下:

1-表示白色(255),

0-表示黑色。

蓝色1-表示膨胀之后扩张区域,

红色1-表示二值图像原区域大小。

基于积分图的形态学膨胀算法步骤

  • 根据输入二值图像建立积分图
  • 使用积分图索引查找结构元素重叠区块的像素总和,如果不为0 而且总和不等于窗口大小X255,则中心像素设为255 ,即膨胀
  • 重复第二步实现对每个像素点做相同计算。
  • 输出结果,显示

积分图方式与传统方式运行时间比对

  • 图像为600x400大小, 基于Java语言JDK8实现代码与运行测试结果如下:

从上面可以看出,基于积分图的方式,随着结构元素的变大,计算时间趋于一个常量时间值-C,而基于传统方式随着结构元素变大,时间消耗成几何级数增加。充分证明了基于积分图方式二值膨胀操作是一种高效时间线性化的算法实现。

基于积分图膨胀代码Java版本实现

代码语言:javascript
复制
public class FastDilateOperator extends AbstractByteProcessor {

    private byte[] data;

    private int radius; // must be odd


    public FastDilateOperator() {

        this.radius = 21;

    }


    public void setRadius(int radius) {

        this.radius = radius;

        if(radius % 2 == 0) {

            throw new RuntimeException("invalid parameters");

        }

    }


    public void setData(byte[] data) {

        this.data = data;

    }


     @Override

    public void process(int width, int height) {

         int size = width*height;

        byte[] output = new byte[size];

        IntIntegralImage grayii = new IntIntegralImage();

        grayii.setImage(data);

        grayii.process(width, height);

        int yr = radius/2;

        int xr = radius/2;

        System.arraycopy(data, 0, output, 0, size);

        int index = 0;

        int sum = radius*radius*255;

        int c = 0;

        for(int row=0; row<height; row++) {

            for(int col=0; col<width; col++) {

                index = row * width + col;

                c = data[index]&0xff;

                if(c == 255) continue;

                // 计算均值

                int sr = grayii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));


                // 二值化

                if(sr > 0 && sr < sum) {

                    output[index] = (byte)255;

                }

            }

        }

        System.arraycopy(output, 0, data, 0, size);


    }


}

其中IntIntegralImage类为Java版本的积分图算法实现。 传统二值图像膨胀算法Java版本实现如下:

代码语言:javascript
复制
public class NormalDilateOperator extends AbstractByteProcessor {

    private byte[] data;

    private int radius; // must be odd


    public NormalDilateOperator() {

        this.radius = 21;

    }


    public void setRadius(int radius) {

        this.radius = radius;

        if(radius % 2 == 0) {

            throw new RuntimeException("invalid parameters");

        }

    }


    public void setData(byte[] data) {

        this.data = data;

    }


     @Override

    public void process(int width, int height) {

         int size = width*height;

        byte[] output = new byte[size];

        IntIntegralImage grayii = new IntIntegralImage();

        grayii.setImage(data);

        grayii.process(width, height);

        int yr = radius/2;

        int xr = radius/2;

        System.arraycopy(data, 0, output, 0, size);

        int c = 0;

        int nx=0, ny=0;

        for(int row=0; row<height; row++) {

            for(int col=0; col<width; col++) {

                c = data[row*width+col]&0xff;

                if(c == 255)continue;

                c=0;

                for(int y=-yr; y<=yr; y++) {

                    ny = y + row;

                    if(ny < 0 || ny >= height){

                        ny = 0;

                    }

                    for(int x=-xr; x<=xr; x++) {

                        nx = x+col;

                        if(nx < 0 || nx >= width) {

                            nx = 0;

                        }

                        c += data[ny*width+nx]&0xff;

                    }

                }

                if(c > 0) {

                    output[row*width+col] = (byte)255;

                }

            }

        }

        System.arraycopy(output, 0, data, 0, size);


    }


}

运行截屏如下:

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 积分图来源与发展
  • 积分图概念
  • 膨胀介绍
    • 上述图像说明如下:
    • 基于积分图的形态学膨胀算法步骤
    • 积分图方式与传统方式运行时间比对
    • 基于积分图膨胀代码Java版本实现
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档