图像处理检测质心

2013-12-27 00:15:14 jia20003 阅读数 25504
  • 图像特征描述

    掌握常用的图像边缘检测算子,及Canny算子基本原理 掌握灰度阈值化及大津算法; 掌握常见的图像特征描述方式 了解局部阈值分割、区域生长、分水岭算法及基于轮廓的阈值分割; 通过米粒检测实例掌握图像预处理、分割...

    2622人学习 CSDN就业班
    免费试看

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

一:几何距(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;
	}
}
觉得不错请支持一下

2019-01-10 18:12:14 walkmaner 阅读数 4537
  • 图像特征描述

    掌握常用的图像边缘检测算子,及Canny算子基本原理 掌握灰度阈值化及大津算法; 掌握常见的图像特征描述方式 了解局部阈值分割、区域生长、分水岭算法及基于轮廓的阈值分割; 通过米粒检测实例掌握图像预处理、分割...

    2622人学习 CSDN就业班
    免费试看

 

本文介绍纯理论部分,至于FPGA实现就不多说了。

常见的质心算法有以下几种,可以应用于不同的场合。

(1)普通质心算法

   

其中^{I_{ij}}为二维图像上每个像素点所接收到的光强,该算法适用于没有背景噪声,背景噪声一致或信噪比较高的情况。

 

(2) 强加权质心算法

 

        其原理是将光斑中心较近的部分区域像素值增强,使得对光斑影响较大点的影响力进一步加大,提高质心探测精度,即使光斑形状不近似高斯分布,该方法依然能较准确的探测光斑质心。

 

(3)阈值质心算法 
先对图像进行阈值分割,再使用COG算法,此时的质心探测误差要小于只用COG算法时的质心探测误差。该算法关键在阈值的选取。选取阈值的方法有很多。常用的有固定值阈值,经验阈值和直方图阈值。目前应用较广泛的是自适应阈值。自适应阈值具有阈值随图像的变化而变化以达到最好效果的优点。自适应阈值中最常用的是小波自适应阈值。该方法可以很好的去除高斯白噪声。但传统的小波变换在信号降噪中计算不足,所以可以将小波降噪算法进行改进。

 

 

图像质心即图像灰度的重心,设图像有i,j两个方向,m,n分别为i,j方向像素的数量,(,)gij为像素点(,)ij处的灰度值,则图像质心位置坐标表达

  

 

 

 

 

单点激光测距原理

单点激光测距原理图如图所示, 

 

 

激光头Laser与摄像头在同一水平线(称为基准线)上,其距离为s,摄像头焦距为f,激光头与基准线的夹角为β。激光头Laser与摄像头在同一水平线(称为基准线)上。假设目标物体Object在点状激光器的照射下,反射回摄像头成像平面的位置为点P。

 

由几何知识可作相似三角形,激光头、摄像头与目标物体组成的三角形,相似于摄像头、成像点P与辅助点P′。

  设 PP′=x。则由相似三角形可得:  

                                                           f/x=q/s  ==>  q=fs/x                    

其中  X可分为两部分计算:          X=x1+x2= f/tan⁡β + pixelSize* position

 其中pixelSize是像素单位大小, position是成像的像素坐标相对于成像中心的位置。

 最后,可求得距离d:                       d=q/sin⁡β

 


线状激光三角测距原理

 

将激光光条的中心点P1、成像点P1′、摄像头、激光头作为基准面,中心点P1就符合单点结构光测距。对于任一点(该点不在基准面上)

如上图所示,将成像平面镜像到另一侧。

其中P1′,P2′和分别是P1和P2的成像位置,对于点P2、成像点P2′、摄像头、激光头所形成的平面,与基准面存在夹角θ,也符合单点结构光测距。此时的焦距为f′,x的几何意义同单点激光测距原理类似。

如上图所示,将成像平面镜像到另一侧。其中P1′,P2′和分别是P1和P2的成像位置,
     

 由相似三角形原理:    

                                                               d'/baseline=f'/x


d′是P2与baseline所成平面上P2到底边的高(类比于单点激光测距原理中的q)。同样x可分为两部分计算d′是P2与baseline所成平面上P2到底边的高(类比于单点激光测距原理中的q)。

同样x可分为两部分计算                       x=f'/tan⁡β   + pixelSize* position

上述中的平面与基准面的夹角为θ上述中的平面与基准面的夹角为θ
                                                                   f'/f=cos⁡θ 

                                                                    tan⁡θ=(|P2'.y-P1'.y|)/f


可求得f′:可求得f′:
                                                                 f'=f/cos⁡(arctan⁡((P2'.y-P1'.y)/f))  
 

