OpenCV SURF例子注解

SURF算法之Opencv代码详解 这篇博客详细介绍了SURF特征点检测算法的OpenCV实现代码 阅读详情

正文开始了,在OpenCV(据说是1.1以后的版本)中包含了SURF算法,并且还有一个使用SURF的例子,这里使用的是OpenCV2.1。在OpenCV的安装目录下/samples/c 文件夹中一个叫 find_obj.cpp 的文件,这是个应用SURF算法寻找一本书的例子。同目录下还有一对于的可执行文件 find_obj.exe,可以先运行一下看看。来看find_obj.cpp

1、这个程序的框架

从入口 main() 开始慢慢道来

const char* object_filename = argc == 3 ? argv[1] : "box.png";
const char* scene_filename = argc == 3 ? argv[2] : "box_in_scene.png";
main函数前两行,判断是否有图片文件名的参数传入,没有则使用同目录下的"box.png"和"box_in_scene.png"
紧接着创建内存块“CvMemStorage* storage = cvCreateMemStorage(0);”坦白地承认:具体的不懂
cvNamedWindow("Object", 1); //建立两个窗口:物体和对比,第一个参数是窗口名称,第二个参数是Flag。
cvNamedWindow("Object Correspond", 1); //据说Flag只支持一个参数 CV_WINDOW_AUTOSIZE,可能CV_WINDOW_AUTOSIZE = 1 吧。
static CvScalar colors[] =  // 建立类似调色板的东西,colors[0],表示红色,colors[8],表示白色
{                                             // 下面的程序也只用到了这两种颜色,红色的圈儿和白色的线儿。
    {{0,0,255}},                      // 不知道为什么这里弄了九个,吓人吗?
    {{0,128,255}},
    {{0,255,255}},
    {{0,255,0}},
    {{255,128,0}},
    {{255,255,0}},
    {{255,0,0}},
    {{255,0,255}},
    {{255,255,255}}
};
IplImage* object = cvLoadImage( object_filename, CV_LOAD_IMAGE_GRAYSCALE );     
IplImage* image = cvLoadImage( scene_filename, CV_LOAD_IMAGE_GRAYSCALE );
//载入图像,如果为彩色转换为灰度图像,或者说以灰度的模式载入图像。   
//后面的if()就是判断是否正确载入了图像,过!
IplImage* object_color = cvCreateImage(cvGetSize(object), 8, 3);
cvCvtColor( object, object_color, CV_GRAY2BGR );
//上面两行依据灰度图像建立彩色图像,虽然目前实际上的数据是黑白的,但是后面可以添加红色圆圈
CvSeq *objectKeypoints = 0, *objectDescriptors = 0;// 表示指向特征点及其描述符的结构体的指针
CvSeq *imageKeypoints = 0, *imageDescriptors = 0;// CvSeq 为可动态增长元素序列,是所有OpenCV动态数据结构的基础
CvSURFParams params = cvSURFParams(500, 1);//SURF参数设置:阈值500,生成128维描述符
// cvSURFParams 函数原型如下:
CvSURFParams cvSURFParams(double threshold, int extended)
{
    CvSURFParams params;
    params.hessianThreshold = threshold; // 特征点选取的 hessian 阈值
    params.extended = extended; // 是否扩展,1 - 生成128维描述符,0 - 64维描述符
    params.nOctaves = 4; 
    params.nOctaveLayers = 2;
    return params;
}
往下
double tt = (double)cvGetTickCount(); //计时
cvExtractSURF( object, 0, &objectKeypoints, &objectDescriptors, storage, params );
cvExtractSURF( image, 0, &imageKeypoints, &imageDescriptors, storage, params );
//提取图像中的特征点,函数原型:
CVAPI(void) cvExtractSURF( const CvArr* img, const CvArr* mask,
                   CvSeq** keypoints, CvSeq** descriptors,
                   CvMemStorage* storage, CvSURFParams params, int useProvidedKeyPts CV_DEFAULT(0) );
第3、4个参数返回结果:特征点和特征点描述符,数据类型是指针的指针,真麻烦,但是后面的例程中有如何将这些数据从指针的指针中提取出来,所以这里就不管指针的指针是什么东西了。关于对特征点的描述见第二小节,关于特征点描述符见第三小节(三,中国传统文化对三情有独钟,怎么如隔三秋、三日不绝、三月不知菜味<本人菜鸟吗,喜是食白菜的鸟人>,新时代新气象也给“三”赋予新的含义,为发扬传统文化,故本菜鸟喜欢什么都分割为1、2、3)
//后面的因为不太关心没仔细看,大概就是生成匹配对比的图像即:"correspond"
//然后,根据是否定义了 "USE_FLANN" 采用不同的匹配方法,flann 和 非flann
//最后,在object图像中使用红色圆圈画出特征点位置及所处尺度的大小
//在correspond 图像中显示匹配结果,用白色线段相连。

