引言

本人采用的是RobHess的代码,网上实现该代码的文章有很多,但大多是在vs2010和vc6.0上实现的,我在用vs2015实现的过程总出现了很多新问题,在这里我将一步步的把出现的所有bug都解决一遍,希望可以给您提供一些帮助。


ps:关于SIFT的原理可以参考SIFT特征提取分析 和一些硕士论文,我就不再说了。此外,我采用的代码是2010年的版本sift-1.1.2_20101207_win,该代码可以从我列的参考资料中下载到。

正文

现在我们正式开始一步步的实现SIFT的代码。解压缩之后我们可以看到有三个子项目:siftFeat、match、dspFeat。siftFeat是用来提取图片特征的,match是将两幅图像的特征匹配,dspFeat是读取已经提取的特征并显示在图片上。

  1. 我们首先试着运行siftFeat,提示需要对该项目进行升级,点击确定升级。
  2. 进入工程之后我们会看到如下错误:
    fatal error C1083: 无法打开包括文件: “cxcore.h”: No such file or directory
  3. 这是因为我们还没有配置opencv。
  4. 右击工程,选择属性打开属性页,选择VC++目录,选择包含目录,在其中添加如下三个路径,这是我的opencv安装路径,读者注意添加自己的路径。
  5. D:\opencv\build\include
  6. D:\opencv\build\include\opencv
  7. D:\opencv\build\include\opencv2
  8. opencv SIFT 头文件 opencv3 sift_opencv SIFT 头文件


  9. 接着选择库目录添加如下两个路径,同样要添加自己的路径。
  10. D:\opencv\build\x86\vc12\lib
  11. D:\opencv\build\x86\vc12\staticlib
  12. opencv SIFT 头文件 opencv3 sift_d3_02


  13. 最后选择链接器,选择输入,选择附加依赖项把原本的lib都删除,换成如下两条
  14. opencv_ts300d.lib
  15. opencv_world300d.lib
  16. ps:200d是opencv2.0版本的,我们3.0版本当然要用300d了。
  17. 300d是debug编译,300是release编译,我用的是debug编译。
  18. 配置完成后,该问题解决!
  19. 再次运行程序,发现有如下错误:
    error C2440: “=”: 无法从“int”转换为“CvScalar”
    error C2440: “初始化”: 无法从“int”转换为“CvScalar”
  20. 双击错误跳到对应代码处。
  21. opencv SIFT 头文件 opencv3 sift_文件包含_03


  22. 可以看到这句代码是没有语法错误的,所以只能是头文件包含错误。我们看到imgfeatures.c包含的头文件如下,其中与CvScalar有关的头文件是cxcore.h,该头
  23. opencv SIFT 头文件 opencv3 sift_文件包含_04


  24. 文件包含于cv.h,所以改成cv.h或许可以解决问题
  25. opencv SIFT 头文件 opencv3 sift_无法解析_05


  26. 修改之后,该问题解决!
  27. 再次运行程序,发现有如下错误:
    error LNK2019: 无法解析的外部符号 _va_start,该符号在函数 _fatal_error 中被引用
    error LNK2019: 无法解析的外部符号 _va_end,该符号在函数 _fatal_error 中被引用
    这时我们只需要在utils.c里加上#include < stdarg.h >即可
    问题再次解决!
  28. 再次运行程序,呵呵,还有错误,出现如下错误界面:
  29. opencv SIFT 头文件 opencv3 sift_文件包含_06


  30. 点击调试,静静等待之后报的错误是:
    0x10CE0F77 (opencv_world300d.dll) (siftFeat.exe 中)处有未经处理的异常: 0xC0000005: 读取位置 0x00000020 时发生访问冲突。
  31. 在右下角的调用堆栈界面选择最后执行的语句转到出错的代码处。
  32. opencv SIFT 头文件 opencv3 sift_无法解析_07


  33. 错误代码处:
  34. opencv SIFT 头文件 opencv3 sift_文件包含_08


  35. 网上说该错误一般是由于空指针引起的,但对于该处好像不太适用。
  36. 该行代码的原意是利用cvGetSize(img)返回img图片的宽和高,再创建gray32这个新图片,而创建图像的函数cvCreateImage用法没有错误,所以只能是cvGetSize这个函数出错了,也就是说cvGetSize(img)并没有返回img的宽和高,所以我们可以直接手动把img的宽和高写出来,即将cvGetSize(img)修改为cvSize(img->width, img->height),同理,把代码其它地方的cvGetSize修改为相应的cvSize即可。
  37. 此时再运行程序,问题得到解决,并出现了让人感动的松鼠界面。
  38. opencv SIFT 头文件 opencv3 sift_无法解析_09

结束

至此,siftFeat就算运行成功了,为了完整性,我再放两张match和dspFeat运行后的图片,作为结束。

match:

opencv SIFT 头文件 opencv3 sift_无法解析_10


dspFeat:

opencv SIFT 头文件 opencv3 sift_无法解析_11

参考资料