代入式中可求得d.

 

本文的参考资料来自以下链接

 

https://www.sogou.com/link?url=DSOYnZeCC_owkDvmYG0gMz-JrNZwwuWKymS_APuk7tP1C5Jjw8b4Bt86nTG2etG3NQv8G0S-AYCuLaNMGv04nw..

https://wenku.baidu.com/view/d1529dbef121dd36a32d8272.html?sxts=1547103591980

https://blog.csdn.net/Lrisfish/article/details/77838690?utm_source=copy

另附  matlab2018云盘链接  

密码  lw68 pan.baidu.com/s/11NVkjPBX3qYmCNQuC_hX0Q

 

2016-03-22 16:26:09 qq_23100787 阅读数 10653
  • 图像特征描述

    掌握常用的图像边缘检测算子,及Canny算子基本原理 掌握灰度阈值化及大津算法; 掌握常见的图像特征描述方式 了解局部阈值分割、区域生长、分水岭算法及基于轮廓的阈值分割; 通过米粒检测实例掌握图像预处理、分割...

    2622人学习 CSDN就业班
    免费试看

这篇文章的起因是因为我在做一个项目,其中的要求就是求图像的质心,这个算法初步实现了一个功能:
给出一张图片如下:
这里写图片描述

然后把这个图片保存到d:\测试.jpg目录,最后运行我的函数即可

写的思路:
对于图片,质心肯定会数值不一样,这时候可以通过这种想法,然后设定阈值,对于图片数据进行二重循环,最终找到质心那块范围的坐标,最后就能够求出质心

下面附上源代码:(一个名为centroid的matlab函数)

function y = centroid()
I = imread('d:\\测试1.jpg');
[M,N,P] = size(I);
int8 sumx ;
int8 sumy ;
int8 count ;
 sumx = 0;
 sumy = 0;
 count = 0;
 int8 R ;
 int8 G ;
 int8 B ;
 R = 20; G = 200;B = 200;
for i = 1:1:M
    for j = 1:1:N
            if I(i,j,1)>=R &&  I(i,j,2)>=G && I(i,j,3)>=B
                 sumx = sumx + i;
                 sumy = sumy +j;
                 count = count + 1;
            end
    end
end
sumx = sumx / count;    %sumx存储了x轴坐标
sumy = sumy / count;    %sumy存储了y轴坐标
disp(sumx);disp(sumy);

运行效果图:
这里写图片描述

运行结果已经求出了质心

2012-12-16 13:06:34 zhufanqie 阅读数 23065
  • 图像特征描述

    掌握常用的图像边缘检测算子,及Canny算子基本原理 掌握灰度阈值化及大津算法; 掌握常见的图像特征描述方式 了解局部阈值分割、区域生长、分水岭算法及基于轮廓的阈值分割; 通过米粒检测实例掌握图像预处理、分割...

    2622人学习 CSDN就业班
    免费试看

     
        下面贴出我的一个很简单且很容易理解的质心标志代码出来,供大家参考,代码都写了注释的,详情如下:   

clear;clc;close all;
I=imread('E:\xxx.jpg');%读取原图像
figure(1);imshow(I);%显示原图像

I_gray=rgb2gray(I);%原图像变为灰度图像
level=graythresh(I_gray);%计算图像I_gray的全局阈值,level为标准化灰度值,其范围为[0 1]
[height,width]=size(I_gray);%计算灰度图像的长宽
I_bw=im2bw(I_gray,level);%im2bw使用阈值level将灰度图像转换为二值图像.
figure(2);imshow(I_bw);%显示二值图像(背景为白色)

for i=1:height %%循环中进行反色
    for j=1:width   
        if I_bw(i,j)==1      
            I_bw(i,j)=0;  
        else I_bw(i,j)=1; 
        end
    end
end
figure(3);imshow(I_bw);%显示取反后的二值图像(背景为黑色)

[L,num]=bwlabel(I_bw,8);%bwlabel标注二值图像I_bw中的目标物体,返回标识矩阵L和I_bw中目标物体的数量num,8表示连通数.
plot_x=zeros(1,num);%%zeros(m,n)产生m×n的全0矩阵.用于记录质心位置的横坐标
plot_y=zeros(1,num);%zeros(m,n)产生m×n的全0矩阵.用于记录质心位置的纵坐标

for k=1:num  %%num个区域依次统计质心位置    
    sum_x=0;    sum_y=0;    area=0; %初始化
    for i=1:height   
        for j=1:width 
            if L(i,j)==k     
                sum_x=sum_x+i;  %计算第K区域的横坐标总和
                sum_y=sum_y+j;  %计算第K区域的纵坐标总和 
                area=area+1;    %计算第K区域的由多少个坐标点表示
            end
        end
    end
    plot_x(k)=fix(sum_x/area);  %计算第K区域的质心横坐标
    plot_y(k)=fix(sum_y/area);%计算第K区域的质心纵坐标
end

figure(4);imshow(I_bw);%显示取反后的二值图像(背景为黑色),并在图上标注质心点位置
for i=1:num
    hold  on
    plot(plot_y(i) ,plot_x(i), '*')
end

运行出来的图例为:

 

 

        从上面的图片看来,此方法对子区域较明显的图片有较强的分辨率,但是针对图片的子区域不那么的显著地情况呢,下面我们用另一幅图片进行测试,运行结果如下:

 

 

 

      所以对图片特定区域求质心还有待进一步研究。


 

2019-09-23 17:15:53 Vichael_Chan 阅读数 452
  • 图像特征描述

    掌握常用的图像边缘检测算子,及Canny算子基本原理 掌握灰度阈值化及大津算法; 掌握常见的图像特征描述方式 了解局部阈值分割、区域生长、分水岭算法及基于轮廓的阈值分割; 通过米粒检测实例掌握图像预处理、分割...

    2622人学习 CSDN就业班
    免费试看

数字图像处理学习笔记(一):特征检测和匹配概述

参考博客:

1、特征点概述

如何高效且准确的匹配出两个不同视角的图像中的同一个物体,是许多计算机视觉应用中的第一步。虽然图像在计算机中是以灰度矩阵的形式存在的,但是利用图像的灰度并不能准确的找出两幅图像中的同一个物体。这是由于灰度受光照的影响,并且当图像视角变化后,同一个物体的灰度值也会跟着变化。所以,就需要找出一种能够在相机进行移动和旋转(视角发生变化),仍然能够保持不变的特征,利用这些不变的特征来找出不同视角的图像中的同一个物体。

为了能够更好的进行图像匹配,需要在图像中选择具有代表性的区域,例如:图像中的角点、边缘和一些区块,但在图像识别出角点是最容易,也就是说角点的辨识度是最高的。所以,在很多的计算机视觉处理中,都是提取角点作为特征,对图像进行匹配,例如SFM,视觉SLAM等。

但是,单纯的角点并不能很好的满足我们的需求,例如:相机从远处得到的是角点,但是在近处就可能不是角点;或者,当相机旋转后,角点就发生了变化。为此,计算机视觉的研究者们设计了许多更为稳定的的特征点,这些特征点不会随着相机的移动,旋转或者光照的变化而变化。例如:SIFT,SURF,ORB

一个图像的特征点由两部分构成:

  • 关键点(Keypoint):关键点指的是该特征点在图像中的位置,有些还具有方向、尺度信息;
  • 描述子(Descriptor):描述子通常是一个向量,按照人为的设计的方式,描述关键点周围像素的信息
    通常描述子是按照外观相似的特征应该有相似的描述子设计的。因此,在匹配的时候,只要两个特征点的描述子在向量空间的距离相近,就可以认为它们是同一个特征点。

2、特征点的匹配

特征点的匹配通常需要以下三个步骤:

1)提取图像中的关键点,这部分是查找图像中具有某些特征(不同的算法有不同的)的像素;
2)根据得到的关键点位置,计算特征点的描述子;
3)根据特征点的描述子,进行匹配;

这里先介绍下特征点的描述子,一个好的描述子是准确匹配的基础,关键点的提取和特征点的匹配,在后面介绍。

3、特征点描述子

从图像中提取到特征的关键点信息,通常只是其在图像的位置信息(有可能包含尺度和方向信息),仅仅利用这些信息无法很好的进行特征点的匹配,所以就需要更详细的信息,将特征区分开来,这就是特征描述子。另外,通过特征描述子可以消除视角的变化带来图像的尺度和方向的变化,能够更好的在图像间匹配。

特征的描述子通常是一个精心设计的向量,描述了关键点及其周围像素的信息。为了能够更好的匹配,一个好的描述子通常要具有以下特性:

  • 不变性:指特征不会随着图像的放大缩小旋转而改变;
  • 鲁棒性:对噪声、光照或者其他一些小的形变不敏感;
  • 可区分性:每一个特征描述子都是独特的,具有排他性,尽可能减少彼此间的相似性。

