基于积分图的二值图像膨胀算法实现
时间:2022-05-07
本文章向大家介绍基于积分图的二值图像膨胀算法实现,主要内容包括积分图来源与发展、积分图概念、膨胀介绍、基于积分图的形态学膨胀算法步骤、积分图方式与传统方式运行时间比对、基于积分图膨胀代码Java版本实现、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
积分图来源与发展
积分图是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版本实现
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版本实现如下:
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);
}
}
运行截屏如下:
- 零基础学编程017:画出我的公众号LOGO
- 一个实用的却被忽略的命名空间:Microsoft.VisualBasic
- Spring @RequestBody 传递 List/Map 参数
- win7怎么去除快捷方式的小箭头
- 零基础学编程015:画些有趣的图案
- Spring boot with Thymeleaf
- 零基础学编程014:小海龟做画
- Springboot @RequestBody 传递 List
- 零基础学编程013:import让你飞起来
- 【教程】利用Tensorflow目标检测API确定图像中目标的位置
- 零基础学编程012:画出复利曲线图
- OpenAI发布高度优化的GPU计算内核—块稀疏GPU内核
- SQL SERVER 原来还可以这样玩 FOR XML PATH
- 零基础学编程011:复利数据表问题(总结)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python使用文件操作实现一个XX信息管理系统的示例
- PHP htmlspecialchars() 函数实例代码及用法大全
- 浅谈keras2 predict和fit_generator的坑
- 使用python实现名片管理系统
- PHP实现PDO操作mysql存储过程示例
- Python bisect模块原理及常见实例
- PHP的curl函数的用法总结
- Python函数的迭代器与生成器的示例代码
- PHP中检查isset()和!empty()函数的必要性
- python代码中怎么换行
- PHP让网站移动访问更加友好方法
- python代码区分大小写吗
- php面试中关于面向对象的相关问题
- python实现在线翻译
- Python字符串格式化常用手段及注意事项