圖像區域求質心,面積


二值圖像中大於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