其中描述子的可区分性和其不变性是矛盾的,一个具有众多不变性的特征描述子,其区分局部图像内容的能力就比较稍弱;而如果一个很容易区分不同局部图像内容的特征描述子,其鲁棒性往往比较低。所以,在设计特征描述子的时候,就需要综合考虑这三个特性,找到三者之间的平衡

特征描述子的不变性主要体现在两个方面:

  • 尺度不变性 (Scale Invarient)
    指的是同一个特征,在图像的不同的尺度空间保持不变。匹配在不同图像中的同一个特征点经常会有图像的尺度问题,不同尺度的图像中特征点的距离变得不同,物体的尺寸变得不同,而仅仅改变特征点的大小就有可能造成强度不匹配。如果描述子无法保证尺度不变性,那么同一个特征点在放大或者缩小的图像间,就不能很好的匹配。为了保持尺度的不变性,在计算特征点的描述子的时候,通常将图像变换到统一的尺度空间,再加上尺度因子
  • 旋转不变性 (Rotation Invarient)
    指的是同一个特征,在成像视角旋转后,特征仍然能够保持不变。和尺度不变性类似,为了保持旋转不变性,在计算特征点描述子的时候,要加上关键点的方向信息。

为了有个更直观的理解,下面给出SIFT,SURF,BRIEF描述子计算方法对比:

在这里插入图片描述
从上表可以看出,SIFT,SURF和BRIEF描述子都是一个向量,只是维度不同。其中,SIFT和SURF在构建特征描述子的时候,保存了特征的方向和尺度特征,这样其特征描述子就具有尺度和旋转不变性;而BRIEF描述子并没有尺度和方向特征,不具备尺度和旋转不变性。

4、常用的特征点算法

上面提到图像的特征点包含两个部分:

  • 特征点的提取,在图像检测到特征点的位置。
  • 特征点的描述,也就是描述子。

在图像中提取到关键点的位置信息后,为了能够更有效的匹配(主要是保证尺度和旋转不变性),通常使用一个向量来描述关键点及其周围的信息。特征的描述子,在特征点的匹配中是非常重要的,上一小节中对其应该具有的性质做了介绍。但具体到一个算法来说,可能其既有特征点的提取算法也有特征点描述子的算法,也有可能其仅仅是一个特征点提取算法或者是特征点的描述子算法。在本小节就常用的特征点算法做一个简要的说明。

一、SIFT

提到特征点算法,首先就是大名鼎鼎的SIFT算法了。SIFT的全称是Scale Invariant Feature Transform,尺度不变特征变换,2004年由加拿大教授David G.Lowe提出的。SIFT特征对旋转、尺度缩放、亮度变化等保持不变性,是一种非常稳定的局部特征。

SIFT算法主要有以下几个步骤:

  • 1)高斯差分金字塔的构建
    使用组和层的结构构建了一个具有线性关系的金字塔(尺度空间),这样可以在连续的高斯核尺度上查找图像的特征点;另外,它使用一阶的高斯差分来近似高斯的拉普拉斯核,大大的减少了运算量。
  • 2)尺度空间的极值检测及特征点的定位
    搜索上一步建立的高斯尺度空间,通过高斯差分来识别潜在的对尺度和旋转不变的特征点。但是,在离散空间中,局部极值点可能并不是真正意义的极值点,真正的极值点有可能落在离散点的间隙中,SIFT通过尺度空间DoG函数进行曲线拟合寻找极值点
    特征方向赋值
  • 3)基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向,后续的所有操作都是对于关键点的方向、尺度和位置进行变换,从而提供这些特征的不变性。
  • 4)特征描述子的生成
    通过上面的步骤已经找到的SIFT特征点的位置、方向、尺度信息,最后使用一组向量来描述特征点及其周围邻域像素的信息。

SIFT算法中及包含了特征点的提取算法,也有如何生成描述子的算法,更进一步的SIFT算法介绍可参看:

二、SURF

SURF全称 Speeded Up Robust Features “加速版的具有鲁棒性的特征”,是在SIFT算法的基础上提出的,主要针对SIFT算法运算速度慢,计算量大的缺点进行了改进。
SURF的流程和SIFT比较类似,这些改进体现在以下几个方面:

  • 1)特征点检测是基于Hessian矩阵,依据Hessian矩阵行列式的极值来定位特征点的位置。并且将Hession特征计算与高斯平滑结合在一起,两个操作通过近似处理得到一个核模板。
  • 2)在构建尺度空间时,使用box filter与源图像卷积,而不是使用DoG算子。
  • 3)SURF使用一阶Haar小波在x、y两个方向的响应作为构建特征向量的分布信息。

三、FAST特征点提取算法

