最近有个图像处理的任务,是要提取图像中的特征点。在OPENCV库中,提供了很多的特征提取库,一些基础的算法在feature2d库中就有,但是有些算法在这个核心库中没有,需要在扩展库xfeatrue2d中才有,比如我需要用的SIFT。
这一篇先不说SIFT的原理,说说如何用上opencv中的这个SIFT。
如果有直接想使用的,我上传了我自己编译好的一些LIB包,有需要的朋友可以自行下载使用:
https://download.csdn.net/download/pcgamer/89998105
环境
- opencv版本:4.2.0
- 开发语言:C++
- 操作系统:windows 10
- 编译IDE:VS 2015
- 开发IDE:VS 2022
- cmake:3.28
下载
SIFT算法在opencv4.2版本的时候,不在核心库中,而且好像是因为版权的问题,需要单独编译,也就是不能直接下载lib库直接使用,必须手动从源码编译。
- opencv4.2.0核心库源码可以直接从opencv官网上下载:
- opencv扩展库需要在github上下载:https://github.com/opencv/opencv_contrib,注意选好branch和tag:
编译
cmake
- CMAKE的几个配置:
BUILD_OPENEXR需要勾选。
BUILD_EXR_PATH需要填写上面的opencv_contrib中的moudules
注意,一定要勾选NONFREE这个勾选框,因为在4.2.0这个版本中,如果不勾选的话,打出来的xfeature2d的lib或者dll中是没有这个函数的实现的。
-
几个文件无法下载,翻墙即可。
cmake-gui中给出的日志:
CMake Warning at cmake/OpenCVDownload.cmake:202 (message):
xfeatures2d/vgg: Download failed: 6;"Couldn't resolve host name"
For details please refer to the download log file:
D:/opencv/opencv-4.2.0/build/CMakeDownloadLog.txt
Call Stack (most recent call first):
D:/opencv/opencv_contrib-4.2.0/modules/xfeatures2d/cmake/download_vgg.cmake:16 (ocv_download)
D:/opencv/opencv_contrib-4.2.0/modules/xfeatures2d/CMakeLists.txt:12 (download_vgg_descriptors)
xfeatures2d/vgg: Download: vgg_generated_120.i
Try 1 failed
=======================================================================
Couldn't download files from the Internet.
Please check the Internet access on this host.CMake Warning at cmake/OpenCVDownload.cmake:202 (message):
xfeatures2d/vgg: Download failed: 6;"Couldn't resolve host name"
For details please refer to the download log file:
D:/opencv/opencv-4.2.0/build/CMakeDownloadLog.txt
Call Stack (most recent call first):
D:/opencv/opencv_contrib-4.2.0/modules/xfeatures2d/cmake/download_vgg.cmake:16 (ocv_download)
D:/opencv/opencv_contrib-4.2.0/modules/xfeatures2d/CMakeLists.txt:12 (download_vgg_descriptors)
或者自己去手动下载下来,放到xfeature2d的src目录下即可:
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/34e4206aef44d50e6bbcd0ab06354b52e7466d26/boostdesc_lbgm.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/34e4206aef44d50e6bbcd0ab06354b52e7466d26/boostdesc_binboost_256.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/34e4206aef44d50e6bbcd0ab06354b52e7466d26/boostdesc_binboost_128.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/34e4206aef44d50e6bbcd0ab06354b52e7466d26/boostdesc_binboost_064.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/34e4206aef44d50e6bbcd0ab06354b52e7466d26/boostdesc_bgm_hd.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/34e4206aef44d50e6bbcd0ab06354b52e7466d26/boostdesc_bgm_bi.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/34e4206aef44d50e6bbcd0ab06354b52e7466d26/boostdesc_bgm.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/fccf7cd6a4b12079f73bbfb21745f9babcd4eb1d/vgg_generated_120.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/fccf7cd6a4b12079f73bbfb21745f9babcd4eb1d/vgg_generated_64.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/fccf7cd6a4b12079f73bbfb21745f9babcd4eb1d/vgg_generated_48.i
- https://raw.githubusercontent.com/opencv/opencv_3rdparty/fccf7cd6a4b12079f73bbfb21745f9babcd4eb1d/vgg_generated_80.i
-
因为4.2.0的版本比较老,其中有几个第三方的依赖库用到了c++11标准中的std::binary_fucntion,而这个东西在14的标准中就弃用,17以后的标准就直接废弃了。所以我自己用的vs 2022默认就是14的标准,会编译出错,需要找到一个vs2015的IDE来进行编译。中间的2017,2019不知道可不可以。
代码调用
我的调用方式是通过核心库的opencv_world全量库,配合xfeature2d这些一个一个的扩展库进行使用。
#include <opencv2/xfeatures2d.hpp>
#include "opencv2/opencv.hpp"
int main(int argc, char* argv[]) {
fs::path basePath = "test.png";
cv::Mat img = cv::imread(basePath.string());
if (img.channels() == 3)
{
cv::cvtColor(img, img, cv::COLOR_RGB2GRAY);
}
cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create(0, 3, 0.04, 10, 1.6);
// 检测关键点
std::vector<cv::KeyPoint> keypoints;
sift->detect(img, keypoints);
// 在图像上绘制关键点
cv::Mat img_with_keypoints;
cv::drawKeypoints(img, keypoints, img_with_keypoints, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);
// 显示结果
cv::resize(img_with_keypoints, img_with_keypoints, cv::Size(img_with_keypoints.cols / 2, img_with_keypoints.rows / 2));
cv::imshow("Keypoints", img_with_keypoints);
cv::waitKey(0);
cv::destroyAllWindows();
}