图像处理之基于泛红算法的二值图像内部区域填充

简介: 图像处理之基于泛红算法的二值图像内部区域填充一:基本原理在二值图像处理中有个常用的操作叫做Hole Fill意思是填充所有封闭区域的内部,这种算法在二值图像基础上的对象识别与提取有很大作用。基于泛红填充算法实现二值图像内部区域填充是一直快速填充算法。

图像处理之基于泛红算法的二值图像内部区域填充

一:基本原理

在二值图像处理中有个常用的操作叫做Hole Fill意思是填充所有封闭区域的内部,这种算法在二值图像基础上的对象识别与提取有很大作用。基于泛红填充算法实现二值图像内部区域填充是一直快速填充算法。


因为泛红填充通常需要指定从一个点开始,填满整个封闭区域,对一张二值图像来说,我们最好的办法是把背景当成一个封闭区域,从上向下从左到右查到第一个背景像素点,基于扫描线算法实现全部填充成一个非0,255之外的一个像素值,我这里是127。填充完成之后再一次从左到右,从上向下检查每个像素值如果是127的则为背景像素,否则全部设为前景像素。这样就完成二值图像每个封闭区域内部填充。


二:算法实现步骤

1.      读取二值图像

2.      基于扫描线算法对背景像素区域进行泛红填充,填充值为127

3.      循环每个像素对值为127的设为背景像素,其它值设为前景像素

4.      返回填充之后的二值图像像素数据

三:代码实现

package com.gloomyfish.basic.imageprocess;

public class FloodFillAlgorithm extends AbstractByteProcessor {
	private int foreground;
	private int background;
	private byte[] data;
	private int width;
	private int height;

	// stack data structure
	private int maxStackSize = 500; // will be increased as needed
	private int[] xstack = new int[maxStackSize];
	private int[] ystack = new int[maxStackSize];
	private int stackSize;

	public FloodFillAlgorithm(byte[] data) {
		this.data = data;
		this.foreground = 0;
		this.background = 255 - this.foreground;
	}

	public int getColor(int x, int y) {
		int index = y * width + x;
		return data[index] & 0xff;
	}

	public void setColor(int x, int y, int newColor) {
		int index = y * width + x;
		data[index] = (byte) newColor;
	}

	public void floodFillScanLineWithStack(int x, int y, int newColor, int oldColor) {
		if (oldColor == newColor) {
			System.out.println("do nothing !!!, filled area!!");
			return;
		}
		emptyStack();

		int y1;
		boolean spanLeft, spanRight;
		push(x, y);

		while (true) {
			x = popx();
			if (x == -1)
				return;
			y = popy();
			y1 = y;
			while (y1 >= 0 && getColor(x, y1) == oldColor)
				y1--; // go to line top/bottom
			y1++; // start from line starting point pixel
			spanLeft = spanRight = false;
			while (y1 < height && getColor(x, y1) == oldColor) {
				setColor(x, y1, newColor);
				if (!spanLeft && x > 0 && getColor(x - 1, y1) == oldColor)// just
																			// keep
																			// left
																			// line
																			// once
																			// in
																			// the
																			// stack
				{
					push(x - 1, y1);
					spanLeft = true;
				} else if (spanLeft && x > 0 && getColor(x - 1, y1) != oldColor) {
					spanLeft = false;
				}
				if (!spanRight && x < width - 1 && getColor(x + 1, y1) == oldColor) // just
																					// keep
																					// right
																					// line
																					// once
																					// in
																					// the
																					// stack
				{
					push(x + 1, y1);
					spanRight = true;
				} else if (spanRight && x < width - 1 && getColor(x + 1, y1) != oldColor) {
					spanRight = false;
				}
				y1++;
			}
		}

	}

	private void emptyStack() {
		while (popx() != -1) {
			popy();
		}
		stackSize = 0;
	}