2、特征点的描述,例如 objectKeypoints
定义:CvSeq *objectKeypoints = 0;
对于描述特征点和特征点的描述是基于一种 结构体CvSeq,结构CvSeq是所有OpenCV动态数据结构的基础,内部结构:
int flags; /* micsellaneous flags */ \ //不懂
int header_size; /* size of sequence header */ \ // 头大小,具体不懂
struct CvSeq* h_prev; /* previous sequence */ \//类似链表中的东西
struct CvSeq* h_next; /* next sequence */ \                //同上
struct CvSeq* v_prev; /* 2nd previous sequence */ \//同上
struct CvSeq* v_next; /* 2nd next sequence */ \         //同上
int total; /* total number of elements */ \ // 总共有多少个元素,objectKeypoints->total 表有多少个特征点
int elem_size;/* size of sequence element in bytes */ \ // 每个元素的大小,字节表示
char* block_max;/* maximal bound of the last block */ \ //不懂
char* ptr; /* current write pointer */ \ // 当时写指针的位置,可能就是指向实际数据的指针吧
int delta_elems; /* how many elements allocated when the sequence grows (sequence granularity) */ \
//不懂
CvMemStorage* storage; /* where the seq is stored */ \//同上
CvSeqBlock* free_blocks; /* free blocks list */ \ //同上
CvSeqBlock* first; /* pointer to the first sequence block */ //同上

其实这些弄不弄明白对于应用来说没影响,因为一组特征点被提取出来了,通常会关心:
整体的
特征点的个数: objectKeypoints->total 
第i个特征点
CvSURFPoint *r = (CvSURFPoint*)cvGetSeqElem(objectKeypoints,i);
第i个特征点的:
X坐标位置(单位像素): r->pt.x
Y坐标位置(单位像素): r->pt.y
特征点所处的尺度大小 : r->size
特征点主方位角 : r->dir (0-360 表示,如何定义未知)
特征点的Hessian值 : r->hessian
还有一个参数: r->laplacian 取值为1 或 -1 不知道是什么意思,什么拉普拉斯,有木有高人给指点一下,望指导

3、特征点描述符,例如:objectDescriptors
定义:CvSeq *objectDescriptors = 0;
特征点的个数: objectDescriptors->total 
对于某个特征点描述符,就没有特征点那么简单了,至少这个例程中没有涉及仅使用一个函数和对应的结构体就可以提取出所需数据的简单的方法。
通过观查特征点匹配的代码,菜鸟以为得到特征点描述符的方法为:
CvSetReader reader; 
cvStartReadSeq(objectDescriptors, &reader, 0);
for(int i = 0; i < objectDescriptors->total; i++)
{
        const float* descriptor = (const float*)reader.ptr; // descriptor 指向第i 特征描述符(float数组)的指针
        // 数组长度为:reader.seq->elem_size/sizeof(float) or objectDescriptors->elem_size/sizeof(float) 
       CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader); //读取下一个特征点
}

// 同样对于 特征点 objectKeypoints 也有
CvSetReader kreader; 
cvStartReadSeq(objectKeypoints , &kreader, 0);
for(int i = 0; i < objectKeypoints ->total; i++)
{
        const CvSURFPoint* kp = (const CvSURFPoint*)kreader.ptr; 
        CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader); //读取下一个特征点
        // 上面等价于 CvSURFPoint *kp = (CvSURFPoint*)cvGetSeqElem(objectKeypoints,i);(第二小节)
}

顺便提一下特征点的匹配,前面第一小节涉及到了两种特征匹配:flann 和 非flann。
flann没看明白,非flann就是计算描述符向量的距离,即每个对应元素差的平方和,对于每个需要匹配的特征点同对应的图片中的各个特征点进行距离的计算并保存最短的两个距离,当最短距离小于次短距离的0.6时认为匹配成功。函数定义如下:
int naiveNearestNeighbor( const float* vec, int laplacian,
                                                 const CvSeq* model_keypoints,
                                                 const CvSeq* model_descriptors )
