Fast 角点提取c++代码

35 篇文章 3 订阅
24 篇文章 1 订阅

本人近来研究opencv的Fast 的源码,发现opencv 对Fast 的算法写的有优化,并不方便初学者来理解代码,本人根据Fast 算法的原理,写了一个相对非常好理解的Fast 算法,在速度上不如opencv, 但是在代码的理解和简洁上绝对是更胜一抽,希望能帮助更多学习Fast 算法的同学们,请大家相信,本程序Fast 的结果经过验证和opencv 结果一样,请大家放心使用。
下面是头文件

struct OnePoint2f
{
    float x;
    float y;
};
typedef struct __KeyPoint_
{
    OnePoint2f pt; 
    float size; 
    float angle;

    float response; 
    int octave;

}OneKeyPoint;

enum MyEnum
{
    start = -1,
    nOAST_9_16,
    nAGAST_5_8,

};

// @para img 灰度图
// @para mWidth 图像宽
// @para mHeight 图像高
// @para keypoints 结果
// @para threshold 阈值
void OAST_9_16_(unsigned char * img, int mWidth, int mHeight, std::vector<OneKeyPoint>& keypoints, int threshold);

// 下面是cpp 文件

#include <algorithm>
#include <vector>
#include "Fast.h"
using namespace std;
void makeAgastOffsets(int pixel[16], int rowStride, int type)
{
    static const int offsets16[][2] =
    {
        {-3,  0}, {-3, -1}, {-2, -2}, {-1, -3}, {0, -3}, { 1, -3}, { 2, -2}, { 3, -1},
        { 3,  0}, { 3,  1}, { 2,  2}, { 1,  3}, {0,  3}, {-1,  3}, {-2,  2}, {-3,  1}
    };

    static const int offsets8[][2] =
    {
        {-1,  0}, {-1, -1}, {0, -1}, { 1, -1},
        { 1,  0}, { 1,  1}, {0,  1}, {-1,  1}
    };

    const int (*offsets)[2] = type == nOAST_9_16 ? offsets16 :
                              type == nAGAST_5_8 ? offsets8  : 0;


    int k = 0;
    for( ; k < 16; k++ )
        pixel[k] = offsets[k][0] + offsets[k][1] * rowStride;
}



int agast_cornerScore_9_16_(const unsigned char* ptr, const int pixel[], int threshold)
{
    int bmin = threshold;
    int bmax = 255;
    int b_test = (bmax + bmin) / 2;
    register short offset[16] = { 0 };
    offset[0]= (short)pixel[0];
    offset[1]= (short)pixel[1];
    offset[2]= (short)pixel[2];
    offset[3]= (short)pixel[3];
    offset[4]= (short)pixel[4];
    offset[5]= (short)pixel[5];
    offset[6]= (short)pixel[6];
    offset[7]= (short)pixel[7];
    offset[8]= (short)pixel[8];
    offset[9]= (short)pixel[9];
    offset[10] = (short)pixel[10];
    offset[11] = (short)pixel[11];
    offset[12] = (short)pixel[12];
    offset[13] = (short)pixel[13];
    offset[14] = (short)pixel[14];
    offset[15] = (short)pixel[15];

    while (true)
    {
        register const int cb = *ptr + b_test;
        register const int c_b = *ptr - b_test;
        int flag[32] = { 0 };
        for (int k = 0; k < 16; k++)
        {
            if (ptr[offset[k]] > cb)
            {
                flag[k] = 1;
                flag[k + 16] = 1;

            }
            else if (ptr[offset[k]] < c_b)
            {
                flag[k] = -1;
                flag[k + 16] = -1;
            }
            else
            {
                flag[k] = 0;
                flag[k + 16] = 0;
            }

        }
        int temp = 0;
        int count = 0;
        for (int k = 0; k < 31; k++)
        {
            temp = flag[k] * flag[k + 1];
            if (temp > 0)
            {
                count++;
            }
            else
            {
                count = 0;
            }
            if (count >= 8)
            {
                goto is_a_corner;
            }
        }
        goto is_not_a_corner;

        is_a_corner:
            bmin = b_test;
            goto end;

        is_not_a_corner:
            bmax = b_test;
            goto end;

        end:

            if (bmin == bmax - 1 || bmin == bmax)
                return bmin;
            b_test = (bmin + bmax) / 2;
    }
}