SIFT和SURF是非常好的,稳定的特征点算法,但运算速度是其一大弊端,无法做到实时的特征提取和匹配,其应用就有了很大的局限性。FAST特征提取算法弥补了这一局限,检测局部像素灰度变化明显的地方,以速度快而著称,其全称为:Features From Accelerated Segment Test。在FAST算法的思想很简单:如果一个像素与周围邻域的像素差别较大(过亮或者过暗),那么可以认为该像素是一个角点。和其他的特征点提取算法相比,FAST算法只需要比较像素和其邻域像素的灰度值大小,十分便捷。

FAST算法提取角点的步骤:

  • 1)在图像中选择像素p,假设其灰度值为:Ip
  • 2)设置一个阈值T,例如:Ip 的20%
  • 3)选择p周围半径为3的圆上的16个像素,作为比较像素
  • 4)假设选取的圆上有连续的N个像素大于 Ip+T 或者 Ip-T,那么可以认为像素p就是一个特征点。
    (N通常取12,即为FAST-12;常用的还有FAST-9,FAST-11)。

FAST算法只检测像素的灰度值,其运算速度极快,同时不可避免的也有一些缺点:

  • 检测到的特征点过多并且会出现“扎堆”的现象。这可以在第一遍检测完成后,使用非最大值抑制(Non-maximal suppression),在一定区域内仅保留响应极大值的角点,避免角点集中的情况。
  • FAST提取到的角点没有方向和尺度信息

上面的介绍的SIFT和SURF算法都包含有各自的特征点描述子的计算方法,而FAST不包含特征点描述子的计算,仅仅只有特征点的提取方法,这就需要一个特征点描述方法来描述FAST提取到的特征点,以方便特征点的匹配。下面介绍一个专门的特征点描述子的计算算法:

BRIEF描述子

BRIEF是一种二进制的描述子,其描述向量是0和1表示的二进制串。0和1表示特征点邻域内两个像素(p和q)灰度值的大小:如果p比q大则选择1,反正就取0。在特征点的周围选择128对这样的p和q的像素对,就得到了128维由0,1组成的向量。那么p和q的像素对是怎么选择的呢?通常都是按照某种概率来随机的挑选像素对的位置。

BRIEF使用随机选点的比较,速度很快,而且使用二进制串表示最终生成的描述子向量,在存储以及用于匹配的比较时都是非常方便的,其和FAST的搭配起来可以组成非常快速的特征点提取和描述算法。

四、ORB算法

在这里插入图片描述
ORB的全称是Oriented FAST and Rotated BRIEF,是目前来说非常好的能够进行的实时的图像特征提取和描述的算法,它改进了FAST特征提取算法,并使用速度极快的二进制描述子BRIEF。
针对FAST特征提取的算法的一些确定,ORB也做了相应的改进。

  • 使用非最大值抑制,在一定区域内仅仅保留响应极大值的角点,避免FAST提取到的角点过于集中。
  • FAST提取到的角点数量过多且不是很稳定,ORB中可以指定需要提取到的角点的数量N,然后对FAST提取到的角点分别计算Harris响应值,选择前N个具有最大响应值的角点作为最终提取到的特征点集合。
  • FAST提取到的角点不具有尺度信息,在ORB中使用图像金字塔,并且在每一层金字塔上检测角点,以此来保持尺度的不变性。
  • FAST提取到的角点不具有方向信息,在ORB中使用灰度质心法(Intensity Centroid)来保持特征的旋转不变性。

FAST-12算法:

添加预测试操作,于每个像素,直接检测在邻域圆上的第1,5,9,13个像素的亮度,只有当这四个像素当中有三个同时大于IP+T或者小于IP-T的时候,当前像素才有可能是是角点。

  • 问题1:FAST特征点的数量很多,并且不是确定,而大多数情况下,我们希望能够固定特征点的数量。

解决方法:在ORB当中,我们可以指定要提取的特征点数量。对原始的FAST角点分别计算Harris的响应值,然后选取前N个点具有最大相应值的角点,作为最终角点的集合。

  • 问题2:FAST角点不具有方向信息和尺度问题。

解决方法:尺度不变性构建的图像的金字塔,并且从每一层上面来检测角点。旋转性是由灰度质心法实现。

灰度质心法:质心是指以图像块灰度值作为权重的中心。(目标是为了找到方向)

1)在一个小的图像块B中,定义图像块的矩为:
在这里插入图片描述
2)通过矩找到图像块的质心

在这里插入图片描述

3)连接图像块的几何中心o与质心C,得到一个oc的向量,把这个向量的方向定义特征点的方向
在这里插入图片描述

图像处理与识别

阅读数 9098