连通组件标记算法–算法修正版

简介: 连通组件标记算法–算法修正版 昨天使用自己修改的连通组件标记算法代码去对一个稍微复杂点的图片做皮肤的最大连通 区域识别,发现Java报了栈溢出错误,自己想了想,感觉是合并标记时其中一段递归的代 码的问题,修改为非递归以后,运行结果吓我一跳,发现更加的不对,最后发现原来我读 取标记时候使用了逻辑操作符&,导致标记超过255时候被低位截取。

连通组件标记算法–算法修正版

昨天使用自己修改的连通组件标记算法代码去对一个稍微复杂点的图片做皮肤的最大连通

区域识别,发现Java报了栈溢出错误,自己想了想,感觉是合并标记时其中一段递归的代

码的问题,修改为非递归以后,运行结果吓我一跳,发现更加的不对,最后发现原来我读

取标记时候使用了逻辑操作符&,导致标记超过255时候被低位截取。为了找到这个错误,

花了一个下午的时间重新完成了代码与测试。

 

一:基本原理如下


以前的有问题的算法版本连接,看这里:

http://blog.csdn.net/jia20003/article/details/7596443

二:完整的算法代码如下:

package com.gloomyfish.face.detection;

import java.util.Arrays;
import java.util.HashMap;

/**
 * fast connected component label algorithm
 * 
 * @date 2012-05-23
 * @author zhigang
 *
 */
public class AdjustableConnectedComponentLabelAlg {
	private int bgColor;
	public int getBgColor() {
		return bgColor;
	}

	public void setBgColor(int bgColor) {
		this.bgColor = bgColor;
	}

	private int[] outData;
	private int dw;
	private int dh;
	
	public AdjustableConnectedComponentLabelAlg() {
		bgColor = 255; // black color
	}

	public int[] doLabel(int[] inPixels, int width, int height) {
		dw = width;
		dh = height;
		int nextlabel = 1;
		int result = 0;
		outData = new int[dw * dh];
		for(int i=0; i<outData.length; i++) {
			outData[i] = 0;
		}
		
		// we need to define these two variable arrays.
		int[] eightNeighborhoodPixels = new int[8];
		int[] eightNeighborhoodLabels = new int[8];
		int[] knownLabels = new int[8];
		
		int srcrgb = 0, index = 0;
		boolean existedLabel = false;
		for(int row = 0; row < height; row ++) {
			for(int col = 0; col < width; col++) {
				index = row * width + col;
				srcrgb = inPixels[index] & 0x000000ff;
				if(srcrgb == bgColor) {
					result = 0; // which means no labeled for this pixel.
				} else {
					// we just find the eight neighborhood pixels.
					eightNeighborhoodPixels[0] = getPixel(inPixels, row-1, col); // upper cell
					eightNeighborhoodPixels[1] = getPixel(inPixels, row, col-1); // left cell
					eightNeighborhoodPixels[2] = getPixel(inPixels, row+1, col); // bottom cell
					eightNeighborhoodPixels[3] = getPixel(inPixels, row, col+1); // right cell
					
					// four corners pixels
					eightNeighborhoodPixels[4] = getPixel(inPixels, row-1, col-1); // upper left corner
					eightNeighborhoodPixels[5] = getPixel(inPixels, row-1, col+1); // upper right corner
					eightNeighborhoodPixels[6] = getPixel(inPixels, row+1, col-1); // left bottom corner
					eightNeighborhoodPixels[7] = getPixel(inPixels, row+1, col+1); // right bottom corner
					
					// get current possible existed labels
					eightNeighborhoodLabels[0] = getLabel(outData, row-1, col); // upper cell
					eightNeighborhoodLabels[1] = getLabel(outData, row, col-1); // left cell
					eightNeighborhoodLabels[2] = getLabel(outData, row+1, col); // bottom cell
					eightNeighborhoodLabels[3] = getLabel(outData, row, col+1); // right cell
					
					// four corners labels value
					eightNeighborhoodLabels[4] = getLabel(outData, row-1, col-1); // upper left corner
					eightNeighborhoodLabels[5] = getLabel(outData, row-1, col+1); // upper right corner
					eightNeighborhoodLabels[6] = getLabel(outData, row+1, col-1); // left bottom corner
					eightNeighborhoodLabels[7] = getLabel(outData, row+1, col+1); // right bottom corner
					
					int minLabel = 0;
					int count = 0;
					for(int i=0; i<knownLabels.length; i++) {
						if(eightNeighborhoodLabels[i] > 0) {
							existedLabel = true;
							knownLabels[i] = eightNeighborhoodLabels[i];
							minLabel = eightNeighborhoodLabels[i];
							count++;
						}
					}
					
					if(existedLabel) {
						if(count == 1) {
							result = minLabel;
						} else {
							int[] tempLabels = new int[count];
							int idx = 0;
							for(int i=0; i<knownLabels.length; i++) {
								if(knownLabels[i] > 0){
									tempLabels[idx++] = knownLabels[i];
								}
								if(minLabel > knownLabels[i] && knownLabels[i] > 0) {
									minLabel = knownLabels[i];
								}
							}
							result = minLabel;
							mergeLabels(index, result, tempLabels);
						}
					} else {
						result = nextlabel;
						nextlabel++;
					}
					outData[index] = result;
					// reset and cleanup the known labels now...
					existedLabel = false;
					for(int kl = 0; kl < knownLabels.length; kl++) {
						knownLabels[kl] = 0;
					}
				}
			}
		}
		
		// labels statistic
		HashMap<Integer, Integer> labelMap = new HashMap<Integer, Integer>();
		for(int d=0; d<outData.length; d++) {
			if(outData[d] != 0) {
				if(labelMap.containsKey(outData[d])) {
					Integer count = labelMap.get(outData[d]);
					count+=1;
					labelMap.put(outData[d], count);
				} else {
					labelMap.put(outData[d], 1);
				}
			}
		}
		
		// try to find the max connected component
		Integer[] keys = labelMap.keySet().toArray(new Integer[0]);
		Arrays.sort(keys);
		int maxKey = 1;
		int max = 0;
		for(Integer key : keys) {
			if(max < labelMap.get(key)){
				max = labelMap.get(key);
				maxKey = key;
			}
			System.out.println( "Number of " + key + " = " + labelMap.get(key));
		}
		System.out.println("maxkey = " + maxKey);
		System.out.println("max connected component number = " + max);
		return outData;
	}
	
	private void mergeLabels (int index, int result, int[] labels) {
		for(int i=0; i<labels.length; i++) {
			if(labels[i] == result) continue;
			mergeLabel(index, result, labels[i]);
		}
	}

	private void mergeLabel(int index, int result, int i) {

		int row = index / dw;
		int idx = 0;
		for(int k = 0; k <= row; k++) {
			for(int col = 0; col < dw; col++) {
				idx = k * dw + col;
				if(outData[idx] == i) {
					outData[idx] = result;
				}
			}
		}
		
	}
	
	private int getLabel(int[] data, int row, int col) {
		// handle the edge pixels
		if(row < 0 || row >= dh) {
			return 0;
		}
		
		if(col < 0 || col >= dw) {
			return 0;
		}
		
		int index = row * dw + col;
		return (data[index] & 0xffffffff);
		
		// it's difficulty for me to find the data overflow issue......
		// return (data[index] & 0x000000ff); defect, @_@
	}

	private int getPixel(int[] data, int row, int col) {
		// handle the edge pixels
		if(row < 0 || row >= dh) {
			return bgColor;
		}
		
		if(col < 0 || col >= dw) {
			return bgColor;
		}
		
		int index = row * dw + col;
		return (data[index] & 0x000000ff);
	}

	/**
	 * binary image data:
	 * 
	 * 255, 0,   0,   255,   0,   255, 255, 0,   255, 255, 255,
	 * 255, 0,   0,   255,   0,   255, 255, 0,   0,   255, 0,
	 * 255, 0,   0,   0,     255, 255, 255, 255, 255, 0,   0,
	 * 255, 255, 0,   255,   255, 255, 0,   255, 0,   0,   255
	 * 255, 255, 0,   0,     0,   0,   255, 0,   0,   0,   0
	 * 
	 * height = 5, width = 11
	 * @param args
	 */
	public static int[] imageData = new int[]{
		 255, 0,   0,   255,   0,   255, 255, 0,   255, 255, 255,
		 255, 0,   0,   255,   0,   255, 255, 0,   0,   255, 0,
		 255, 0,   0,   255,     255, 255, 255, 255, 255, 0,   0,
		 255, 255, 0,   255,   255, 255, 0,   255, 0,   0,   255,
		 255, 255, 0,   0,     0,   0,   255, 255,   0,   0,   0,
		 255, 255, 255, 255,   255, 255, 255, 255, 255, 255, 255,
		 255, 0,   255, 0,     255, 0,   0,   255, 255, 255, 255,
		 255, 255, 0,   0,     255, 255, 255, 0,   0,   255, 255
	};
	
