图像处理之计算连通区域的角度方向

简介: 图像处理之计算连通区域的角度方向

图像处理之计算连通区域的角度方向

一:基本原理

基于空间Moment算法在图像处理与分析中寻找连通区域计算连通区域的中心与角度方

Moment的一阶可以用来计算区域的中心质点,二阶可以用来证明图像的几个不变性

如旋转不变行,放缩不变性等。基于Moment的二阶计算结果,根据如下公式:


可以得到区域的方向角度。

二:算法流程

1.      读入图像数据

2.      根据连通组件标记算法得到区域

3.      根据中心化Moment算法计算角度

4.      根据中心离心值画出渲染黄色线条

三:算法演示效果

四:算法主要源代码

package com.gloomyfish.image.moments;
 
import java.awt.image.BufferedImage;
 
import com.gloomyfish.filter.study.AbstractBufferedImageOp;
import com.gloomyfish.rice.analysis.FastConnectedComponentLabelAlg;
 
public class DirectionRegionMoments 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 the orientation of the region
        int[] input = new int[labels.length];
        GeometricMomentsAlg momentsAlg = new GeometricMomentsAlg();
        momentsAlg.setBACKGROUND(0);
        double[][] labelCenterPos = new double[max][2];
        double[][] centerAngles = new double[max][3];
        for(int i=1; i<=max; i++)
        {
          int numberOfLabel = 0;
          for(int p=0; p<input.length; p++)
          {
            if(labels[p] == i)
            {
              input[p] = labels[p];  
              numberOfLabel++;
            }
            else
            {
              input[p] = 0;
            }
          }
          labelCenterPos[i-1] = momentsAlg.getGeometricCenterCoordinate(input, width, height);
          double m11 = momentsAlg.centralMoments(input, width, height, 1, 1);
          double m02 = momentsAlg.centralMoments(input, width, height, 0, 2);
          double m20 = momentsAlg.centralMoments(input, width, height, 2, 0);
          double m112 = m11 * m11;
          double dd = Math.pow((m20-m02), 2);
          double sum1 = Math.sqrt(dd + 4*m112);
          double sum2 = m02 + m20;
          double a1 = sum2 + sum1;
          double a2 = sum2 - sum1;
          // double ecc = a1 / a2;
          
          double ra = Math.sqrt((2*a1)/Math.abs(numberOfLabel));
          double rb = Math.sqrt((2*a2)/Math.abs(numberOfLabel));
          double angle = Math.atan((2*m11)/(m20 - m02))/2.0;
          centerAngles[i-1][0] = angle;
          centerAngles[i-1][1] = ra;
          centerAngles[i-1][2] = rb;
        }
        
        
        // render the angle/orientation info for each region
        // 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
            }
          }
        }
        
        int labelCount = centerAngles.length;
        for(int i=0; i<labelCount; i++)
        {
          System.out.println("Region " + i + "'s angle = " + centerAngles[i][0]);
          System.out.println("Region " + i + " ra = " + centerAngles[i][1]);
          System.out.println("Region " + i + " rb = " + centerAngles[i][2]);
          double sin = Math.sin(centerAngles[i][0]);
          double cos = Math.cos(centerAngles[i][0]);
          System.out.println("sin = " + sin);
          System.out.println("cos = " + cos);
          System.out.println();
          int crow = (int)labelCenterPos[i][0];
          int ccol = (int)labelCenterPos[i][1];
          int radius = (int)centerAngles[i][1]; // ra
          for(int j=0; j<radius; j++)
          {
            int drow = (int)(crow - j * sin); // it is trick, display correct angle as you see!!!
            int dcol = (int)(ccol + j * cos);
            if(drow >= height) continue;
            if(dcol >= width) continue;
            index = drow * width + dcol;
              outPixels[index] = (255 << 24) | (255 << 16) | (255 << 8) | 0; 
          }
        }
        
        // 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;
  }
 
}

用到的其它JAVA类代码请参见这里:

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

相关文章
|
6月前
|
人工智能 Linux API
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
104 0
技术好文共享:辅助角公式的几何意义
技术好文共享:辅助角公式的几何意义
|
6月前
|
算法 图形学
【头歌 计算机图形学 练习】多边形填充v1.0 (第1关:扫描线填充算法(活动边表AET法) 第2关:边缘填充法 第3关:区域四连通种子填充算法 第4关:区域扫描线种子填充算法)
【头歌 计算机图形学 练习】多边形填充v1.0 (第1关:扫描线填充算法(活动边表AET法) 第2关:边缘填充法 第3关:区域四连通种子填充算法 第4关:区域扫描线种子填充算法)
417 0
|
5月前
|
算法 计算机视觉
图像处理之计算二值连通区域的质心
图像处理之计算二值连通区域的质心
38 0
|
6月前
[C++&OpenCv] 两点距离、三点角度的计算
[C++&OpenCv] 两点距离、三点角度的计算
154 0
|
6月前
[Halcon&几何] 线段中点、端点和角度的计算
[Halcon&几何] 线段中点、端点和角度的计算
266 0
3D孪生场景搭建:模型区域摆放
NSDT 3D孪生场景编辑器区域绘制功能详解。
161 0
3D孪生场景搭建:模型区域摆放
|
数据处理 C++ 计算机视觉
C++-掩膜外数据填补(边缘扩展法)
C++-掩膜外数据填补(边缘扩展法)
【双目视觉】 理想条件下计算物体距离
【双目视觉】 理想条件下计算物体距离
71 0