图像特征—FAST关键点

图像特征—FAST关键点

一、引言

最近在看视觉slam十四讲这本书,里面关于图像特征点的一些总结非常值得学习一下。

1.特征点所应具有的性质

(1)可重复性:相同的特征可以在不同的图像中找到;
(2)可区别性:不同的特征具有不同的表达;
(3)高效率:同一图像中,特征点的数量应远小于像素的数量;
(4)本地性:特征仅与一小片图像区域有关。

2.常见的一些特征提取方法的区别

(1)SIFT(尺度不变特征变换)特征:属于最为经典的一种,该方法充分地考虑了在图像变换过程中出现的光照、
尺度、旋转等变化,因此也使得这种方法的计算量极大,使用非常耗时。
(2)FAST关键点:属于计算特别快的一种特征点检测方法,之所以快是因为这种方法只是只是找到了关键点,
并没有相应的描述子。
(3)ORB特征:该方法改进了FAST检测不具有方向性的问题,并且采用速度极快的二进制描述子BRIEF,使整个
图像特征的提取速度大大加快。
补充:特征点是由关键点和描述子两部分组成。关键点是指该特征点在图像中的位置,而描述子是描述特征点
周围像素的信息。

二、FAST关键点

1.检测思路

如果一个像素与邻域的像素差别较大(过亮或过暗),那么它更可能是角点。

2.检测过程

(1)在图像中选取像素p,假设它的亮度为Ip;
(2)设置一个阈值T,比如为Ip的五分之一;
(3)以像素p为中心,选取半径为3的圆上的16个像素点;
(4)假如选取的圆上有连续的N个点的亮度大于Ip+T或者小于Ip-T,那么像素p可以被认为是特征点(N通常取12,
即FAST-12。其他的常用的N取值为9和11,即FAST-9和FAST-11);
(5)循环以上四步,对每个像素执行相同的操作。
补充:在FAST-12中,为提升检测的效率,通常会增加一步预筛选,具体操作如下:
	对每个像素,直接检测邻域圆上的第1、5、9、13个像素的亮度,只有当这4个像素中有3个同时大于Ip+T或小于
	Ip-T时,当前像素才有可能是一个角点,否则就直接排除。

3.FAST-12代码如下

#include <iostream>
#include <opencv2/opencv.hpp>
class FastKeyPointDec{
public:
    /* 功能:判断当前像素点是否为角点;
     * 输入:arg1:Ip当前像素点的亮度值
     *      arg2:t为筛选阈值
     *      arg3:IpVec为以当前像素点为中心,半径为3的周围16个像素
     * 输出:true or false
     * */
    bool isKeyPoint(double Ip,double T,std::vector<double>IpVec){
        assert(IpVec.size()==16);
        int n=0;    //统计特征点数量
        //assert(Ip>=T);
        //预筛选:1 5 9 13四个点至少有三个同时满足条件可进行下一步
        int a1=IpVec[0]>Ip+T || IpVec[0]<Ip-T;
        int a2=IpVec[4]>Ip+T || IpVec[4]<Ip-T;
        int a3=IpVec[8]>Ip+T || IpVec[8]<Ip-T;
        int a4=IpVec[12]>Ip+T || IpVec[12]<Ip-T;
        if(a1+a2+a3+a4<=2){
            return false;
        }
        for(size_t i=0;i<16;i++){
            double temp=IpVec[i];
            if(temp>Ip+T||temp<Ip-T){
                n++;
            }
        }
        if(n>=12){
            return true;
        }else{
            return false;
        }
    }
    /* 功能:对一幅图像进行角点检测
     * 输入:arg1:输入检测的图像
     *      arg2:角点坐标
     *      arg3:阈值
     * 输出:角点检测的结果
     * */
    void fastDectKey(const cv::Mat srcImg,std::vector<cv::Point>&keyPoint,double T){
        assert(!srcImg.empty());
        cv::Mat img;
        int row=srcImg.rows;
        int col=srcImg.cols;
        std::vector<double>ipVec(0);
        cv::cvtColor(srcImg,img,cv::COLOR_BGR2GRAY);
        //assert(img.channels()==1);
        for(int i=3;i<row-3;i++){
            for(int j=3;j<col-3;j++){
                double ipval=img.at<uchar>(i,j);
                ipVec.push_back(img.at<uchar>(i-3,j));ipVec.push_back(img.at<uchar>(i-3,j+1));   //1,2
                ipVec.push_back(img.at<uchar>(i-2,j+2));    //3
                ipVec.push_back(img.at<uchar>(i-1,j+3));ipVec.push_back(img.at<uchar>(i,j+3));ipVec.push_back(img.at<uchar>(i+1,j+3));//4,5,6
                ipVec.push_back(img.at<uchar>(i+2,j+2));    //7
                ipVec.push_back(img.at<uchar>(i+3,j+1));ipVec.push_back(img.at<uchar>(i+3,j));ipVec.push_back(img.at<uchar>(i+3,j-1));//8,9,10
                ipVec.push_back(img.at<uchar>(i+2,j-2));    //11
                ipVec.push_back(img.at<uchar>(i+1,j-3));ipVec.push_back(img.at<uchar>(i,j-3));ipVec.push_back(img.at<uchar>(i-1,j-3));//12,13,14
                ipVec.push_back(img.at<uchar>(i-2,j-2));    //15
                ipVec.push_back(img.at<uchar>(i-3,j-2));    //16
                if(ipVec.size()==16){
                    if(isKeyPoint(ipval,T,ipVec)){
                        keyPoint.push_back(cv::Point(j,i));
                        cv::circle(srcImg,cv::Point(j,i),2,cv::Scalar(255,255,0),1,cv::LINE_8);
                    }
                    ipVec.clear();
                }
            }
        }
        cv::imshow("res-key",srcImg);
    }
};
int main() {
    std::cout << "Hello, World!" << std::endl;
    cv::Mat src=cv::imread("../1.png");
    if(src.empty()){
        std::cout<<"no imagen";
    }
    FastKeyPointDec fast;
    std::vector<cv::Point>pt;
    //cv::flip(src,src,1);
    fast.fastDectKey(src,pt,30);
    cv::imshow("src",src);
    cv::waitKey(0);
    return 0;
}

检测效果如下
在这里插入图片描述

三、总结

观察FAST-12的检测结果,图像中大多亮度变化明显的角点都有被检测出来,但是单纯的论特征点检测来说,效果
不甚理想。其原因大概有以下三点:
(1)FAST算法只是比较图像亮度的大小,所以亮度变化明显的容易被检测出来,而在一些亮度变化缓慢的地方的
特征点容易被忽略,因此可以在预处理时增加一些边缘锐化等一些操作,增加一下图像的对比度,可以较好的提升检测效果。
(2)筛选阈值选取的不够合理;
(3)检测的图像不够理想。
另外,在FAST关键点检测完毕后,还需要使用非极大值抑制法再进行一次筛选,以避免特征点集中的问题。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>