特征检测属于 opencv_contrib 库,在编译 OpenCV 时包含了附加模块才能使用,具体如何编译这里就不再作说明了

一、创建检测器

首先读取要建立提取特征的图像与存放特征点的数组

cv::Mat image = cv::imread("hy.jpg", 1);
std::vector<cv::KeyPoint>keypoints;

 使用特征检测方法之前,要创建检测器,然后调用它的检测方法,例如

1、FAST

// FAST 特征检测器,阈值为 40
cv::Ptr<cv::FastFeatureDetector> ptrFAST =
        cv::FastFeatureDetector::create(40);
// 检测关键点
ptrFAST->detect(image,keypoints);

2、SURF

// 创建 SURF 特征检测器对象
cv::Ptr<cv::xfeatures2d::SurfFeatureDetector> ptrSURF =
        cv::xfeatures2d::SurfFeatureDetector::create(2000.0);

// 检测关键点
ptrSURF->detect(image, keypoints);

3、SIFT

// 构建 SIFT 特征检测器实例
cv::Ptr<cv::xfeatures2d::SiftFeatureDetector> ptrSIFT =
        cv::xfeatures2d::SiftFeatureDetector::create();
// 检测关键点
ptrSIFT->detect(image, keypoints);

4、BRISK

// 构造 BRISK 特征检测器对象
cv::Ptr<cv::BRISK> ptrBRISK = cv::BRISK::create();
// 检测关键点
ptrBRISK->detect(image, keypoints);

5、ORB

// 构造 ORB 特征检测器对象
cv::Ptr<cv::ORB> ptrORB =
        cv::ORB::create(75, // 关键点的总数
                        1.2, // 图层之间的缩放因子
                        8); // 金字塔的图层数量
// 检测关键点
ptrORB->detect(image, keypoints);
opencv
OpenCV: 开源计算机视觉库

二、特征匹配

 

五种方法的使用都非常相似,接下来给出一个具体的例子

1、画图函数

cv::drawMatches(image1, keypoints1, // 第一幅图像
        image2, keypoints2, // 第二幅图像
        matches, // 匹配项的向量
        matchImage,//最终图像
        cv::Scalar(255, 255, 255), // 线条颜色
        cv::Scalar(255, 255, 255)); // 点的颜色

2、匹配

std::vector<cv::DMatch> matches; //存放匹配关系

这里将主要几条语句拿出来看,建议直接看下边源码注释

//patch1、patch2是两幅图片特征点附近的一块矩形区域,两者进行比较,
//结果存放在result中
cv::matchTemplate(patch1, patch2, result, cv::TM_SQDIFF);

三、示例

int main()
{
    cv::Mat image = cv::imread("hy.jpg", 1);
    cv::pyrDown(image, image);
    cv::Mat image1 = image.clone();
    cv::Mat image2 = image.clone();
    cv::Ptr<cv::FeatureDetector> ptrDetector; // 泛型检测器指针
    ptrDetector = // 这里选用 FAST 检测器
        cv::FastFeatureDetector::create(80);
    // 检测关键点
    std::vector<cv::KeyPoint>keypoints1, keypoints2;
    ptrDetector->detect(image1, keypoints1);
    ptrDetector->detect(image2, keypoints2);

    const int nsize(11); // 邻域的尺寸
    cv::Rect neighborhood(0, 0, nsize, nsize); // 11×11
    cv::Mat patch1;
    cv::Mat patch2;

    cv::Mat result;
    std::vector<cv::DMatch> matches;

    for (int i = 0; i < keypoints1.size(); i++) {
        // 定义图像块
        neighborhood.x = keypoints1[i].pt.x - nsize / 2;
        neighborhood.y = keypoints1[i].pt.y - nsize / 2;
        if (neighborhood.x < 0 || neighborhood.y < 0 ||
            neighborhood.x + nsize >= image1.cols ||
            neighborhood.y + nsize >= image1.rows)
            continue;
        patch1 = image1(neighborhood);
        cv::DMatch bestMatch;
        for (int j = 0; j < keypoints2.size(); j++) {
            // 定义图像块
            neighborhood.x = keypoints2[j].pt.x - nsize / 2;
            neighborhood.y = keypoints2[j].pt.y - nsize / 2;
            // 如果邻域超出图像范围,就继续处理下一个点
            if (neighborhood.x < 0 || neighborhood.y < 0 ||
                neighborhood.x + nsize >= image2.cols ||
                neighborhood.y + nsize >= image2.rows)
                continue;
            // 第二幅图像的块
            patch2 = image2(neighborhood);
            // 匹配两个图像块
            cv::matchTemplate(patch1, patch2, result, cv::TM_SQDIFF);
            // 检查是否为最佳匹配
            if (result.at<float>(0, 0) < bestMatch.distance) {
                bestMatch.distance = result.at<float>(0, 0);
                bestMatch.queryIdx = i;
                bestMatch.trainIdx = j;
            }
        }
        // 添加最佳匹配
        matches.push_back(bestMatch);
    }
    //取25条相关性最强的匹配
    std::nth_element(matches.begin(), matches.begin() + 25, matches.end());
    matches.erase(matches.begin() + 25, matches.end());

    cv::Mat matchImage;
    cv::drawMatches(image1, keypoints1, // 第一幅图像
        image2, keypoints2, // 第二幅图像
        matches, // 匹配项的向量
        matchImage,//最终图像
        cv::Scalar(255, 255, 255), // 线条颜色
        cv::Scalar(255, 255, 255)); // 点的颜色

    cv::imshow("image", matchImage);
    cv::waitKey(0);
}

 下边是匹配结果:(想更换检测器的可以按照第一部分直接将对应代码替换掉

 

推荐内容
阅读全文
AI总结
GitHub 加速计划 / opencv31 / opencv
187
14
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:7 个月前 )
0b315598 Added reinterpret() method to Mat to convert meta-data without actual data conversion 1 天前
d49dee83 videoio: fixed V4L frame size for non-BGR output 2 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