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

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

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

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

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

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

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

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

 

一:基本原理如下

1338717591_1887.png

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

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();
    }
  }
 
}

相关文章
|
1天前
|
存储 算法 安全
JVM-内存划分-垃圾回收器-回收算法-双亲委派-三色标记
JVM-内存划分-垃圾回收器-回收算法-双亲委派-三色标记
|
20天前
|
算法 计算机视觉
图像处理之基于图的广度优先搜索组件标记算法
图像处理之基于图的广度优先搜索组件标记算法
10 0
|
21天前
|
存储 算法 Java
图像分析之连通组件标记算法
图像分析之连通组件标记算法
68 1
|
2天前
|
机器学习/深度学习 自然语言处理 算法
m基于深度学习的OFDM+QPSK链路信道估计和均衡算法误码率matlab仿真,对比LS,MMSE及LMMSE传统算法
**摘要:** 升级版MATLAB仿真对比了深度学习与LS、MMSE、LMMSE的OFDM信道估计算法,新增自动样本生成、复杂度分析及抗频偏性能评估。深度学习在无线通信中,尤其在OFDM的信道估计问题上展现潜力,解决了传统方法的局限。程序涉及信道估计器设计,深度学习模型通过学习导频信息估计信道响应,适应频域变化。核心代码展示了信号处理流程,包括编码、调制、信道模拟、降噪、信道估计和解调。
23 8
|
3天前
|
算法 计算机视觉
基于Chan-Vese算法的图像边缘提取matlab仿真
**算法预览展示了4幅图像,从边缘检测到最终分割,体现了在matlab2022a中应用的Chan-Vese水平集迭代过程。核心代码段用于更新水平集并显示迭代效果,最后生成分割结果及误差曲线。Chan-Vese模型(2001)是图像分割的经典方法,通过最小化能量函数自动检测平滑区域和清晰边界的图像分割,适用于复杂环境,广泛应用于医学影像和机器视觉。**
|
4天前
|
算法
基于GA遗传优化的混合发电系统优化配置算法matlab仿真
**摘要:** 该研究利用遗传算法(GA)对混合发电系统进行优化配置,旨在最小化风能、太阳能及电池储能的成本并提升系统性能。MATLAB 2022a用于实现这一算法。仿真结果展示了一系列图表,包括总成本随代数变化、最佳适应度随代数变化,以及不同数据的分布情况,如负荷、风速、太阳辐射、弃电、缺电和电池状态等。此外,代码示例展示了如何运用GA求解,并绘制了发电单元的功率输出和年变化。该系统原理基于GA的自然选择和遗传原理,通过染色体编码、初始种群生成、适应度函数、选择、交叉和变异操作来寻找最优容量配置,以平衡成本、效率和可靠性。
|
5天前
|
机器学习/深度学习 算法
基于鲸鱼优化的knn分类特征选择算法matlab仿真
**基于WOA的KNN特征选择算法摘要** 该研究提出了一种融合鲸鱼优化算法(WOA)与K近邻(KNN)分类器的特征选择方法,旨在提升KNN的分类精度。在MATLAB2022a中实现,WOA负责优化特征子集,通过模拟鲸鱼捕食行为的螺旋式和包围策略搜索最佳特征。KNN则用于评估特征子集的性能。算法流程包括WOA参数初始化、特征二进制编码、适应度函数定义(以分类准确率为基准)、WOA迭代搜索及最优解输出。该方法有效地结合了启发式搜索与机器学习,优化特征选择,提高分类性能。
|
5天前
|
机器学习/深度学习 算法 数据可视化
基于BP神经网络的64QAM解调算法matlab性能仿真
**算法预览图省略** MATLAB 2022A版中,运用BP神经网络进行64QAM解调。64QAM通过6比特映射至64复数符号,提高数据速率。BP网络作为非线性解调器,学习失真信号到比特的映射,对抗信道噪声和多径效应。网络在处理非线性失真和复杂情况时展现高适应性和鲁棒性。核心代码部分未显示。
|
5天前
|
缓存 算法
基于机会网络编码(COPE)的卫星网络路由算法matlab仿真
**摘要:** 该程序实现了一个基于机会网络编码(COPE)的卫星网络路由算法,旨在提升无线网络的传输效率和吞吐量。在MATLAB2022a中测试,结果显示了不同数据流个数下的网络吞吐量。算法通过Dijkstra函数寻找路径,计算编码机会(Nab和Nx),并根据编码机会减少传输次数。当有编码机会时,中间节点执行编码和解码操作,优化传输路径。结果以图表形式展示,显示数据流与吞吐量的关系,并保存为`R0.mat`。COPE算法预测和利用编码机会,适应卫星网络的动态特性,提高数据传输的可靠性和效率。
|
7天前
|
机器学习/深度学习 算法 语音技术
基于语音信号MFCC特征提取和GRNN神经网络的人员身份检测算法matlab仿真
**语音识别算法概览** MATLAB2022a中实现,结合MFCC与GRNN技术进行说话人身份检测。MFCC利用人耳感知特性提取语音频谱特征,GRNN作为非线性映射工具,擅长序列学习,确保高效识别。预加重、分帧、加窗、FFT、滤波器组、IDCT构成MFCC步骤,GRNN以其快速学习与鲁棒性处理不稳定数据。适用于多种领域。