图像区域求质心,面积


二值图像中大于0的像素个数就是图像的面积

坐标x乘以每个像素点的值 求和,除以图像中像素值的和得到质心

注意图像的宽高范围从1-width,1-height

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

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

 

一:几何距(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

五:程序源代码

  1. package com.gloomyfish.image.moments;  
  2.   
  3. import java.awt.image.BufferedImage;  
  4.   
  5. import com.gloomyfish.filter.study.AbstractBufferedImageOp;  
  6. import com.gloomyfish.rice.analysis.FastConnectedComponentLabelAlg;  
  7. // Geometric Moments Computing  
  8. // low-order moments - calculate the center point  
  9. // second-order moments - get angle size  
  10. // projection -   
  11. public class GeometricMomentsFilter extends AbstractBufferedImageOp {  
  12.   
  13.     @Override  
  14.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
  15.         int width = src.getWidth();  
  16.         int height = src.getHeight();  
  17.   
  18.         if ( dest == null )  
  19.             dest = createCompatibleDestImage( src, null );  
  20.   
  21.         // first step - make it as binary image output pixel  
  22.         int[] inPixels = new int[width*height];  
  23.         int[] outPixels = new int[width*height];  
  24.         getRGB( src, 0, 0, width, height, inPixels );  
  25.         int index = 0;  
  26.         for(int row=0; row<height; row++) {  
  27.             int tr = 0;  
  28.             for(int col=0; col<width; col++) {  
  29.                 index = row * width + col;  
  30.                 tr = (inPixels[index] >> 16) & 0xff;  
  31.                 if(tr > 127)  
  32.                 {  
  33.                      outPixels[index] = 1;  
  34.                 }  
  35.                 else  
  36.                 {  
  37.                     outPixels[index] = 0;  
  38.                 }  
  39.             }  
  40.         }  
  41.           
  42.         // second step, connected component labeling algorithm  
  43.         FastConnectedComponentLabelAlg ccLabelAlg = new FastConnectedComponentLabelAlg();  
  44.         ccLabelAlg.setBgColor(0);  
  45.         int[] labels = ccLabelAlg.doLabel(outPixels, width, height);  
  46.         int max = 0;  
  47.         for(int i=0; i<labels.length; i++)  
  48.         {  
  49.             if(max < labels[i])  
  50.             {  
  51.                 System.out.println("Label Index = " + labels[i]);  
  52.                 max = labels[i];  
  53.             }  
  54.         }  
  55.           
  56.         // third step, calculate center point of each region area(connected component)  
  57.         int[] input = new int[labels.length];  
  58.         GeometricMomentsAlg momentsAlg = new GeometricMomentsAlg();  
  59.         momentsAlg.setBACKGROUND(0);  
  60.         double[][] labelCenterPos = new double[max][2];  
  61.         for(int i=1; i<=max; i++)  
  62.         {  
  63.             for(int p=0; p<input.length; p++)  
  64.             {  
  65.                 if(labels[p] == i)  
  66.                 {  
  67.                     input[p] = labels[p];                     
  68.                 }  
  69.                 else  
  70.                 {  
  71.                     input[p] = 0;  
  72.                 }  
  73.             }  
  74.             labelCenterPos[i-1] = momentsAlg.getGeometricCenterCoordinate(input, width, height);  
  75.         }  
  76.           
  77.         // render the each connected component center position  
  78.         for(int row=0; row<height; row++) {  
  79.             for(int col=0; col<width; col++) {  
  80.                 index = row * width + col;  
  81.                 if(labels[index] == 0)  
  82.                 {  
  83.                     outPixels[index] = (255 << 24) | (0 << 16) | (0 << 8) | 0; // make it as black for background  
  84.                 }  
  85.                 else  
  86.                 {  
  87.                     outPixels[index] = (255 << 24) | (0 << 16) | (0 << 8) | 100; // make it as blue for each region area  
  88.                 }  
  89.             }  
  90.         }  
  91.           
  92.         // make it as white color for each center position  
  93.         for(int i=0; i<max; i++)  
  94.         {  
  95.             int crow = (int)labelCenterPos[i][0];  
  96.             int ccol = (int)labelCenterPos[i][1];  
  97.             index = crow * width + ccol;  
  98.             outPixels[index] = (255 << 24) | (255 << 16) | (255 << 8) | 255;   
  99.         }  
  100.           
  101.         setRGB( dest, 0, 0, width, height, outPixels );  
  102.         return dest;  
  103.     }  
  104.   
  105. }  
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算法代码:

  1. package com.gloomyfish.image.moments;  
  2.   
  3. public class GeometricMomentsAlg {  
  4.     private int BACKGROUND = 0; // background color  
  5.     private int labelIndex = 1;  
  6.   
  7.     public GeometricMomentsAlg()  
  8.     {  
  9.         System.out.println("Geometric Moments Algorithm Initialziation...");  
  10.     }  
  11.       
  12.     public int getLabelIndex() {  
  13.         return labelIndex;  
  14.     }  
  15.       
  16.     public void setLabelIndex(int labelIndex) {  
  17.         this.labelIndex = labelIndex;  
  18.     }  
  19.       
  20.     public int getBACKGROUND() {  
  21.         return BACKGROUND;  
  22.     }  
  23.   
  24.     public void setBACKGROUND(int bACKGROUND) {  
  25.         BACKGROUND = bACKGROUND;  
  26.     }  
  27.       
  28.     public double[] getGeometricCenterCoordinate(int[] pixels, int width, int height)  
  29.     {  
  30.         double m00 = moments(pixels, width, height, 0, 0);  
  31.         double xCr = moments(pixels, width, height, 1, 0) / m00; // row  
  32.         double yCr = moments(pixels, width, height, 0, 1) / m00; // column  
  33.         return new double[]{xCr, yCr};  
  34.     }  
  35.   
  36.     public double moments(int[] pixels, int width, int height, int p, int q)  
  37.     {  
  38.         double mpq = 0.0;  
  39.         int index = 0;  
  40.         for(int row=0; row<height; row++)  
  41.         {  
  42.             for(int col=0; col<width; col++)  
  43.             {  
  44.                 index = row * width + col;  
  45.                 if(pixels[index] == BACKGROUND) continue;  
  46.                 mpq += Math.pow(row, p) * Math.pow(col, q);  
  47.             }  
  48.         }  
  49.         return mpq;  
  50.     }  
  51.       
  52.     public double centralMoments(int[] pixel, int width, int height, int p, int q)  
  53.     {  
  54.         double m00 = moments(pixel, width, height, 0, 0);  
  55.         double xCr = moments(pixel, width, height, 1, 0) / m00;  
  56.         double yCr = moments(pixel, width, height, 0, 1) / m00;  
  57.         double cMpq = 0.0;  
  58.         int index = 0;  
  59.         for(int row=0; row<height; row++)  
  60.         {  
  61.             for(int col=0; col<width; col++)  
  62.             {  
  63.                 index = row * width + col;  
  64.                 if(pixel[index] == BACKGROUND) continue;  
  65.                 cMpq += Math.pow(row - xCr, p) * Math.pow(col - yCr, q);  
  66.             }  
  67.         }  
  68.         return cMpq;  
  69.     }  
  70.       
  71.     public double normalCentralMoments(int[] pixel, int width, int height, int p, int q)  
  72.     {  
  73.         double m00 = moments(pixel, width, height, 0, 0);  
  74.         double normal = Math.pow(m00, ((double)(p+q+2))/2.0d);  
  75.         return centralMoments(pixel, width, height, p, q)/normal;  
  76.     }  
  77. }  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM