当前位置: 首页 > article >正文

落地 基于特征的对象检测

首先要通过暴力匹配对比出图像和目标图像的相同点


using namespace std;

int main(int argc, char** argv) {
    // Mat image = imread("D:/images/butterfly.jpg");
    Mat book = imread("C:/newword/image/29.jpg");
    Mat book_on_desk = imread("C:/newword/image/30.jpg");
    imshow("book", book);
    auto orb = ORB::create(500);
    vector<KeyPoint> kypts_book;
    vector<KeyPoint> kypts_book_on_desk;
    Mat desc_book, desc_book_on_desk;
    orb->detectAndCompute(book, Mat(), kypts_book, desc_book);
    orb->detectAndCompute(book_on_desk, Mat(), kypts_book_on_desk, desc_book_on_desk);
    Mat result;
    auto bf_matcher = BFMatcher::create(NORM_HAMMING, false);
    vector<DMatch> matches;
    bf_matcher->match(desc_book, desc_book_on_desk, matches);
    float good_rate = 0.15f;//用于筛选相同点位
    int num_good_matches = matches.size() * good_rate;
    std::cout << num_good_matches << std::endl;
    std::sort(matches.begin(), matches.end());//从高到低排序
    matches.erase(matches.begin() + num_good_matches, matches.end());//筛选目标点位
    drawMatches(book, kypts_book, book_on_desk, kypts_book_on_desk, matches, result);//绘制
    imshow("暴力匹配23", result);



接下来处理锁定目标图片

    vector<Point2f> obj_pts;
    vector<Point2f> scene_pts;
    for (size_t t = 0; t < matches.size(); t++) {
        obj_pts.push_back(kypts_book[matches[t].queryIdx].pt);
        scene_pts.push_back(kypts_book_on_desk[matches[t].trainIdx].pt);
    }//

用作对比

在OpenCV的特征匹配相关操作中,queryIdx 和 trainIdx 用于区分不同图像中的特征点索引,.pt 用于获取对应特征点的坐标,它们的区别如下:

• queryIdx 及 queryIdx].pt:queryIdx 是指在查询图像(query image)的特征点集合中的索引。比如在进行图像匹配时,将一幅图像设为查询图像,要在另一幅图像中找与它匹配的部分,queryIdx 就用来索引查询图像中的特征点,queryIdx].pt 就是通过该索引获取到的查询图像中特征点的坐标。

• trainIdx 及 trainIdx].pt:trainIdx 是在训练图像(train image)的特征点集合中的索引。在图像匹配任务里,训练图像是用来与查询图像进行匹配对比的图像,trainIdx 用于索引训练图像中的特征点,trainIdx].pt 就是获取到的训练图像中对应特征点的坐标。

例如在代码 obj_pts.push_back(kypts_book[matches[t].queryIdx].pt); 与 scene_pts.push_back(kypts_book_on_desk[matches[t].trainIdx].pt); 中,queryIdx 用于从 kypts_book(可视为查询图像的特征点集)中取点,trainIdx 用于从 kypts_book_on_desk(可视为训练图像的特征点集)中取点,分别获取在不同图像中相互匹配的特征点坐标。

    Mat h = findHomography(obj_pts, scene_pts, RANSAC);//

功能

findHomography函数用于计算两个平面之间的单应性矩阵。简单来说,就是在已知两组对应点的情况下,找到一个能够将一组点通过透视变换映射到另一组点的变换矩阵,这个矩阵就被称为单应性矩阵。它在图像配准、图像拼接、相机标定等计算机视觉任务中有着广泛的应用。

    ●    obj_pts:这是源图像(这里指 book 图像)中匹配点的坐标集合,作为单应性矩阵计算的输入点集之一。这些点将通过计算得到的单应性矩阵映射到目标图像中的对应位置。

    ●    scene_pts:目标图像(book_on_desk 图像)中与 obj_pts 对应的匹配点坐标集合。它与 obj_pts 共同决定了单应性矩阵的计算,使得通过该矩阵能够将 obj_pts 中的点尽可能准确地映射到 scene_pts 中的位置。

    ●    RANSAC:这是指定的计算单应性矩阵的方法,即随机抽样一致性(Random Sample Consensus)算法。由于在实际的特征匹配中,可能存在误匹配点(外点),RANSAC 算法能够通过多次随机抽样,从包含外点的数据中估计出最优的单应性矩阵。它会尝试不同的点对组合来计算单应性矩阵,并根据重投影误差来判断哪些点是内点(正确匹配的点)。经过多次迭代,选择内点数量最多的那个单应性矩阵作为最终结果,从而提高了单应性矩阵计算的准确性和鲁棒性。

    vector<Point2f> srcPts;
    srcPts.push_back(Point2f(0, 0));
    srcPts.push_back(Point2f(book.cols, 0));
    srcPts.push_back(Point2f(book.cols, book.rows));
    srcPts.push_back(Point2f(0, book.rows));

    std::vector<Point2f> dstPts(4);
    perspectiveTransform(srcPts, dstPts, h);