vec ---- 待匹配的描述符
laplacian ---- 第二小节中的神秘变量在这里再一次出现了,当两个特征点的 laplacian 值不同时直接pass 不准配对(只有同性才能配对,OMG 太变态了太变态了EMTF怎么存在这么恶心的变量)不匹配也不计算距离
model_keypoints --------- 指向匹配候选特征点们的结构体指针
model_descriptors ------ 指向匹配候选特征点描述符们的结构体指针
如果匹配成功返回 特征点在 model_keypoints 中的索引值

计算两个描述符距离,函数定义
double compareSURFDescriptors( const float* d1, const float* d2, double best, int length )
d1 --------- 描述符1数组
d2 --------- 描述符2数组
best ------ 相当阈值,当计算的过程中距离大于 beat  的值时即刻返回当前计算的距离值,不用再计算了,木有意义,通常将目前的次近距离传递给 best,以便节省匹配时间(其实提取时间远远大于匹配时间)
length  --- 描述符的维数,即描述符数组长度
返

数学建模题干解码与工具链协同实战指南 数学建模本质是将现实问题精准翻译为数学语言的过程,其核心能力在于题干解码、约束识别与工具适配。题干中的数字、单位、限定词(如‘不超过’‘显著’‘12.7%’)并非干扰信息,而是模型结构、参数设定与验证逻辑的直接依据。Matlab擅长工程计算与统计检验,Python强于异构数据流水线调度,Lingo专精逻辑约束的晶体化表达——三者并非替代关系,而是按‘问题特征→建模需求→工具边界’协同分工。该能力直接决定模型物理可解释性、结果可验证性与竞赛答辩说服力,广泛应用于优化调度、社会仿真与数据预测等典型场景。 阅读详情

相关推荐

【OpenCV】第二十三章: 图像特征检测之SURF、FAST、BRIEF、OBR算法

4、由于在检测特征点时是需要对图像中所有的像素点进行检测,然而图像中的绝大多数点都不是特征点,如果对每个像素点都进行上述的检测过程,那显然是种浪费,所以FAST采用一种进行非特征点判别的方法:首先对候选点的周围90度的点(1,9,5,13)四个点进行测试,而且是先测试1和9,如果它们两个符合阈值要求再测试5和13。继SIFT和SURF后,大家在特征点检测的速度上又进行了很多的改进尝试,但速度的提升效果都不是非常明显,直到FAST算法诞生,特征点检测的速度才有了一个质的飞跃。无法计算描述符的特征点将被删除。

因为热爱所以坚持 2158

Opencv学习之SURF算法

Opencv学习之SURF算法 SURF(加速版的具有鲁棒性的特征,SpeededUp Robust Features),SURF是尺度不变特征变换算法(SIFT算法)的加速版。SURF最大的特征在于采用了harr特征以及积分图像的概念。 SURF原理: (1)构建Hessian矩阵构造高斯金字塔尺度空间 SIFT采用的是DoG图像,而SURF采用的是Hess

Minskyli 2万+

OpenCV中的SURF(Speeded-Up Robust Features 加速鲁棒特征)

上一篇博客介绍了用于关键点检测和描述的SIFT,但它相对较慢。这篇博客将介绍其优化版本——SURF(Speeded-Up Robust Features 加速鲁棒特征),它是加速版的SIFT。

qq_40985985的博客 2708

OpenCV:SURF算法浅析

引子: 课题需要SURF特征提取算法,在运动中提取摄像头图像中的特征点,并进行跟踪匹配,以此估计运动状态。开始找到了SIFT算法,SIFT特征提取具有极强的适应能力,但运算量稍大,后来就有了SURF特征提取算法,简化了计算量,保持了较高的性能,是性价比很不错的算法。开始并不知道O

2万+

【人工智能】【GPU芯片】第一篇 GPU算子——璧韧篇-02

璧韧GPU采用BR-Vision 3.0视觉处理架构,集成专用图像处理单元、计算机视觉加速器、神经网络视觉处理流水线。本列表包含2,048个图像与视觉算子,涵盖8种图像格式、12种颜色空间、16种滤波算法、24种特征检测方法。指令编码指令名称功能描述图像格式颜色空间内存分配应用场景BR_IMG_0001创建RGBA 8位图像RGBA8RGBA设备内存通用图像处理BR_IMG_0002创建RGB 8位图像RGB8RGB设备内存无Alpha通道BR_IMG_0003创建灰度8位图像L8灰度设备内存单通道处理BR