	final void push(int x, int y) {
		stackSize++;
		if (stackSize == maxStackSize) {
			int[] newXStack = new int[maxStackSize * 2];
			int[] newYStack = new int[maxStackSize * 2];
			System.arraycopy(xstack, 0, newXStack, 0, maxStackSize);
			System.arraycopy(ystack, 0, newYStack, 0, maxStackSize);
			xstack = newXStack;
			ystack = newYStack;
			maxStackSize *= 2;
		}
		xstack[stackSize - 1] = x;
		ystack[stackSize - 1] = y;
	}

	final int popx() {
		if (stackSize == 0)
			return -1;
		else
			return xstack[stackSize - 1];
	}

	final int popy() {
		int value = ystack[stackSize - 1];
		stackSize--;
		return value;
	}

	@Override
	public void process(int width, int height) {
		this.width = width;
		this.height = height;

		for (int y = 0; y < height; y++) {
			if (getColor(0, y) == background)
				floodFillScanLineWithStack(0, y, 127, 255);
			if (getColor(width - 1, y) == background)
				floodFillScanLineWithStack(width - 1, y, 127, 255);
		}
		for (int x = 0; x < width; x++) {
			if (getColor(x, 0) == background)
				floodFillScanLineWithStack(x, 0, 127, 255);
			if (getColor(x, height - 1) == background)
				floodFillScanLineWithStack(x, height - 1, 127, 255);
		}
		
		int p = 0;
		for (int i = 0; i < data.length; i++) {
			p = data[i]&0xff;
			if (p == 127)
				data[i] = (byte)255;
			else
				data[i] = (byte)0;
		}
	}

}
四:运行结果


使用代码,要先读取二值图像数据到data字节数组

FloodFillAlgorithm ffa = new FloodFillAlgorithm(data);
		ffa.process(width, height);


目录
相关文章
|
1月前
|
算法 计算机视觉
图像处理常用算法—6个算子 !!
图像处理常用算法—6个算子 !!
26 2
|
1月前
|
机器学习/深度学习 算法 数据库
KNN和SVM实现对LFW人像图像数据集的分类应用
KNN和SVM实现对LFW人像图像数据集的分类应用
33 0
|
4月前
|
算法 数据挖掘 计算机视觉
Python利用K-Means算法进行图像聚类分割实战(超详细 附源码)
Python利用K-Means算法进行图像聚类分割实战(超详细 附源码)
99 0
|
4月前
|
算法 计算机视觉 异构计算
基于FPGA的图像形态学腐蚀算法实现,包括tb测试文件和MATLAB辅助验证
基于FPGA的图像形态学腐蚀算法实现,包括tb测试文件和MATLAB辅助验证
|
3天前
|
文字识别 算法 计算机视觉
图像倾斜校正算法的MATLAB实现:图像倾斜角检测及校正
图像倾斜校正算法的MATLAB实现:图像倾斜角检测及校正
12 0
|
1月前
|
算法 数据可视化 计算机视觉
使用Python实现图像处理中的边缘检测算法
图像处理中的边缘检测是计算机视觉和图像识别领域的重要技术之一。本文将介绍如何利用Python语言实现常见的边缘检测算法,包括Sobel、Canny等,并结合实例演示其在图像处理中的应用。
|
1月前
|
机器学习/深度学习 算法 计算机视觉
利用深度学习算法实现图像风格转换技术探究
本文将通过深入分析深度学习算法在图像处理领域的应用,探讨如何利用神经网络实现图像风格转换技术。通过研究不同风格迁移算法的原理和实现方式,揭示其在艺术创作、图像编辑等领域的潜在应用和挑战。
|
1月前
|
编解码 算法 计算机视觉
基于FPGA的图像最近邻插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
基于FPGA的图像最近邻插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
|
2月前
|
机器学习/深度学习 算法 搜索推荐
【实操】数据扩增:Retinex算法用于图像颜色恢复和对比度增强
【实操】数据扩增:Retinex算法用于图像颜色恢复和对比度增强
30 0
【实操】数据扩增:Retinex算法用于图像颜色恢复和对比度增强
|
2月前
|
算法 计算机视觉
基于Harris角点的多视角图像全景拼接算法matlab仿真
基于Harris角点的多视角图像全景拼接算法matlab仿真