图像处理之计算二值连通区域的质心

简介: 图像处理之计算二值连通区域的质心

图像处理之计算二值连通区域的质心

一:几何距(Geometric Moments)知识与质心寻找原理

1. Image Moments是图像处理中非常有用的算法,可以用来计算区域图像

的质心,方向等几何特性,同时Mpq的高阶具有旋转不变性,可以用来

实现图像比较分类,正是因为Moments有这些特性,很多手绘油画效果

也会基于该算法来模拟实现。它的数学表达为:

它的低阶M00,M01, M10可以用来计算质心,中心化以后M11,M02,M20

可以用来计算区域的方向/角度

2. 什么是质心就是通过该点,区域达到一种质量上的平衡状态,可能物理学上讲的比较多,简单点的

说就是规则几何物体的中心,不规则的可以通过挂绳子的方法来寻找。


二:算法流程

1.      输入图像转换为二值图像

2.      通过连通组件标记算法找到所有的连通区域,并分别标记

3.      对每个连通区域运用计算几何距算法得到质心

4.      用不同颜色绘制连通区域与质心,输出处理后图像

三:算法效果

左边为原图, 右边蓝色为连通组件标记算法处理以后结果,白色点为质心

四:关键代码解析

1.      计算几何距算法代码

doublem00 = moments(pixels, width, height, 0, 0);

doublexCr = moments(pixels, width, height, 1, 0) / m00;// row


doubleyCr = moments(pixels, width, height, 0, 1) / m00;// column


return new double[]{xCr, yCr};

2.      连通组件标记算法代码参见这里:

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

五:程序源代码

package com.gloomyfish.image.moments;
 
import java.awt.image.BufferedImage;
 
import com.gloomyfish.filter.study.AbstractBufferedImageOp;
import com.gloomyfish.rice.analysis.FastConnectedComponentLabelAlg;
// Geometric Moments Computing
// low-order moments - calculate the center point
// second-order moments - get angle size
// projection - 
public class GeometricMomentsFilter extends AbstractBufferedImageOp {
 
  @Override
  public BufferedImage filter(BufferedImage src, BufferedImage dest) {
    int width = src.getWidth();
        int height = src.getHeight();
 
        if ( dest == null )
          dest = createCompatibleDestImage( src, null );
 
        // first step - make it as binary image output pixel
        int[] inPixels = new int[width*height];
        int[] outPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, inPixels );
        int index = 0;
        for(int row=0; row<height; row++) {
          int tr = 0;
          for(int col=0; col<width; col++) {
            index = row * width + col;
                tr = (inPixels[index] >> 16) & 0xff;
                if(tr > 127)
                {
                   outPixels[index] = 1;
                }
                else
                {
                  outPixels[index] = 0;
                }
          }
        }
        
        // second step, connected component labeling algorithm
        FastConnectedComponentLabelAlg ccLabelAlg = new FastConnectedComponentLabelAlg();
        ccLabelAlg.setBgColor(0);
        int[] labels = ccLabelAlg.doLabel(outPixels, width, height);
        int max = 0;
        for(int i=0; i<labels.length; i++)
        {
          if(max < labels[i])
          {
            System.out.println("Label Index = " + labels[i]);
            max = labels[i];
          }
        }
        
        // third step, calculate center point of each region area(connected component)
        int[] input = new int[labels.length];
        GeometricMomentsAlg momentsAlg = new GeometricMomentsAlg();
        momentsAlg.setBACKGROUND(0);
        double[][] labelCenterPos = new double[max][2];
        for(int i=1; i<=max; i++)
        {
          for(int p=0; p<input.length; p++)
          {
            if(labels[p] == i)
            {
              input[p] = labels[p];             
            }
            else
            {
              input[p] = 0;
            }
          }
          labelCenterPos[i-1] = momentsAlg.getGeometricCenterCoordinate(input, width, height);
        }
        
        // render the each connected component center position
        for(int row=0; row<height; row++) {
          for(int col=0; col<width; col++) {
            index = row * width + col;
            if(labels[index] == 0)
            {
              outPixels[index] = (255 << 24) | (0 << 16) | (0 << 8) | 0; // make it as black for background
            }
            else
            {
              outPixels[index] = (255 << 24) | (0 << 16) | (0 << 8) | 100; // make it as blue for each region area
            }
          }
        }
        