weixin_49199313的博客 827

opencv实现surf算法

本代码可以让用户在vs平台上结合opencv实现对两幅图像的匹配,只需要将文件中的图片名称改一下,换成自己图像名称就可以,简单好用

opencv3.0 beta的一些改变

1. 楔子          计划同github上的opencv结合,然后经常编译,这样就可以持续的在源代码中加注解,而不需要很在意opencv的版本更新;前期get代码和cmake编译(vs2013)都正常;在调试过去的project时发现:         A. 部分没有经过保证性测试的算法,迁移至opencv_contrib,所以需要将这部分代码也get下来,我将其放在opencv\mo

鹿角山下 5195

TI C2000 , .cmd文件,.TI.ramfunc,将程序分配为在RAM中运行/Flash运行的配置方法和原理讲解,(如28375S ,280049,28335等等芯片)

1 基础知识讲解 1.1 在RAM中运行还是在flash中运行指的是什么? 1.1.1 背景:程序编译完之后生成的.bin文件,.bin文件中包含代码段,代码段中全是汇编指令,而汇编指令中包含多个函数,各函数头的地址不同,如存在A函数和B函数,假设RAM地址区间是0x0000-0x8000,flash的地址区间是0xA000-0xF000,A函数要调用B函数,则A函数调用B函数的那段汇编指令中包含的是B函数头的存储地址,A函数和B函数都在flash中有存储 1.1.2 情况1:B函数是配置为在RAM中运行,

weixin_43776284的博客 8065

opencv3.1 svm(支持向量机)使用心得

本文转载自:http://livezingy.com/category/opencv/  在开源的车牌识别系统EasyPR中,用SVM(支持向量机)模型甄选出候选车牌中真正的车牌。目前EasyPR1.4的SVM模型输入的是LBP特征,作者提及后续会考虑增加HOG和SIFT特征。据此思路,我用HOG特征作为SVM模型的输入进行了初步验证,在此记录训练方法和数据。       本文验证

maweifei的博客 3594

SAP面试全过程(已拿offer)

周五打电话给我说过了SAP第一轮面试,第二轮要在下周四北京,这几天终于体会到了什么叫做重压下的感觉,越复习越虚,看别人的面经都感觉卧槽这问题也巨难了吧...连去北京可以见妹子这种事情都感觉一点心情都没有。面前准备固然是要有的,但关键是平时就要有料,多想想自己做的项目。当作一个给自己的提醒吧!

cloudray8580的专栏 4万+

Claude Code × SolidWorks:批量填属性、格式转换、BOM 汇总自动化实战

摘要:本文介绍利用 Claude Code 生成 VBA 宏实现 SolidWorks 批量处理任务的自动化方案。包含5个实战案例:批量填写自定义属性(60分钟任务→10秒)、批量格式转换(80分钟→30秒)、多配置工程图自动生成(120分钟→2分钟)、滚珠丝杠选型计算(15分钟→10秒)和装配体递归BOM导出(40分钟→1分钟)。所有代码基于SolidWorks 2020+ API,提供完整VBA实现和操作指南,可显著提升设计效率。

m0_64424835的博客 610

100+个多媒体开源项目源码

转自:http://sigmm.org/Resources/software/projects Advene: aims at providing a model and a format to share annotations about digital video documentsAmalia.js: is an extensible and versatile HTML5 mult

signal926的专栏 5028

Windows 10 下 DockerToolbox 安装全攻略:从下载到配置阿里云镜像加速

本文详细介绍了在Windows 10系统上安装和配置DockerToolbox的完整流程。从下载安装包、执行初步安装,到关键步骤——修改虚拟机存储路径以及配置阿里云镜像加速器,旨在帮助开发者,尤其是初次接触Docker的新手,快速搭建高效的本地容器开发环境,并解决国内镜像下载缓慢的痛点。

moon9的博客 476

文物数字化核心技术解析:从多光谱成像到Web展示的全链路实践

计算机视觉与图像处理技术是连接物理世界与数字世界的桥梁,其核心在于通过算法对视觉信息进行采集、分析与重建。在工程实践中,高精度成像、特征匹配和图像拼接等基础原理,为解决大规模、高保真度的数字化需求提供了技术支撑。这些技术的价值在于能够非接触、无损伤地记录和复现对象的几何与纹理信息,在工业检测、地图测绘以及文化遗产保护等领域具有广泛应用。以纺织品等平面文物的数字化为例,其核心挑战在于如何通过多光谱成像、结构光扫描等技术栈,获取并融合超大幅面、高分辨率的图像数据,并最终通过自动化采集脚本和基于IIIF标准的We