	public static void main(String[] args) {
		AdjustableConnectedComponentLabelAlg ccl = new AdjustableConnectedComponentLabelAlg();
		int[] outData = ccl.doLabel(imageData, 11, 8);
		for(int i=0; i<8; i++) {
			System.out.println("--------------------");
			for(int j = 0; j<11; j++) {
				int index = i * 11 + j;
				if(j != 0) {
					System.out.print(",");
				}
				System.out.print(outData[index]);
			}
			System.out.println();
		}
	}

}
目录
相关文章
|
15天前
|
存储 算法 Java
图像分析之连通组件标记算法
图像分析之连通组件标记算法
15 1
|
14天前
|
算法 计算机视觉
图像处理之基于图的广度优先搜索组件标记算法
图像处理之基于图的广度优先搜索组件标记算法
10 0
|
15天前
|
算法 Java
连通组件标记算法–算法修正版
连通组件标记算法–算法修正版
9 0
|
2天前
|
机器学习/深度学习 算法 数据可视化
m基于PSO-LSTM粒子群优化长短记忆网络的电力负荷数据预测算法matlab仿真
在MATLAB 2022a中,应用PSO优化的LSTM模型提升了电力负荷预测效果。优化前预测波动大,优化后预测更稳定。PSO借鉴群体智能,寻找LSTM超参数(如学习率、隐藏层大小)的最优组合,以最小化误差。LSTM通过门控机制处理序列数据。代码显示了模型训练、预测及误差可视化过程。经过优化,模型性能得到改善。
16 6
|
2天前
|
算法 调度
基于变异混合蛙跳算法的车间调度最优化matlab仿真,可以任意调整工件数和机器数,输出甘特图
**摘要:** 实现变异混合蛙跳算法的MATLAB2022a版车间调度优化程序,支持动态调整工件和机器数,输出甘特图。核心算法结合SFLA与变异策略,解决Job-Shop Scheduling Problem,最小化总完成时间。SFLA模拟蛙群行为,分组进行局部搜索和全局信息交换。变异策略增强全局探索,避免局部最优。程序初始化随机解,按规则更新,经多次迭代和信息交换后终止。
|
13天前
|
算法
基于GA-PSO遗传粒子群混合优化算法的VRPTW问题求解matlab仿真
摘要: 本文介绍了考虑时间窗的车辆路径问题(VRPTW),在MATLAB2022a中进行测试。VRPTW涉及车辆从配送中心出发,服务客户并返回,需在指定时间窗内完成且满足车辆容量限制,目标是最小化总行驶成本。文章探讨了遗传算法(GA)和粒子群优化(PSO)的基本原理及其在VRPTW中的应用,包括编码、适应度函数、选择、交叉、变异等步骤。同时,提出了动态惯性权重、精英策略、邻域搜索、多种群和启发式信息等优化策略,以应对时间窗限制并提升算法性能。
|
7天前
|
算法 JavaScript 决策智能
基于禁忌搜索算法的TSP路径规划matlab仿真
**摘要:** 使用禁忌搜索算法解决旅行商问题(TSP),在MATLAB2022a中实现路径规划,显示优化曲线与路线图。TSP寻找最短城市访问路径,算法通过避免局部最优,利用禁忌列表不断调整顺序。关键步骤包括初始路径选择、邻域搜索、解评估、选择及禁忌列表更新。过程示意图展示搜索效果。
|
7天前
|
机器学习/深度学习 算法
基于BP神经网络和小波变换特征提取的烟草香型分类算法matlab仿真,分为浓香型,清香型和中间香型
```markdown 探索烟草香型分类:使用Matlab2022a中的BP神经网络结合小波变换。小波分析揭示香气成分的局部特征,降低维度,PCA等用于特征选择。BP网络随后处理这些特征,以区分浓香、清香和中间香型。 ```
|
10天前
|
算法 调度 决策智能
基于自适应遗传算法的车间调度matlab仿真,可以任意调整工件数和机器数,输出甘特图
这是一个使用MATLAB2022a实现的自适应遗传算法解决车间调度问题的程序,能调整工件数和机器数,输出甘特图和适应度收敛曲线。程序通过编码初始化、适应度函数、遗传操作(选择、交叉、变异)及自适应机制进行优化,目标如最小化完工时间。算法在迭代过程中动态调整参数,以提升搜索效率和全局优化。
|
12天前
|
传感器 算法 安全
基于WSN网络的定向步幻影路由算法matlab仿真
该文探讨了无线传感器网络中的位置隐私保护,对比了NDRW路由与定向步幻影路由在安全时间和能耗方面的性能。在MATLAB2022a中进行测试,结果显示NDRW路由提供最长的安全时间,尤其在长距离传输时,且在近距离下能耗低于幻影路由。幻影路由虽消耗更多能量,但通过随机步创造幻影源以增强安全性。NDRW路由利用非确定性随机游走策略,避免拥堵并提高效率,而幻影路由则引入方向性控制,通过启发式算法优化路径选择。