perspectiveTransform 通常是计算机视觉库(如OpenCV)中的一个函数,用于执行透视变换操作,以下是关于它的详述:

函数功能

perspectiveTransform 主要用于对一组点或图像进行透视变换。它根据给定的透视变换矩阵,将源坐标系统中的点映射到目标坐标系统中,实现图像的视角变换、校正等操作,常用于图像校正、图像拼接、目标识别等计算机视觉任务。

在perspectiveTransform函数中,dst是结合src和m来输出的。具体来说:

    ●    src是输入的源数据,它可以是一组点的坐标集合,也可以是一幅图像等数据,代表了要进行透视变换的原始对象。

    ●    m是3×3的透视变换矩阵,它定义了从源坐标系统到目标坐标系统的映射关系,决定了透视变换的具体方式和效果,比如旋转、缩放、平移、扭曲等操作的组合。

    ●    dst作为函数的输出参数,根据src提供的原始数据,按照m所定义的变换规则,存储经过透视变换后的结果。函数通过将src中的每个元素(如点的坐标)与变换矩阵m进行相应的数学运算,来计算出在目标空间中的新位置,并将结果存储到dst中。

    for (int i = 0; i < 4; i++) {
        line(book_on_desk, dstPts[i], dstPts[(i + 1) % 4], Scalar(0, 0, 255), 2, 8, 0);
    }
    imshow("暴力匹配", result);
    namedWindow("对象检测", WINDOW_FREERATIO);
    imshow("对象检测", book_on_desk);
    imwrite("C:/newword/31.jpg", book_on_desk);
    waitKey(0);
    return 0;
}


http://www.kler.cn/a/521993.html

相关文章:

  • 【MySQL】悲观锁和乐观锁的原理和应用场景
  • Helm Chart 实战指南
  • 微服务入门(go)
  • 【微服务与分布式实践】探索 Sentinel
  • 春晚舞台上的人形机器人:科技与文化的奇妙融合
  • CMAKE工程编译好后自动把可执行文件传输到远程开发板
  • leetcode 面试经典 150 题:简化路径
  • 鲁滨逊漂流记读后感
  • 【PySide6快速入门】QGridLayout 网格布局
  • 如何使用 DeepSeek API 结合 VSCode 提升开发效率
  • 深度学习笔记13-CIFAR彩色图片识别(Pytorch)
  • 供应链管理中的BOM 和 MRP 是什么,如何计算
  • 探索前端可观察性:如何使用Telemetry提高用户体验
  • 基于Java+Springboot+MySQL校园在线考试网站系统设计与实现
  • zyNo.19
  • 解析“in the wild”——编程和生活中的俚语妙用
  • 八股——Java基础(四)
  • 【PySide6拓展】QLCDNumber类lcd 显示数字
  • 多级缓存(亿级并发解决方案)
  • C#常用257单词
  • 基于RIP的MGRE实验
  • MySQL 主从同步报错:`Unknown or incorrect time zone` 问题全解析
  • 【GESP】2024 C++ 一级编程题解析及测试信息下载
  • UART ,IIC 和SPI三种总线协议
  • C# 中 [MethodImpl(MethodImplOptions.Synchronized)] 的使用详解
  • Tensor 基本操作5 device 管理,使用 GPU 设备 | PyTorch 深度学习实战