Fast角点检测算法

1.角点定义

  角点是一种局部特征,具有旋转不变性和不随光照条件变化而变化的特点,一般将图像中曲率足够高或者曲率变化明显的点作为角点。检测得到的角点特征通常用于图像匹配、目标跟踪、运动估计等方面。

2.Fast检测角点

1)基本思想

  E.Rosten和T.Drummond两位大佬在06年一篇文章中提出了FAST特征算法,基本思想十分简单:以某个像素点为圆心,某半径的圆周上其他像素点与圆心像素点特性差异达到某种标准时即认为该点就是角点。

2)数学模型

  

  经过测试发现,选取的圆形半径为3时可以兼顾检测结果和效率。如上图所示,点p与半径为3的圆周上的16个像素点比较其灰度差,若灰度差绝对值大于某阈值的点数超过设定数目(一般可以取9/10/11/12),则认为该点是角点。

     使用小技巧加速该算法,这里取设定数目为12。

  (1)判断点1和点9灰度值与点p差值绝对值是否都大于阈值,如果是则继续;否则pass该点

      (2)判断点1、点5、点9、点13四点与点p灰度值差值大于阈值的数目是否大于2,如果是则继续;否则pass该点

      (3)判断圆周上16点与点p灰度值差值大于阈值的数目是否不小于12,如果是则认为该点是候选点;否则pass该点

  对图像中所有像素点进行上述操作后,得到候选点点集。通常使用非极大值抑制过滤局部非极大值点,在这之前需要先计算各候选点的score,score就定义为16个点与中心点灰度值差值的绝对值总和

3.opencv实现

    个人使用vs2012+opencv2.4.13作为开发环境,具体实现如下

#include <iostream>
#include <core/core.hpp>
#include <highgui/highgui.hpp>
#include <imgproc/imgproc.hpp>
#include <features2d/features2d.hpp>

using namespace std;
using namespace cv;


int getSum(uchar *p, int length)
{
    int sum = 0;
    for(int i=0;i<length; i++)
    {
        sum += *(p+i);
    }
    return sum;
}

int main(int argc, char* argv[])
{
    /* 1.读入图像 */
    Mat image = imread("../church01.jpg", 0);
    if(!image.data)
        return 0;

    namedWindow("Original Image");
    imshow("Original Image", image);

    Mat fastImg(image.size(), CV_8U, Scalar(0));//用于保存Fast特征点候选点
    Mat fastScore(image.size(), CV_32F, Scalar(0));//用于计算候选点score
    vector<Point> points;
    int rows, cols, threshold;
    rows = image.rows;
    cols = image.cols;
    threshold = 50;

    /* 2.检测Fast特征点 */
    for(int x = 3; x < rows - 3; x++)
    {
        for(int y = 3; y < cols - 3; y++)
        {
            uchar delta[16] = {0};
            uchar diff[16] = {0};
            delta[0] = (diff[0] = abs(image.at<uchar>(x,y) - image.at<uchar>(x, y-3))) > threshold;
            delta[8] = (diff[8] = abs(image.at<uchar>(x,y) - image.at<uchar>(x, y+3))) > threshold;
            if(getSum(delta, 16) == 0)
                continue;
            else
            {
                delta[12] = (diff[12] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-3, y))) > threshold;
                delta[4] = (diff[4] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+3, y))) > threshold;
                if(getSum(delta, 16) < 3)
                    continue;

                else
                {
                    delta[1] = (diff[1] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+1, y-3))) > threshold;
                    delta[2] = (diff[2] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+2, y-2))) > threshold;
                    delta[3] = (diff[3] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+3, y-1))) > threshold;
                                
                    delta[5] = (diff[5] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+3, y+1))) > threshold;
                    delta[6] = (diff[6] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+2, y+2))) > threshold;
                    delta[7] = (diff[7] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+1, y+3))) > threshold;

                    delta[9] = (diff[9] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-1, y+3))) > threshold;
                    delta[10] = (diff[10] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-2, y+2))) > threshold;
                    delta[11] = (diff[11] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-3, y+1))) > threshold;

                    delta[13] = (diff[13] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-3, y-1))) > threshold;
                    delta[14] = (diff[14] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-2, y-2))) > threshold;
                    delta[15] = (diff[15] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-1, y-3))) > threshold;

                    if(getSum(delta, 16) >= 12)
                    {
                        points.push_back(Point(y,x));
                        fastScore.at<float>(x,y) = getSum(diff, 16);
                        fastImg.at<uchar>(x,y) = 255;
                    }
                }
            }
        }

    }

    vector<Point>::const_iterator itp = points.begin();
    while(itp != points.end())
    {
        circle(image, *itp, 3, Scalar(255), 1);
        ++itp;
    }
    //未进行非极大值抑制之前的特征点检测结果
    namedWindow("Fast Image");
    imshow("Fast Image", image);

    /* 3.对特征点候选点进行非极大值抑制 */
    image = imread("../church01.jpg", 0);
    Mat dilated(fastScore.size(), CV_32F, Scalar(0));
    Mat localMax;
    Mat element(7, 7, CV_8U, Scalar(1));
    dilate(fastScore, dilated, element);
    compare(fastScore, dilated, localMax, CMP_EQ);
    bitwise_and(fastImg, localMax, fastImg);

    for(int x = 0;x < fastImg.cols; x++)
    {
        for(int y = 0; y < fastImg.rows; y++)
        {
            if(fastImg.at<uchar>(y,x))
            {
                circle(image, Point(x,y), 3, Scalar(255), 1);

            }
        }
    }
    //进行非极大值抑制之后的特征点检测结果
    namedWindow("Fast Image2");
    imshow("Fast Image2", image);

    waitKey();
    return 0;
}

        代码运行结果如下,比较第2/3张图可以发现,非极大值抑制具有过滤掉局部区域中非极大值角点的作用。

