OpenCV SIFT源码详解——detectAndCompute函数详解

这篇具有很好参考价值的文章主要介绍了OpenCV SIFT源码详解——detectAndCompute函数详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、函数声明

    void detectAndCompute(InputArray img, InputArray mask,
                    std::vector<KeyPoint>& keypoints,
                    OutputArray descriptors,
                    bool useProvidedKeypoints = false) CV_OVERRIDE;

useProvidedKeypoints参数决定当前是探测关键点还是计算描述符文章来源地址https://www.toymoban.com/news/detail-604256.html

二、函数实现关键处注释

void SIFT_Impl::detectAndCompute(InputArray _image, InputArray _mask,
                      std::vector<KeyPoint>& keypoints,
                      OutputArray _descriptors,
                      bool useProvidedKeypoints)
{
    CV_TRACE_FUNCTION();
	/*
	*	firstOctave:当图像放大两倍时,金字塔的组号从-1开始,否则从0开始
	*	actualNOctaves:指图像金字塔的组数
	*	actualNLayers:指DoG每组内参与极值点探测的图像数,一般为3层
	*/
    int firstOctave = -1, actualNOctaves = 0, actualNLayers = 0;
    Mat image = _image.getMat(), mask = _mask.getMat();

    if( image.empty() || image.depth() != CV_8U )
        CV_Error( Error::StsBadArg, "image is empty or has incorrect depth (!=CV_8U)" );

    if( !mask.empty() && mask.type() != CV_8UC1 )
        CV_Error( Error::StsBadArg, "mask has incorrect type (!=CV_8UC1)" );

	/*
	*	使用提供的关键点,用于计算描述符
	*/
    if( useProvidedKeypoints )
    {
        firstOctave = 0;
        int maxOctave = INT_MIN;
        /*
        *	遍历所有的关键点,计算图像金字塔起始组号和总组数
        */
        for( size_t i = 0; i < keypoints.size(); i++ )
        {
            int octave, layer;
            /*
            *	scale指的是当前关键点所在图层的大小与原始图像大小之比;
            *	比如,oct = -1时, scale = 2;
            *		  oct = 0时, scale = 1;
            */
            float scale;
            /*
            *	OpenCV很巧妙的使用一个变量(cv::KeyPoint::octave)
            *	存储了两个信息:oct和layer。具体可见本系列我的另一篇文章
            */
            unpackOctave(keypoints[i], octave, layer, scale);
            firstOctave = std::min(firstOctave, octave);
            maxOctave = std::max(maxOctave, octave);
            actualNLayers = std::max(actualNLayers, layer-2);
        }

        firstOctave = std::min(firstOctave, 0);
        CV_Assert( firstOctave >= -1 && actualNLayers <= nOctaveLayers );
        actualNOctaves = maxOctave - firstOctave + 1;
    }
	/*
	*	图像初始化,具体可见本系列我的另一篇文章
	*/
    Mat base = createInitialImage(image, firstOctave < 0, (float)sigma);
    
    std::vector<Mat> gpyr;
	/*
	* 只有useProvidedKeypoints为true时,actualNOctaves 才会大于 0
	* 此时,使用直接使用已经计算好的actualNOctaves 即可;
	* 否则,说明要进行关键点探测步骤,需要构建高斯图像金字塔,
	* 使用公式 计算组数
	*/
    int nOctaves = actualNOctaves > 0 ? actualNOctaves : cvRound(std::log( (double)std::min( base.cols, base.rows ) ) / std::log(2.) - 2) - firstOctave;

    //double t, tf = getTickFrequency();
    //t = (double)getTickCount();
    /*
    *	建立高斯图像金字塔,具体见本系列我的另一篇文章
    */
    buildGaussianPyramid(base, gpyr, nOctaves);

    //t = (double)getTickCount() - t;
    //printf("pyramid construction time: %g\n", t*1000./tf);
	
	/*
	*	进行关键点探测
	*/
    if( !useProvidedKeypoints )
    {
    	/*
    	*	构建DOG,具体见本系列我的另一篇文章
    	*/
        std::vector<Mat> dogpyr;
        buildDoGPyramid(gpyr, dogpyr);

        //t = (double)getTickCount();
        
        /*
        *	根据DOG探测关键点,以及极值点亚像素定位
        *	具体可见本系列我的另一篇文章
        */
        findScaleSpaceExtrema(gpyr, dogpyr, keypoints);
		/*
		*	关键点排序去重
		*/
        KeyPointsFilter::removeDuplicatedSorted( keypoints );
		
		/*
		*	nfeatures:用户提供的最大关键点数
		*		若用户提供了最大的关键点数,则根据cv::KeyPoint::response的
		*	大小,去除多余关键点
		*/
        if( nfeatures > 0 )
            KeyPointsFilter::retainBest(keypoints, nfeatures);
        //t = (double)getTickCount() - t;
        //printf("keypoint detection time: %g\n", t*1000./tf);
		
		/*
		*	将关键点放缩到原图尺寸下
		*		经过findScaleSpaceExtrema获取的关键点坐标与高斯金字塔第一组的
		*	尺寸相同,因此,当firstOctave < 0时,要将关键点乘以0.5。
		*		否则,金字塔第一层与原图尺寸相同,无需处理。
		*/
        if( firstOctave < 0 )
            for( size_t i = 0; i < keypoints.size(); i++ )
            {
                KeyPoint& kpt = keypoints[i];
                float scale = 1.f/(float)(1 << -firstOctave);
                kpt.octave = (kpt.octave & ~255) | ((kpt.octave + firstOctave) & 255);
                kpt.pt *= scale;
                kpt.size *= scale;
            }

		/*
		*	如果提供了mask,过滤掉mask标记的关键点
		*/
        if( !mask.empty() )
            KeyPointsFilter::runByPixelsMask( keypoints, mask );
    }
    else
    {
        // filter keypoints by mask
        //KeyPointsFilter::runByPixelsMask( keypoints, mask );
    }
	
	/*
	*	计算关键点描述符
	*/
    if( _descriptors.needed() )
    {
        //t = (double)getTickCount();
        /*
        *	描述符大小:128维
        *	实际上 等于 SIFT_DESCR_WIDTH * SIFT_DESCR_WIDTH * SIFT_DESCR_HIST_BINS;
        */  
        int dsize = descriptorSize();		
		
		/*
		*  构造合适大小,类型的描述符集合
		*/
        _descriptors.create((int)keypoints.size(), dsize, descriptor_type);

        Mat descriptors = _descriptors.getMat();
        /*
        *	计算关键点描述符,具体可见本系列我的另一篇文章
        */
        calcDescriptors(gpyr, keypoints, descriptors, nOctaveLayers, firstOctave);
        //t = (double)getTickCount() - t;
        //printf("descriptor extraction time: %g\n", t*1000./tf);
    }
}

三、关键点总结

  1. useProvidedKeypoints为true时,执行compute功能,计算描述符;为false时,执行detect功能,探测关键点;
  2. 当探测关键点时,构建的高斯金字塔首层图像会扩大两倍,firstOctave等于-1;而计算描述符时,firstOctave会根据传入的关键点集合计算得到
  3. findScaleSpaceExtrema探测到的关键点坐标,与高斯金字塔第一层的尺度相同。当firstOctave等于-1时,坐标需要乘以0.5,缩放到原图尺寸。

到了这里,关于OpenCV SIFT源码详解——detectAndCompute函数详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • opencv的SIFT样例(CPP/python)

    结论说明: 两种代码在同一个环境上的,相同的图片大小和数量(19张图片),运行耗时如下: python c++ 差距不会很明显,但是如果文件很多,并且使用多线程/多进程,会有一个比较明显的差距。

    2024年01月19日
    浏览(42)
  • 学习笔记:Opencv实现图像特征提取算法SIFT

    2023.8.19 为了在暑假内实现深度学习的进阶学习,特意学习一下传统算法,分享学习心得,记录学习日常 SIFT的百科: SIFT = Scale Invariant Feature Transform, 尺度不变特征转换 全网最详细SIFT算法原理实现_ssift算法_Tc.小浩的博客-CSDN博客 在环境配置中要配置opencv: pip install opencv-c

    2024年02月12日
    浏览(44)
  • OpenCV 入门教程:SIFT和SURF特征描述

    SIFT (尺度不变特征变换)和 SURF (加速稳健特征)是图像处理中常用的特征描述算法,用于提取图像中的关键点和生成对应的特征描述子。这些算法具有尺度不变性、旋转不变性和光照不变性等特点,适用于图像匹配、目标识别和三维重建等应用。本文将以 SIFT 和 SURF 特征

    2024年02月15日
    浏览(57)
  • 【OpenCV】双目相机标定、极线矫正、SIFT匹配以及深度估计

    双目标定有很多示例,就不多讲,直接放代码 有个小技巧就是可以先使用matlab标定箱试一下,把误差过大的左右相机图片剔除,保证精度 匹配: 过滤: 这里过滤条件2需要注意一下 ,因为我们是进行了极线校正的,所以理论上左右视图相同的点应该在同一条水平线上,即像

    2024年02月07日
    浏览(36)
  • OpenCV使用SURF和SIFT算法报错解决记录

    OpenCV使用SURF和SIFT算法报错解决记录 1.报错代码,使用以下两种写法都会报错 第一种报错 AttributeError: module ‘cv2’ has no attribute ‘xfeatures2d’ 第二种报错 AttributeError: module ‘cv2’ has no attribute ‘SURF_create’ 2.查找网络上的解决办法,大部分分为两种 SIFT和SURF算法申请了专利,

    2024年02月07日
    浏览(37)
  • OpenCV Python – 使用SIFT实现两张图片的特征匹配

     我们使用尺度不变特征变换(  SIFT  )特征描述符和暴力匹配算法实现两张图像的特征匹配。其中,  SIFT  用于找到图像中的关键点和描述符,而  暴力匹配算法  用于在两张图像中匹配描述符。 要使用  SIFT  特征检查器和  暴力  匹配算法实现两张图像的特征匹配,可

    2024年02月03日
    浏览(49)
  • OpenCV Python – 使用SIFT算法实现两张图片的特征匹配

    1.要实现在大图中找到任意旋转、缩放等情况下的小图位置,可以使用特征匹配算法,如 SIFT (尺度不变特征变换) 或 SURF (加速稳健特征)。这些算法可以在不同尺度和旋转情况下寻找匹配的特征点 2.我们使用了 SIFT 算法检测和匹配特征点,然后使用 RANSAC 算法计算透视变换矩阵

    2024年02月06日
    浏览(47)
  • python+openCV使用SIFT算法实现印章的总相似度检测

    首先整体流程是预建了一个印章库,包含若干张图片。目的是输入一张印章图片,与库里图片对比,最终显示相似度最高的三张。记一下关键代码。 1.图像预处理 主要是红色区域提取、常规灰度二值、对于形态不好的图片做个腐蚀啥的。 2.做一个霍夫圆打开,方便后续文字识

    2024年02月08日
    浏览(46)
  • 【教程】Autojs使用OpenCV进行SIFT/BRISK等算法进行图像匹配

    转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn]         此代码可以替代内置的images.findImage函数使用,但可能会误匹配,如果是对匹配结果要求比较高的,还是得谨慎使用。

    2024年02月07日
    浏览(47)
  • Lesson4-3:OpenCV图像特征提取与描述---SIFT/SURF算法

    学习目标 理解 S I F T / S U R F SIFT/SURF S I FT / S U RF 算法的原理, 能够使用 S I F T / S U R F SIFT/SURF S I FT / S U RF 进行关键点的检测 1.1 SIFT原理 前面两节我们介绍了 H a r r i s Harris H a rr i s 和 S h i − T o m a s i Shi-Tomasi S hi − T o ma s i 角点检测算法,这两种算法具有旋转不变性,但不具

    2024年02月09日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包