        // make it as white color for each center position
        for(int i=0; i<max; i++)
        {
          int crow = (int)labelCenterPos[i][0];
          int ccol = (int)labelCenterPos[i][1];
          index = crow * width + ccol;
          outPixels[index] = (255 << 24) | (255 << 16) | (255 << 8) | 255; 
        }
        
        setRGB( dest, 0, 0, width, height, outPixels );
        return dest;
  }
 
}


Moment算法代码:

package com.gloomyfish.image.moments;
 
public class GeometricMomentsAlg {
  private int BACKGROUND = 0; // background color
  private int labelIndex = 1;
 
  public GeometricMomentsAlg()
  {
    System.out.println("Geometric Moments Algorithm Initialziation...");
  }
  
  public int getLabelIndex() {
    return labelIndex;
  }
  
  public void setLabelIndex(int labelIndex) {
    this.labelIndex = labelIndex;
  }
  
  public int getBACKGROUND() {
    return BACKGROUND;
  }
 
  public void setBACKGROUND(int bACKGROUND) {
    BACKGROUND = bACKGROUND;
  }
  
  public double[] getGeometricCenterCoordinate(int[] pixels, int width, int height)
  {
    double m00 = moments(pixels, width, height, 0, 0);
    double xCr = moments(pixels, width, height, 1, 0) / m00; // row
    double yCr = moments(pixels, width, height, 0, 1) / m00; // column
    return new double[]{xCr, yCr};
  }
 
  public double moments(int[] pixels, int width, int height, int p, int q)
  {
    double mpq = 0.0;
    int index = 0;
    for(int row=0; row<height; row++)
    {
      for(int col=0; col<width; col++)
      {
        index = row * width + col;
        if(pixels[index] == BACKGROUND) continue;
        mpq += Math.pow(row, p) * Math.pow(col, q);
      }
    }
    return mpq;
  }
  
  public double centralMoments(int[] pixel, int width, int height, int p, int q)
  {
    double m00 = moments(pixel, width, height, 0, 0);
    double xCr = moments(pixel, width, height, 1, 0) / m00;
    double yCr = moments(pixel, width, height, 0, 1) / m00;
    double cMpq = 0.0;
    int index = 0;
    for(int row=0; row<height; row++)
    {
      for(int col=0; col<width; col++)
      {
        index = row * width + col;
        if(pixel[index] == BACKGROUND) continue;
        cMpq += Math.pow(row - xCr, p) * Math.pow(col - yCr, q);
      }
    }
    return cMpq;
  }
  
  public double normalCentralMoments(int[] pixel, int width, int height, int p, int q)
  {
    double m00 = moments(pixel, width, height, 0, 0);
    double normal = Math.pow(m00, ((double)(p+q+2))/2.0d);
    return centralMoments(pixel, width, height, p, q)/normal;
  }
}

觉得不错请支持一下

相关文章
|
23天前
|
算法 计算机视觉
图像处理之距离变换
图像处理之距离变换
30 8
|
22天前
|
算法 计算机视觉
图像处理之倒角距离变换
图像处理之倒角距离变换
16 1
|
22天前
|
算法 计算机视觉
图像处理之基于采样距离变换算法
图像处理之基于采样距离变换算法
15 0
|
22天前
|
算法 Java 计算机视觉
图像处理之计算连通区域的角度方向
图像处理之计算连通区域的角度方向
7 0
|
22天前
|
资源调度 算法 计算机视觉
图像处理之积分图应用二(快速边缘保留滤波算法)
图像处理之积分图应用二(快速边缘保留滤波算法)
12 0
|
1月前
用图直观上理解梯度算子(一阶)与拉普拉斯算子(二阶)的区别,线检测与边缘检测的区别
用图直观上理解梯度算子(一阶)与拉普拉斯算子(二阶)的区别,线检测与边缘检测的区别
91 1
|
1月前
|
机器学习/深度学习 XML 编解码
ENVI实现最小距离法、最大似然法、支持向量机遥感图像监督分类与分类后处理操作
ENVI实现最小距离法、最大似然法、支持向量机遥感图像监督分类与分类后处理操作
194 1
|
1月前
[Halcon&拟合] 拟合直线边缘并计算距离
[Halcon&拟合] 拟合直线边缘并计算距离
128 0
|
6月前
|
算法
3D Hough变换点云平面检测算法
3D Hough变换点云平面检测算法
108 0
|
11月前
|
算法
改进极坐标表示(MPR)中AOA定位的特征空间解和偏置减少解(Matlab代码实现)
改进极坐标表示(MPR)中AOA定位的特征空间解和偏置减少解(Matlab代码实现)