int agast_cornerScore_5_8_(const unsigned char* ptr, const int pixel[], int threshold)
{
    int bmin = threshold;
    int bmax = 255;
    int b_test = (bmax + bmin) / 2;


    register short offset[8] = { 0 };
    offset[0] = (short)pixel[0];
    offset[1] = (short)pixel[1];
    offset[2] = (short)pixel[2];
    offset[3] = (short)pixel[3];
    offset[4] = (short)pixel[4];
    offset[5] = (short)pixel[5];
    offset[6] = (short)pixel[6];
    offset[7] = (short)pixel[7];

    while (true)
    {
        register const int cb = *ptr + b_test;
        register const int c_b = *ptr - b_test;
        int flag[16] = { 0 };
        for (int k = 0; k < 8; k++)
        {
            if (ptr[offset[k]] > cb)
            {
                flag[k] = 1;
                flag[k + 8] = 1;

            }
            else if (ptr[offset[k]] < c_b)
            {
                flag[k] = -1;
                flag[k + 8] = -1;
            }
            else
            {
                flag[k] = 0;
                flag[k + 8] = 0;
            }

        }
        int temp = 0;
        int count = 0;
        for (int k = 0; k < 15; k++)
        {
            temp = flag[k] * flag[k + 1];
            if (temp > 0)
            {
                count++;
            }
            else
            {
                count = 0;
            }
            if (count >= 4)
            {
                goto is_a_corner;
            }
        }
        goto is_not_a_corner;

    is_a_corner:
        bmin = b_test;
        goto end;

    is_not_a_corner:
        bmax = b_test;
        goto end;

    end:

        if (bmin == bmax - 1 || bmin == bmax)
            return bmin;
        b_test = (bmin + bmax) / 2;
    }
}


void OAST_9_16_(unsigned char * img, int mWidth, int mHeight, std::vector<OneKeyPoint>& keypoints, int threshold)
{


        size_t total = 0;
        int xsize = mWidth;
        int ysize = mHeight;
        size_t nExpectedCorners = keypoints.capacity();
        register int x, y;
        register int xsizeB = xsize - 4;
        register int ysizeB = ysize - 3;
        register int width;

        keypoints.resize(0);

        int pixel_9_16_[16];
        makeAgastOffsets(pixel_9_16_, xsize, nOAST_9_16);
        register short offset[16] = { 0 };
        offset[0] = (short)pixel_9_16_[0];
        offset[1] = (short)pixel_9_16_[1];
        offset[2] = (short)pixel_9_16_[2];
        offset[3] = (short)pixel_9_16_[3];
        offset[4] = (short)pixel_9_16_[4];
        offset[5] = (short)pixel_9_16_[5];
        offset[6] = (short)pixel_9_16_[6];
        offset[7] = (short)pixel_9_16_[7];
        offset[8] = (short)pixel_9_16_[8];
        offset[9] = (short)pixel_9_16_[9];
        offset[10] = (short)pixel_9_16_[10];
        offset[11] = (short)pixel_9_16_[11];
        offset[12] = (short)pixel_9_16_[12];
        offset[13] = (short)pixel_9_16_[13];
        offset[14] = (short)pixel_9_16_[14];
        offset[15] = (short)pixel_9_16_[15];

        width = xsize;
        int flag[32] = { 0 };
        for (y = 3; y < ysizeB; y++)
        {
            for (x = 3; x < xsizeB + 1; x++)
            {
                register const unsigned char* const ptr = img + y*width + x;
                register const int cb = *ptr + threshold;
                register const int c_b = *ptr - threshold;
                for (int k = 0; k < 16; k++)
                {
                    if (ptr[offset[k]] > cb)
                    {
                        flag[k] = 1;
                        flag[k + 16] = 1;

                    }
                    else if (ptr[offset[k]] < c_b)
                    {
                        flag[k] = -1;
                        flag[k + 16] = -1;
                    }
                    else
                    {
                        flag[k] = 0;
                        flag[k + 16] = 0;
                    }

                }
                int temp = 0;
                int count = 0;
                for (int k = 0; k < 31; k++)
                {
                    temp = flag[k] * flag[k + 1];
                    if (temp > 0)
                    {
                        count++;
                    }
                    else
                    {
                        count = 0;
                    }
                    if (count >= 8)
                    {
                        OneKeyPoint tempKeyPoint;
                        tempKeyPoint.pt.x = (float)x;
                        tempKeyPoint.pt.y = (float)y;
                        tempKeyPoint.size = 1.0f;
                        tempKeyPoint.response = (float)agast_cornerScore_9_16_(ptr, pixel_9_16_, threshold);

                        keypoints.push_back(tempKeyPoint);
                        //printf("x = %d, y = %d\n", x, y);
                        break;
                    }
                }

            }

        }
}

下面是main 函数

#include <opencv2/opencv.hpp>
#include <vector>
#include "Fast.h"
using namespace std;
using namespace cv;

int main()
{

    Mat gray = imread("lena.bmp", 0);

    vector<OneKeyPoint> keypoints;
    int threshold = 30;
    OAST_9_16_(gray.data, gray.cols, gray.rows, keypoints, threshold);



    Mat image = imread("lena.bmp", 1);
    cv::Point2f srcPts;
    for (int k = 0; k < keypoints.size(); k++) {

        srcPts.x = keypoints[k].pt.x;
        srcPts.y = keypoints[k].pt.y;
        circle(image, srcPts, 1, Scalar(0, 255, 0));
    }

    imshow("show", image);
    waitKey(0);
    return 0;
}

结果如下
这里写图片描述

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值