求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 


业务架构设计
4月18-19日 在线直播



基于UML和EA进行系统分析设计
4月25-26日 北京+在线



AI 智能化软件测试方法与实践
5月23-24日 上海+在线
 
追随技术信仰

随时听讲座
每天看新闻
 
 
OpenCV 教程
1. OpenCV 简介
2. OpenCV 安装
3. OpenCV 安装(C++)
Python OpenCV
4. OpenCV 入门实例
5. OpenCV 基础模块
6. OpenCV 图像处理基础
7. OpenCV 图像基本操作
8. OpenCV 图像算术运算
9. OpenCV 图像阈值处理
10. OpenCV 图像平滑处理
11. OpenCV 图像形态学操作
12. OpenCV 图像边缘检测
13. OpenCV 图像轮廓检测
14. OpenCV 图像直方图
15. OpenCV 视频处理
16. OpenCV 视频目标跟踪
17. OpenCV 视频背景减除
18. OpenCV 人脸检测
19. OpenCV 物体识别
20. OpenCV 图像拼接
21. OpenCV 简单滤镜效果
C++ OpenCV
22. C++ OpenCV 基础操作
23. C++ OpenCV 图像处理
24. C++ OpenCV 基本模块介绍
25. C++ OpenCV 特征检测与描述
26. C++ OpenCV 高级图像处理
27. C++ OpenCV 视频处理
28. C++ OpenCV 机器学习与深度学习
29. C++ OpenCV 项目实战
30. C++ OpenCV 性能优化
 
 
目录
C++ OpenCV 特征检测与描述
56 次浏览
4次  

特征检测与描述是计算机视觉中的核心技术,用于从图像中提取关键点(Keypoints)并计算其描述符(Descriptors)。这些关键点和描述符可以用于图像匹配、目标识别、3D 重建等任务。

主要步骤

  • 特征检测:检测图像中的关键点(如角点、边缘等)。

  • 特征描述:为每个关键点计算描述符,用于表示关键点周围的局部特征。

  • 特征匹配:通过比较描述符,找到不同图像中相似的关键点。

  • 特征检测与描述:通过特征匹配找到两幅图像中相似的关键点,用于图像拼接、全景图生成等。

  • 目标识别:提取目标图像的特征,与数据库中的特征进行匹配,实现目标识别。

  • 3D 重建:通过多视图图像中的特征点匹配,计算相机的位姿并重建 3D 场景。

  • 实时跟踪:在视频序列中检测和跟踪特征点,用于 SLAM(同步定位与地图构建)等应用。

常用特征检测与描述算法

OpenCV 提供了多种特征检测与描述算法,以下是常见的几种:

角点检测

角点是图像中亮度变化剧烈的点,通常位于物体的边缘或纹理丰富的区域。角点检测是特征检测的基础,常用的角点检测算法有 Harris 角点检测和 Shi-Tomasi 角点检测。

Harris角点检测

Harris 角点检测是一种经典的角点检测算法,它通过计算图像中每个像素点的自相关矩阵来判断该点是否为角点。自相关矩阵的特征值可以反映该点的局部结构:如果两个特征值都很大,则该点很可能是角点;如果一个特征值很大,另一个很小,则该点可能是边缘;如果两个特征值都很小,则该点可能是平坦区域。

在 OpenCV 中,可以使用 cv::cornerHarris 函数来实现 Harris 角点检测:

实例

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
    cv::Mat dst, dst_norm;

    // Harris角点检测
    cv::cornerHarris(src, dst, 2, 3, 0.04);

    // 归一化并显示结果
    cv::normalize(dst, dst_norm, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
    cv::imshow("Harris Corners", dst_norm);
    cv::waitKey(0);

    return 0;
}

Shi-Tomasi 角点检测

Shi-Tomasi角点检测是对Harris角点检测的改进,它通过计算图像中每个像素点的最小特征值来判断该点是否为角点。与Harris角点检测相比,Shi-Tomasi角点检测更加稳定,且计算量较小。

在OpenCV中,可以使用cv::goodFeaturesToTrack函数来实现Shi-Tomasi角点检测:

实例

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
    std::vector<cv::Point2f> corners;

    // Shi-Tomasi角点检测
    cv::goodFeaturesToTrack(src, corners, 100, 0.01, 10);

    // 绘制角点
    for (size_t i = 0; i < corners.size(); i++) {
        cv::circle(src, corners[i], 5, cv::Scalar(0, 0, 255), 2);
    }

    cv::imshow("Shi-Tomasi Corners", src);
    cv::waitKey(0);

    return 0;
}

