• VLFeat中SIFT特征点检测 PAK FA T


    本代码使用VLFeat库中的函数对一幅图像进行了SIFT检测

    需要事先配置好VLFeat和OpenCV,VLFeat的配置参考前一篇博文,OpenCV的配置网上一大堆,自己去百度

    #include "stdafx.h"
    #include <stdio.h>
    #include <tchar.h>
    #include <opencv2/opencv.hpp>
    #include <stdio.h>
    
    using namespace cv;
    using namespace std;
    
    extern "C"{
    #include <vl/generic.h>
    #include <vl/stringop.h>
    #include <vl/sift.h>
    #include <vl/getopt_long.h>
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        // 注意此处一定是0,不能不填,因为是单通道,灰度空间
        IplImage* img = cvLoadImage("1.jpg", 0);
    
        // 此处这三个变量的定义看下面vl_sift_new函数中的解释
        int noctaves = 4, nlevels = 2, o_min = 0;
    
        // vl_sift_pix 就是float型数据
        vl_sift_pix *imgdata = new vl_sift_pix[img->height * img->width];
    
        // 将原图像复制到float型的vl_sift_pix数组中
        unsigned char *Pixel;
        for (int i=0;i<img->height;i++)
        {
            for (int j=0;j<img->width;j++)
            {
                Pixel=(unsigned char*)(img->imageData+i*img->width+j);
                imgdata[i*img->width+j]=*(Pixel);
            }
        }
    
        // VlSiftFilt: This filter implements the SIFT detector and descriptor.
        // 这个过滤器实现了SIFT检测器和描述符
        VlSiftFilt *siftfilt = NULL;
    
        // vl_sift_new(int width, int height, int noctaves, int nlevels, int o_min)
        // noctaves: numbers of octaves 组数
        // nlevels: numbers of levels per octave 每组的层数
        // o_min: first octave index 第一组的索引号
        siftfilt = vl_sift_new(img->width, img->height, noctaves, nlevels, o_min);
    
        float Descri[1000][128];    //记录每个特征点的描述符,一个特征点有可能有多个描述符,最多有4个
        int      area[1000][4];        //0~3分别记录每个特征点的坐标x,y,圆的半径大小r,该特征点的方向个数,或者说描述符个数
    
        int keypoint = 0;
        int idx_point = 0;            //特征点的个数
        int idx_descri = 0;            //特征点描述符的个数 >= idx_point
    
        // vl_sift_process_first_octave: 
        // The function starts processing a new image by computing its Gaussian scale space at the lower octave. 
        // It also empties the internal keypoint buffer.
        // 这个函数开始处理一幅新图像,通过计算它在低层的高斯尺度空间
        // 它还清空内部记录关键点的缓冲区
        if (vl_sift_process_first_octave(siftfilt, imgdata) != VL_ERR_EOF)
        {
            while (1)
            {
                // 计算每组中的关键点
                vl_sift_detect(siftfilt);
    
                // 遍历每个特征点
                keypoint += siftfilt->nkeys;
    
                VlSiftKeypoint *pkeypoint = siftfilt->keys;
    
                for (int i = 0; i < siftfilt->nkeys; i ++)
                {
                    VlSiftKeypoint tempkeypoint = *pkeypoint;
                    pkeypoint++;
    
                    area[idx_point][0] = tempkeypoint.x;
                    area[idx_point][1] = tempkeypoint.y;
                    area[idx_point][2] = tempkeypoint.sigma/2;
    
                    // 计算并遍历每个点的方向
                    double angles[4];
    
                    // The function computes the orientation(s) of the keypoint k. 
                    // The function returns the number of orientations found (up to four). 
                    // The orientations themselves are written to the vector angles.
                    // 计算每个极值点的方向,包括主方向和辅方向,最多4个方向
                    int angleCount = vl_sift_calc_keypoint_orientations(siftfilt, angles, &tempkeypoint);
    
                    area[idx_point][3] = angleCount;
                    idx_point ++;
    
                    for (int j = 0; j < angleCount; ++ j)
                    {
                        printf("%d: %f\n", j, angles[j]);
    
                        // 计算每个方向的描述符
                        float *descriptors = new float[128];
                        vl_sift_calc_keypoint_descriptor(siftfilt, descriptors, &tempkeypoint, angles[j]);
    
                        memcpy(Descri[idx_descri], descriptors, 128 * sizeof(float));
                        idx_descri ++;
    
                        delete []descriptors;
                        descriptors = NULL;
                    }
    
                }
    
                // vl_sift_process_next_octave: 
                // The function computes the next octave of the Gaussian scale space. 
                // Notice that this clears the record of any feature detected in the previous octave.
                // 这个函数计算高斯尺度空间中的下一组尺度空间图像
                // 这个函数会清除在前一层空间中检测到的特征点
                if (vl_sift_process_next_octave(siftfilt) == VL_ERR_EOF)
                {
                    break;
                }
    
                keypoint = 0;
            }
        }
    
        vl_sift_delete(siftfilt);
        delete []imgdata;
        imgdata = NULL;
    
        for (int i = 0; i < idx_point; ++ i)
        {
            cvDrawCircle(img, cvPoint(area[i][0], area[i][1]), area[i][3], CV_RGB(255,0,0));
        }
    
        cvNamedWindow("Source Image", 1);
        cvShowImage("Source Image", img);
        cvWaitKey(0);
        cvReleaseImage(&img);
        cvDestroyAllWindows();
    
        return 0;
    }
  • 相关阅读:
    thinkphp6 模型中时间戳报错
    php获取真实的ip信息
    java 获取字符串长度
    thinkphp6 linux首次部署Access denied
    mysql5.7 分配子账户和解决进程错误
    springboot controller引用请求体和返回体方法
    微信公众号token 验证
    springboot常量定义
    python 抓接口 利用requests 增加 headers示例
    asp.net web api 如何设置允许后台跨域访问
  • 原文地址:https://www.cnblogs.com/pakfahome/p/3605285.html
Copyright © 2020-2023  润新知