4.算法小结

       该算法思想简单,运算量很小,适合实时检测方面的应用。不过也有缺点,主要表现为对于边缘点与噪点区分能力不强,当然后面也有很多人在此基础上加以改进提高算法的稳定性。

5.参考文献

 [1]《opencv2计算机视觉编程手册》

 [2]【特征检测】FAST特征检测算法(http://blog.csdn.net/hujingshuang/article/details/46898007)

  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FAST(Features from Accelerated Segment Test)角点检测算法是一种用于实时图像处理的高效角点检测算法。该算法通过比较像素点与其邻域像素点的灰度值来判断该点是否为角点,从而实现快速检测角点的功能。 FAST角点检测算法的具体实现步骤如下: 1. 选择一个像素点p作为候选角点; 2. 设置一个阈值t,将p的灰度值与其邻域内所有像素的灰度值进行比较,如果p的灰度值与其中n个像素的灰度值之差都大于t,则认为该点为角点; 3. 为了避免检测到邻域内的多个像素点作为角点,需要对检测到的角点进行非极大值抑制,即只保留灰度值最大的角点。 需要注意的是,在实际应用中,需要根据图像的具体特点来调整算法的参数,以获得更好的效果。同时,FAST角点检测算法也存在一些限制,比如对噪声和图像变换的鲁棒性较差,需要结合其他算法进行增强。 以下是使用OpenCV库实现FAST角点检测算法的Python代码示例: ```python import cv2 import numpy as np img = cv2.imread('test.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) fast = cv2.FastFeatureDetector_create() kp = fast.detect(gray, None) img2 = cv2.drawKeypoints(img, kp, None, color=(0,255,0)) cv2.namedWindow("FAST corner detector", cv2.WINDOW_NORMAL) cv2.imshow("FAST corner detector", img2) cv2.waitKey(0) cv2.destroyAllWindows() ``` 该代码使用OpenCV库实现了FAST角点检测算法,对输入的图像进行角点检测,并将结果显示出来。其中,cv2.FastFeatureDetector_create()用于创建FAST角点检测器,kp为检测到的关键点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mega_Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值