特征点检测

特征点检测是提取图像中具有独特性质的点,这些点通常具有旋转、缩放、光照不变性。常用的特征点检测算法有SIFT、SURF和ORB。

SIFT 算法

SIFT(Scale-Invariant Feature Transform)是一种基于尺度空间的特征点检测算法,它对图像的旋转、缩放、亮度变化具有不变性。SIFT算法通过检测图像中的极值点,并计算这些点的梯度方向直方图来生成特征描述子。

在 OpenCV 中,可以使用cv::xfeatures2d::SIFT类来实现SIFT特征点检测:

实例

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>

int main() {
    cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
    std::vector<cv::KeyPoint> keypoints;
    cv::Mat descriptors;

    // SIFT特征点检测
    cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();
    sift->detectAndCompute(src, cv::noArray(), keypoints, descriptors);

    // 绘制特征点
    cv::Mat output;
    cv::drawKeypoints(src, keypoints, output);
    cv::imshow("SIFT Keypoints", output);
    cv::waitKey(0);

    return 0;
}

SURF 算法

SURF(Speeded-Up Robust Features)是对SIFT算法的改进,它通过使用积分图像和Hessian矩阵来加速特征点检测过程。SURF算法在保持较高检测精度的同时,显著提高了计算速度。

在OpenCV中,可以使用cv::xfeatures2d::SURF类来实现SURF特征点检测:

实例

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>

int main() {
    cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
    std::vector<cv::KeyPoint> keypoints;
    cv::Mat descriptors;

    // SURF特征点检测
    cv::Ptr<cv::xfeatures2d::SURF> surf = cv::xfeatures2d::SURF::create();
    surf->detectAndCompute(src, cv::noArray(), keypoints, descriptors);

    // 绘制特征点
    cv::Mat output;
    cv::drawKeypoints(src, keypoints, output);
    cv::imshow("SURF Keypoints", output);
    cv::waitKey(0);

    return 0;
}

ORB 算法

ORB(Oriented FAST and Rotated BRIEF)是一种结合了FAST角点检测和BRIEF描述子的特征点检测算法。ORB算法具有较高的计算效率,适合实时应用。

在OpenCV中,可以使用cv::ORB类来实现ORB特征点检测:

实例

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
    std::vector<cv::KeyPoint> keypoints;
    cv::Mat descriptors;

    // ORB特征点检测
    cv::Ptr<cv::ORB> orb = cv::ORB::create();
    orb->detectAndCompute(src, cv::noArray(), keypoints, descriptors);

    // 绘制特征点
    cv::Mat output;
    cv::drawKeypoints(src, keypoints, output);
    cv::imshow("ORB Keypoints", output);
    cv::waitKey(0);

    return 0;
}

特征匹配

特征匹配是将两幅图像中的特征点进行匹配的过程。常用的特征匹配算法有BFMatcher(暴力匹配器)和FLANN匹配器。

BFMatcher

BFMatcher(Brute-Force Matcher)是一种简单的特征匹配算法,它通过计算特征描述子之间的欧氏距离来寻找最佳匹配点。BFMatcher适用于特征点数量较少的情况。

在OpenCV中,可以使用cv::BFMatcher类来实现BFMatcher:

实例

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>

int main() {
    cv::Mat src1 = cv::imread("image1.jpg", cv::IMREAD_GRAYSCALE);
    cv::Mat src2 = cv::imread("image2.jpg", cv::IMREAD_GRAYSCALE);
    std::vector<cv::KeyPoint> keypoints1, keypoints2;
    cv::Mat descriptors1, descriptors2;

    // SIFT特征点检测
    cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();
    sift->detectAndCompute(src1, cv::noArray(), keypoints1, descriptors1);
    sift->detectAndCompute(src2, cv::noArray(), keypoints2, descriptors2);

    // BFMatcher匹配
    cv::BFMatcher matcher(cv::NORM_L2);
    std::vector<cv::DMatch> matches;
    matcher.match(descriptors1, descriptors2, matches);

    // 绘制匹配结果
    cv::Mat output;
    cv::drawMatches(src1, keypoints1, src2, keypoints2, matches, output);
    cv::imshow("BFMatcher Matches", output);
    cv::waitKey(0);

    return 0;
}

FLANN 匹配器

FLANN(Fast Library for Approximate Nearest Neighbors)是一种近似最近邻搜索算法,它通过构建KD树或K-means树来加速特征匹配过程。FLANN匹配器适用于特征点数量较多的情况。

在OpenCV中,可以使用cv::FlannBasedMatcher类来实现FLANN匹配器:

实例

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>

int main() {
    cv::Mat src1 = cv::imread("image1.jpg", cv::IMREAD_GRAYSCALE);
    cv::Mat src2 = cv::imread("image2.jpg", cv::IMREAD_GRAYSCALE);
    std::vector<cv::KeyPoint> keypoints1, keypoints2;
    cv::Mat descriptors1, descriptors2;

    // SIFT特征点检测
    cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();
    sift->detectAndCompute(src1, cv::noArray(), keypoints1, descriptors1);
    sift->detectAndCompute(src2, cv::noArray(), keypoints2, descriptors2);

    // FLANN匹配器
    cv::FlannBasedMatcher matcher;
    std::vector<cv::DMatch> matches;
    matcher.match(descriptors1, descriptors2, matches);

    // 绘制匹配结果
    cv::Mat output;
    cv::drawMatches(src1, keypoints1, src2, keypoints2, matches, output);
    cv::imshow("FLANN Matches", output);
    cv::waitKey(0);

    return 0;
}

特征点匹配与筛选

在实际应用中,特征点匹配结果中可能存在一些错误的匹配对。为了提高匹配的准确性,通常需要对匹配结果进行筛选。常用的筛选方法有基于距离的筛选和基于几何约束的筛选。

基于距离的筛选

基于距离的筛选是通过设置一个阈值来过滤掉距离较大的匹配对。OpenCV中可以使用cv::DescriptorMatcher::radiusMatch函数来实现基于距离的筛选。

实例

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>

int main() {
    cv::Mat src1 = cv::imread("image1.jpg", cv::IMREAD_GRAYSCALE);
    cv::Mat src2 = cv::imread("image2.jpg", cv::IMREAD_GRAYSCALE);
    std::vector<cv::KeyPoint> keypoints1, keypoints2;
    cv::Mat descriptors1, descriptors2;

    // SIFT特征点检测
    cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();
    sift->detectAndCompute(src1, cv::noArray(), keypoints1, descriptors1);
    sift->detectAndCompute(src2, cv::noArray(), keypoints2, descriptors2);

    // BFMatcher匹配
    cv::BFMatcher matcher(cv::NORM_L2);
    std::vector<std::vector<cv::DMatch>> matches;
    matcher.radiusMatch(descriptors1, descriptors2, matches, 50.0);

    // 绘制匹配结果
    cv::Mat output;
    cv::drawMatches(src1, keypoints1, src2, keypoints2, matches, output);
    cv::imshow("Filtered Matches", output);
    cv::waitKey(0);

    return 0;
}

基于几何约束的筛选

基于几何约束的筛选是通过计算基础矩阵或单应性矩阵来过滤掉不符合几何约束的匹配对。OpenCV中可以使用cv::findFundamentalMat或cv::findHomography函数来实现基于几何约束的筛选。

实例

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>

int main() {
    cv::Mat src1 = cv::imread("image1.jpg", cv::IMREAD_GRAYSCALE);
    cv::Mat src2 = cv::imread("image2.jpg", cv::IMREAD_GRAYSCALE);
    std::vector<cv::KeyPoint> keypoints1, keypoints2;
    cv::Mat descriptors1, descriptors2;

    // SIFT特征点检测
    cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();
    sift->detectAndCompute(src1, cv::noArray(), keypoints1, descriptors1);
    sift->detectAndCompute(src2, cv::noArray(), keypoints2, descriptors2);

    // BFMatcher匹配
    cv::BFMatcher matcher(cv::NORM_L2);
    std::vector<cv::DMatch> matches;
    matcher.match(descriptors1, descriptors2, matches);

    // 基于几何约束的筛选
    std::vector<cv::Point2f> points1, points2;
    for (size_t i = 0; i < matches.size(); i++) {
        points1.push_back(keypoints1[matches[i].queryIdx].pt);
        points2.push_back(keypoints2[matches[i].trainIdx].pt);
    }

    cv::Mat mask;
    cv::findHomography(points1, points2, cv::RANSAC, 3, mask);

    // 筛选匹配对
    std::vector<cv::DMatch> good_matches;
    for (size_t i = 0; i < matches.size(); i++) {
        if (mask.at<uchar>(i)) {
            good_matches.push_back(matches[i]);
        }
    }

    // 绘制匹配结果
    cv::Mat output;
    cv::drawMatches(src1, keypoints1, src2, keypoints2, good_matches, output);
    cv::imshow("Filtered Matches", output);
    cv::waitKey(0);

    return 0;
}

您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码: 验证码,看不清楚?请点击刷新验证码 必填



56 次浏览
4次