weixin_34159110的博客 330

Python+OpenCV实战:雨天车牌识别准确率提升300%的5个关键技巧

本文针对雨天车牌识别准确率骤降的难题,分享了五个基于Python和OpenCV的实战技巧。通过暗通道先验去雾、雨纹抑制、光照不变量颜色空间转换、多尺度自适应阈值分割以及融合传统特征与轻量级深度学习的混合识别策略,系统性地提升了算法在恶劣天气下的鲁棒性。这些方法能有效解决图像模糊、对比度低、字符断裂粘连等问题,为智能交通等实际应用提供可靠解决方案。

k8l9m0n的博客 715

Ros入门 (十)----激光雷达避障 简易实现

本篇文章通过订阅/scan话题获取障碍物的距离信息,达到避障目的,提供部分代码,仅供参考。

weixin_51157015的博客 1万+

6.1-6.30推荐文章汇总

6.1-6.30推荐文章汇总 【移动开发】 Cocos2d-x Auto-batching 浅浅的”深入分析”笨木头 OpenCV4Android释疑: 透析Android以JNI调OpenCV的三种方式(让OpenCVManager永不困扰) yanzi1225627 Unity3D游戏开发之回合制游戏原型的实现 q...

weixin_30436101的博客 269

YOLOv11改进,YOLOv11结合DynamicConv(动态卷积),CVPR2024,二次创新C3k2结构

DynamicConv(动态卷积)是一个用于提高卷积神经网络(CNN)性能的技术,核心思想是动态地生成卷积核(filter),而不是使用固定的卷积核。通过引入更多的计算灵活性和适应性来增强卷积操作的表达能力,进而提升模型的性能。专家选择:DynamicConv 通过引入多个“专家”(experts),每个专家学习特定的卷积模式。输入图像的不同部分会选择不同的专家进行卷积。动态卷积核生成:根据输入的不同特征,专家网络动态地生成卷积核,而不是使用固定的卷积核。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 2262

Rcpp在数据科学中的应用:高性能统计计算和机器学习算法实现指南

Rcpp作为R和C++的无缝集成工具,已经成为数据科学领域中高性能统计计算和机器学习算法实现的首选解决方案。这个强大的工具让R用户能够轻松地将C++的高性能计算能力与R的丰富统计库相结合,为数据科学家提供了前所未有的计算效率提升。在本文中,我们将深入探讨Rcpp如何帮助您在数据科学项目中实现性能飞跃。 ## 🚀 为什么数据科学家需要Rcpp? 在当今大数据时代,数据科学家面临着海量数据处理和

gitblog_00582的博客 770

YOLOv8【第一章:基础入门篇·第2节】一文搞定,数据集制作与标注完全指南!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏,该专栏专注于分享我在YOLOv8目标检测模型中的实战经验,涵盖从入门基础到深度优化的全方位解决方案。无论你是计算机视觉的新手,还是具有多年深度学习经验的专家,本专栏都将为你提供高效、可复现的技术方案,助你掌握YOLOv8的核心技术,提升目标检测性能,突破瓶颈,优化模型,并加速项目开发🚀!

**My Coding Family** 1506

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

异步7月上市新书,送出一本你爱的

​​ 每个月小编都会带来一波新书福利,送出一本你最爱的异步新书,7月已上市的新书本月带来14本,涉及到的领域分别是Python、深度学习、少儿编程、产品设计、游戏开发、微服务等,看是否有你喜爱的图书呢? 《Keras深度学习实战》 [意大利]安东尼奥·古利(Antonio Gulli), [印度]苏伊特·帕尔(Sujit Pal)著 本书用当前流行的Keras框架实现了大量深度学习算法...

人邮异步社区 762

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

OpenCV中的SURF特征检测、匹配与对象查找

SURF算法工作原理选择图像中的POI(Points of interest) Hessian Matrix在不同的尺度空间发现关键点,非最大信号压制发现特征点方法、旋转不变性要求生成特征向量。

金戈鐡馬 2196

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

SURF原理及基于OPENCV实现

SURF原理及基于OPENCV实现

xiaohuolong的博客 4049
上一篇: OpenCV笔记: 查找轮廓
下一篇: awakeFromNib小总结
trandy
博客等级 码龄17年 79粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值