zoukankan      html  css  js  c++  java
  • 图像分析------连通组件标记算法 分类: 视频图像处理 2015-07-24 09:57 32人阅读 评论(0) 收藏

    连接组件标记算法(connected component labeling algorithm)是图像分析中最常用的算法之一,

    算法的实质是扫描一幅图像的每个像素,对于像素值相同的分为相同的组(group),最终得到

    图像中所有的像素连通组件。扫描的方式可以是从上到下,从左到右,对于一幅有N个像

    素的图像来说,最大连通组件个数为N/2。扫描是基于每个像素单位,对于二值图像而言,

    连通组件集合可以是V={1}或者V={0}, 取决于前景色与背景色的不同。对于灰度图像来说,

    连图组件像素集合可能是一系列在0 ~ 255之间的灰度值。

     

    算法流程如下:

    1.      首先扫描当前像素相邻的八邻域像素值,发现连通像素加以标记。

    2.      完全扫描所有像素点之后,根据标记将所有连通组件合并。

     

    算法实现Class文件解释:

    AbstractConnectedComponentLabel一个抽象的Class定义了抽象方法doConntectedLabel()

    同时完成了一些公共方法

    ConnectedComponentLabelAlgOne一个容易读懂的连接组件算法完成,没有任何优化,

    继承上面的自抽象类

    ConnectedComponentLabelAlgTwo一个快速的连接组件算法,基于算法优化,取当前像素

    的四邻域完成扫描与标记合并。

     

    LabelPixelInfo是两个数据结构,用来存储算法计算过程中的中间变量。

     

    ImageLabelFilter用来测试算法的驱动类,ImageAnalysisUI是现实测试结果的UI

     

    算法运行结果:

     

    根据标记的索引将组件着色。


    定义数据结构的代码如下:

    1. public class Label {  
    2.       
    3.     private int index;  
    4.     private Label root;  
    5.       
    6.     public Label(int index) {  
    7.         this.index = index;  
    8.         this.root = this;  
    9.     }  
    10.       
    11.     public Label getRoot() {  
    12.         if(this.root != this) {  
    13.             this.root = this.root.getRoot();  
    14.         }  
    15.         return root;  
    16.     }  
    17.   
    18.     public int getIndex() {  
    19.         return index;  
    20.     }  
    21.   
    22.     public void setIndex(int index) {  
    23.         this.index = index;  
    24.     }  
    25.   
    26.     public void setRoot(Label root) {  
    27.         this.root = root;  
    28.     }  
    29. }  

    Pixelnfo的代码如下:

    1. package com.gloomyfish.image.analysis;  
    2.   
    3. public class PixelInfo {  
    4.     private int value; // pixel value  
    5.     private int xp;  
    6.     private int yp;  
    7.       
    8.     public PixelInfo(int pixelValue, int yp, int xp) {  
    9.         this.value = pixelValue;  
    10.         this.yp = yp;  
    11.         this.xp = xp;  
    12.     }  
    13.       
    14.     public int getValue() {  
    15.         return value;  
    16.     }  
    17.     public void setValue(int value) {  
    18.         this.value = value;  
    19.     }  
    20.     public int getXp() {  
    21.         return xp;  
    22.     }  
    23.     public void setXp(int xp) {  
    24.         this.xp = xp;  
    25.     }  
    26.     public int getYp() {  
    27.         return yp;  
    28.     }  
    29.     public void setYp(int yp) {  
    30.         this.yp = yp;  
    31.     }  
    32. }  
    抽象的组件连通标记算法Class如下:

    1. public abstract class AbstractConnectedComponentLabel {  
    2.       
    3.     protected int width;  
    4.     protected int height;  
    5.     protected Color fgColor;  
    6.     protected int[] inPixels;  
    7.     protected int[][] chessborad;  
    8.     protected Map<Integer, Integer> neighbourMap;  
    9.       
    10.     public int getWidth() {  
    11.         return width;  
    12.     }  
    13.   
    14.     public void setWidth(int width) {  
    15.         this.width = width;  
    16.     }  
    17.   
    18.     public int getHeight() {  
    19.         return height;  
    20.     }  
    21.   
    22.     public void setHeight(int height) {  
    23.         this.height = height;  
    24.     }  
    25.       
    26.     public abstract Map<Integer, List<PixelInfo>> doConntectedLabel();  
    27.   
    28.     public boolean isForeGround(int tr, int tg, int tb) {  
    29.         if(tr == fgColor.getRed() && tg == fgColor.getGreen() && tb == fgColor.getBlue()) {  
    30.             return true;  
    31.         } else {  
    32.             return false;  
    33.         }  
    34.           
    35.     }  
    36.   
    37. }  
    实现抽象类的算法one的代码如下:

    1. import java.awt.Color;  
    2. import java.util.ArrayList;  
    3. import java.util.HashMap;  
    4. import java.util.List;  
    5. import java.util.Map;  
    6.   
    7. public class ConnectedComponentLabelAlgOne extends AbstractConnectedComponentLabel {  
    8.   
    9.     public ConnectedComponentLabelAlgOne(Color fgColor, int[] srcPixel, int width, int height) {  
    10.         this.fgColor = fgColor;  
    11.         this.width = width;  
    12.         this.height = height;  
    13.         this.inPixels = srcPixel;  
    14.         this.chessborad = new int[height][width];  
    15.         for(int i=0; i<height; i++) {  
    16.             for(int j=0; j<width; j++) {  
    17.                 chessborad[i][j] = 0;  
    18.             }  
    19.         }  
    20.         this.neighbourMap = new HashMap<Integer, Integer>();   
    21.     }  
    22.       
    23.     // assume the input image data is binary image.  
    24.     public Map<Integer, List<PixelInfo>> doConntectedLabel() {  
    25.         System.out.println("start to do connected component labeling algorithm");  
    26.         int index = 0;  
    27.         int labelCount = 0;  
    28.         Label currentLabel = new Label(0);  
    29.         HashMap<Integer, Label> allLabels = new HashMap<Integer, Label>();  
    30.         for(int row=0; row<height; row++) {  
    31.             int ta = 0, tr = 0, tg = 0, tb = 0;  
    32.             for(int col=0; col<width; col++) {  
    33.                 index = row * width + col;  
    34.                 ta = (inPixels[index] >> 24) & 0xff;  
    35.                 tr = (inPixels[index] >> 16) & 0xff;  
    36.                 tg = (inPixels[index] >> 8) & 0xff;  
    37.                 tb = inPixels[index] & 0xff;  
    38.                 if(isForeGround(tr, tg, tb)) {  
    39.                     getNeighboringLabels(row, col);  
    40.                     if(neighbourMap.size() == 0) {  
    41.                         currentLabel.setIndex(++labelCount);  
    42.                         allLabels.put(labelCount,new Label(labelCount));  
    43.   
    44.                     } else {  
    45.                         for(Integer pixelLabel : neighbourMap.keySet().toArray(new Integer[0])) {  
    46.                             currentLabel.setIndex(pixelLabel);  
    47.                             break;  
    48.                         }  
    49.                         mergeLabels(currentLabel.getIndex(), neighbourMap, allLabels);  
    50.                     }  
    51.                     chessborad[row][col] = currentLabel.getIndex();  
    52.                 }  
    53.             }  
    54.         }  
    55.           
    56.         Map<Integer, List<PixelInfo>> connectedLabels = consolidateAllLabels(allLabels);  
    57.         return connectedLabels;  
    58.     }  
    59.       
    60.     private Map<Integer, List<PixelInfo>> consolidateAllLabels(HashMap<Integer, Label> allLabels) {  
    61.         Map<Integer, List<PixelInfo>> patterns = new HashMap<Integer, List<PixelInfo>>();  
    62.         int patternNumber;  
    63.         List<PixelInfo> shape;  
    64.         for (int i = 0; i < this.height; i++)  
    65.         {  
    66.             for (int j = 0; j < this.width; j++)  
    67.             {  
    68.                 patternNumber = chessborad[i][j];  
    69.                 if (patternNumber != 0)  
    70.                 {  
    71.                     patternNumber = allLabels.get(patternNumber).getRoot().getIndex();  
    72.                     if (!patterns.containsKey(patternNumber))  
    73.                     {  
    74.                         shape = new ArrayList<PixelInfo>();  
    75.                         shape.add(new PixelInfo(Color.BLUE.getRGB(), i, j));  
    76.                     }  
    77.                     else  
    78.                     {  
    79.                         shape = patterns.get(patternNumber);  
    80.                         shape.add(new PixelInfo(Color.BLUE.getRGB(), i, j));  
    81.                     }  
    82.                     patterns.put(patternNumber, shape);  
    83.                 }  
    84.             }  
    85.         }  
    86.         return patterns;  
    87.     }  
    88.   
    89.     private void mergeLabels(int index, Map<Integer, Integer> neighbourMap,  
    90.             HashMap<Integer, Label> allLabels) {  
    91.         Label root = allLabels.get(index).getRoot();  
    92.         Label neighbour;  
    93.         for(Integer key : neighbourMap.keySet().toArray(new Integer[0])) {  
    94.              if (key != index)  
    95.              {  
    96.                  neighbour = allLabels.get(key);  
    97.                  if(neighbour.getRoot() != root) {  
    98.                      neighbour.setRoot(neighbour.getRoot());// thanks zhen712,  
    99.                  }  
    100.              }  
    101.         }  
    102.           
    103.     }  
    104.   
    105.     /** 
    106.      * get eight neighborhood pixels 
    107.      *  
    108.      * @param row 
    109.      * @param col 
    110.      * @return 
    111.      */  
    112.     public  void getNeighboringLabels(int row, int col) {  
    113.         neighbourMap.clear();  
    114.         for(int i=-1; i<=1; i++) {  
    115.             int yp = row + i;  
    116.             if(yp >=0 && yp < this.height) {  
    117.                 for(int j=-1; j<=1; j++) {  
    118.                     if(i == 0 && j==0continue// ignore/skip center pixel/itself  
    119.                     int xp = col + j;  
    120.                     if(xp >=0 && xp < this.width) {  
    121.                         if(chessborad[yp][xp] != 0) {  
    122.                             if(!neighbourMap.containsKey(chessborad[yp][xp])) {  
    123.                                 neighbourMap.put(chessborad[yp][xp],0);  
    124.                             }  
    125.                         }  
    126.                     }  
    127.                 }  
    128.             }  
    129.         }  
    130.     }  
    131. }  

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Postgresql HStore 插件试用小结
    postgres-xl 安装与部署 【异常处理】ERROR: could not open file (null)/STDIN_***_0 for write, No such file or directory
    GPDB 5.x PSQL Quick Reference
    postgresql 数据库schema 复制
    hive 打印日志
    gp与 pg 查询进程
    jquery table 发送两次请求 解惑
    python 字符串拼接效率打脸帖
    postgresql 日期类型处理实践
    IBM Rational Rose软件下载以及全破解方法
  • 原文地址:https://www.cnblogs.com/mao0504/p/4706364.html
Copyright © 2011-2022 走看看