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

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

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

一:基本原理

基于空间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

相关文章
技术好文共享:辅助角公式的几何意义
技术好文共享:辅助角公式的几何意义
|
5月前
|
算法 计算机视觉
图像处理之计算二值连通区域的质心
图像处理之计算二值连通区域的质心
34 0
|
6月前
|
算法 图形学
【头歌 计算机图形学 练习】多边形填充v1.0 (第1关:扫描线填充算法(活动边表AET法) 第2关:边缘填充法 第3关:区域四连通种子填充算法 第4关:区域扫描线种子填充算法)
【头歌 计算机图形学 练习】多边形填充v1.0 (第1关:扫描线填充算法(活动边表AET法) 第2关:边缘填充法 第3关:区域四连通种子填充算法 第4关:区域扫描线种子填充算法)
392 0
|
6月前
[C++&OpenCv] 两点距离、三点角度的计算
[C++&OpenCv] 两点距离、三点角度的计算
148 0
|
6月前
[Halcon&几何] 线段中点、端点和角度的计算
[Halcon&几何] 线段中点、端点和角度的计算
255 0
三维之外的更高维度,数学家发现了无限可能的黑洞形状
三维之外的更高维度,数学家发现了无限可能的黑洞形状
146 0
|
智慧交通
智慧交通day03-车道线检测实现06:车道线定位及拟合+代码实现
我们根据前面检测出的车道线信息,利用直方图和滑动窗口的方法,精确定位车道线,并进行拟合。
249 0
|
智慧交通
智慧交通day03-车道线检测实现05:透视变换+代码实现
为了方便后续的直方图滑窗对车道线进行准确的定位,我们在这里利用透视变换将图像转换成俯视图,也可将俯视图恢复成原有的图像
176 0
【双目视觉】 理想条件下计算物体距离
【双目视觉】 理想条件下计算物体距离
71 0
|
传感器 机器学习/深度学习 编解码
3D多目标跟踪新思路!基于多传感器融合的加权几何距离关联方法
在自动驾驶领域,3D多目标跟踪(MOT)作为整个感知系统中的关键任务之一发挥着重要作用,它确保了车辆导航和运动规划的高效和安全。大多数现有的MOT方法基于检测,即通过检测跟踪(TBD),并且仅使用单个深度传感器,如激光雷达来检测和跟踪目标。然而,长距离的非常稀疏的点云导致这些方法无法生成非常精确的检测结果,从而影响跟踪结果。因此,本文提出了一种基于传感器融合的3D MOT方法,利用激光雷达和摄像机的检测结果。
3D多目标跟踪新思路!基于多传感器融合的加权几何距离关联方法