目录
一、OpenCV-features2d 模块简介
1.1 features2d 模块信息
1.2 features2d 模块应用流程
二、features2d 模块编码案例
2.1 实现逻辑
2.2 features2d 模块应用程序代码
2.3 程序编译及运行
一、OpenCV-features2d
模块简介
1.1 features2d
模块信息
features2d
是 OpenCV 中的一个模块,它提供了大量的二维特征检测、描述和匹配算法。
features2d
模块的类及函数包含在modules\features2d\include\opencv2\features2d.hpp,
#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>
以下是一些 features2d
模块中常用的类和函数:
-
特征检测器:
cv::FastFeatureDetector
:基于 FAST(Features from Accelerated Segment Test)算法的特征检测器。cv::ORB
:Oriented FAST and Rotated BRIEF 特征检测器和描述子。cv::SIFT
:Scale-Invariant Feature Transform 特征检测器和描述子(在某些版本的 OpenCV 中可能需要额外安装)。cv::SURF
:Speeded Up Robust Features 特征检测器和描述子(在某些版本的 OpenCV 中可能需要额外安装,并且可能由于版权问题而不再被推荐使用)。cv::AgastFeatureDetector
:基于 AGAST(Adaptive and Generic Accelerated Segment Test)算法的特征检测器。cv::MSER
:Maximally Stable Extremal Regions 特征检测器。cv::SimpleBlobDetector
:用于检测图像中的简单斑点或圆形结构的检测器。
-
描述子:
- 除了 SIFT 和 SURF 之外,许多特征检测器也提供了与之关联的描述子。
- 描述子用于量化特征周围的图像区域,以便在后续步骤中进行特征匹配。
-
特征匹配:
cv::DescriptorMatcher
:一个类,用于匹配来自两个不同图像的特征描述子。它提供了许多匹配方法,如暴力匹配(Brute-Force Matcher)和 FLANN(Fast Library for Approximate Nearest Neighbors)匹配。cv::drawMatches
:一个函数,用于在图像上绘制匹配的特征对。
-
特征匹配评估:
cv::BFMatcher::knnMatch
:对于每个查询描述子,找到 k 个最佳匹配。cv::DescriptorMatcher::radiusMatch
:对于每个查询描述子,找到与其距离在指定半径内的所有匹配。- 评估匹配质量的方法,如比率测试(Ratio Test)和交叉检查(Cross-Check)。
-
非极大值抑制:
- 在某些情况下,检测到的特征可能过于密集,需要进行非极大值抑制(NMS)以减少冗余特征。
-
关键点数据结构:
cv::KeyPoint
:一个类,用于表示检测到的关键点(特征)的位置、大小、方向等信息。
1.2 features2d
模块应用流程
使用 features2d
模块时,通常的流程是:
- 加载或捕获图像。
- 使用特征检测器检测关键点。
- 对于每个关键点,使用描述子算法计算描述子。
- 使用描述子匹配器匹配来自两个不同图像的描述子。
- 评估匹配质量,并可能使用非极大值抑制来减少冗余匹配。
- 可视化匹配结果或进行后续处理。
二、features2d
模块编码案例
2.1 实现逻辑
1. 读取图片数据
使用imread读取图片数据,存入cv::Mat。
2.使用 SIFT等特征检测器及关键点检测
SIFT(Scale-Invariant Feature Transform)常用的特征检测器和描述子,对于尺度、旋转和光照变化都具有一定的鲁棒性。这些特征可以用于在两张图像之间找到匹配的特征点,从而进行图像匹配或拼接。
或ORB(Oriented FAST and Rotated BRIEF)是一种快速的特征检测器和描述子,它结合了 FAST 特征检测器和 BRIEF 描述子的优点,具有较快的处理速度和较好的性能。ORB 可以用于实时图像处理任务,如视频中的物体跟踪。
3. 进行图像匹配
使用 FLANN 匹配器进行特征匹配,检测每张图像中的特征点,并使用特征匹配器找到这些特征点之间的对应关系。
4.绘制匹配结果并显示或其操作,如图像拼接、物体识别
使用cv::drawMatches绘制匹配结果。或者进行图像拼接、物体识别等后续操作。
PS:图像拼接是一种将多张图像合并成一张大图像的技术。使用 features2d
模块,可以检测每张图像中的特征点,并使用特征匹配器找到这些特征点之间的对应关系。然后,通过计算透视变换矩阵,可以将这些图像拼接成一张大图像。
物体识别是一种通过比较图像中的特征点来识别物体的技术。使用 features2d
模块,可以检测待识别图像中的特征点,并与已知物体的特征点进行比较。如果找到了足够多的匹配点,则可以认为待识别图像中包含已知物体。
全息照相法是一种基于特征点的物体识别方法,它通过比较特征点之间的关系来判断物体是否存在。使用 features2d
模块,可以提取参考图像和待检测图像中的特征点,并使用特征匹配器找到这些特征点之间的对应关系。然后,通过比较匹配点的数量和分布情况,可以判断待检测图像中是否包含已知物体。
2.2 features2d
模块应用程序代码
main.cpp
#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>
#include <iostream>int main(int argc, char** argv)
{ // 加载图像 cv::Mat img1 = cv::imread("image_1.jpg", cv::IMREAD_COLOR); cv::Mat img2 = cv::imread("image_2.jpg", cv::IMREAD_COLOR); // 初始化 SIFT 特征检测器 // cv::Ptr<cv::SIFT> detector = cv::SIFT::create(); // 初始化 ORB 特征检测器 // cv::Ptr<cv::ORB> detector = cv::ORB::create(); // 初始化 BRISK 特征检测器 cv::Ptr<cv::BRISK> detector = cv::BRISK::create(); // 检测关键点并计算描述子 std::vector<cv::KeyPoint> keypoints1, keypoints2; cv::Mat descriptors1, descriptors2; detector->detectAndCompute(img1, cv::noArray(), keypoints1, descriptors1); detector->detectAndCompute(img2, cv::noArray(), keypoints2, descriptors2); //ORB和BRISK 特征需转换mat类型descriptors1.convertTo(descriptors1,CV_32FC1);descriptors2.convertTo(descriptors2,CV_32FC1);int type = descriptors1.type(); int depth = CV_MAT_DEPTH(type); int channels = CV_MAT_CN(type); std::cout << "image type: " << type << std::endl; std::cout << "depth: " << depth << std::endl; std::cout << "channels: " << channels << std::endl; // 使用 FLANN 匹配器进行特征匹配 cv::FlannBasedMatcher matcher; std::vector<cv::DMatch> matches; matcher.match(descriptors1, descriptors2, matches); // 绘制匹配结果并显示 cv::Mat imgMatches; cv::drawMatches(img1, keypoints1, img2, keypoints2, matches, imgMatches); cv::imshow("Matches", imgMatches); cv::waitKey(0); //进一步进行图像拼接等操作 ... return 0;
}
2.3 程序编译及运行
本文是采用win系统下,opencv采用MinGW编译的静态库(C/C++开发,win下OpenCV+MinGW编译环境搭建_opencv mingw-CSDN博客),建立makefile:
#/bin/sh
#win32
CX= g++ -DWIN32
#linux
#CX= g++ -Dlinux BIN := ./
TARGET := opencv_features2d01.exe
FLAGS := -std=c++11 -static
SRCDIR := ./
#INCLUDES
INCLUDEDIR := -I"../../opencv_MinGW/include" -I"./"
#-I"$(SRCDIR)"
staticDir := ../../opencv_MinGW/x64/mingw/staticlib/
#LIBDIR := $(staticDir)/libopencv_world460.a\
# $(staticDir)/libade.a \
# $(staticDir)/libIlmImf.a \
# $(staticDir)/libquirc.a \
# $(staticDir)/libzlib.a \
# $(wildcard $(staticDir)/liblib*.a) \
# -lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid
#opencv_world放弃前,然后是opencv依赖的第三方库,后面的库是MinGW编译工具的库LIBDIR := -L $(staticDir) -lopencv_world460 -lade -lIlmImf -lquirc -lzlib \-llibjpeg-turbo -llibopenjp2 -llibpng -llibprotobuf -llibtiff -llibwebp \-lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid
source := $(wildcard $(SRCDIR)/*.cpp) $(TARGET) :$(CX) $(FLAGS) $(INCLUDEDIR) $(source) -o $(BIN)/$(TARGET) $(LIBDIR)clean:rm $(BIN)/$(TARGET)
编译如下:
下载两张类似图片,放置目录下,
程序运行输出如下: