飞行器视觉第四题

对图像进行二值化

阈值180
阈值190

 分析:感觉阈值180-190比较合适,想把机场检测出来,其他都过滤掉。

基于sift特征的模板匹配

首先这是一段GPT给出的代码,但仍需要逐句分析

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

int main() {
    // 读取原图像和模板图像
    cv::Mat originalImage = cv::imread("original_image.jpg", cv::IMREAD_GRAYSCALE);
    cv::Mat templateImage = cv::imread("template_image.jpg", cv::IMREAD_GRAYSCALE);

    // 创建SIFT检测器
    cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();

    // 检测关键点和计算描述符
    std::vector<cv::KeyPoint> keypointsOriginal, keypointsTemplate;
    cv::Mat descriptorsOriginal, descriptorsTemplate;
    sift->detectAndCompute(originalImage, cv::noArray(), keypointsOriginal, descriptorsOriginal);
    sift->detectAndCompute(templateImage, cv::noArray(), keypointsTemplate, descriptorsTemplate);

    // 使用FLANN匹配器
    cv::FlannBasedMatcher matcher;
    std::vector<std::vector<cv::DMatch>> knnMatches;
    matcher.knnMatch(descriptorsTemplate, descriptorsOriginal, knnMatches, 2);

    // 比率测试,以获取良好的匹配
    std::vector<cv::DMatch> goodMatches;
    for (size_t i = 0; i < knnMatches.size(); ++i) {
        if (knnMatches[i][0].distance < 0.7 * knnMatches[i][1].distance) {
            goodMatches.push_back(knnMatches[i][0]);
        }
    }

    // 获取匹配点的位置
    std::vector<cv::Point2f> matchedPointsTemplate, matchedPointsOriginal;
    for (const auto& match : goodMatches) {
        matchedPointsTemplate.push_back(keypointsTemplate[match.queryIdx].pt);
        matchedPointsOriginal.push_back(keypointsOriginal[match.trainIdx].pt);
    }

    // 计算透视变换矩阵
    cv::Mat homography = cv::findHomography(matchedPointsTemplate, matchedPointsOriginal, cv::RANSAC);

    // 获取模板图像的四个角在原图像上的位置
    std::vector<cv::Point2f> templateCorners(4);
    templateCorners[0] = cv::Point2f(0, 0);
    templateCorners[1] = cv::Point2f(static_cast<float>(templateImage.cols), 0);
    templateCorners[2] = cv::Point2f(static_cast<float>(templateImage.cols), static_cast<float>(templateImage.rows));
    templateCorners[3] = cv::Point2f(0, static_cast<float>(templateImage.rows));

    std::vector<cv::Point2f> transformedCorners(4);
    cv::perspectiveTransform(templateCorners, transformedCorners, homography);

    // 在原图像上绘制矩形框
    cv::Mat resultImage = originalImage.clone();
    cv::polylines(resultImage, transformedCorners, true, cv::Scalar(0, 255, 0), 2, cv::LINE_AA);

    // 显示结果
    cv::imshow("SIFT Matches", resultImage);
    cv::waitKey(0);
    cv::destroyAllWindows();

    return 0;
}

对左侧图像进行sift特征点匹配

对右侧图像进行sift特征匹配

SIFT特征具有良好的尺度不变性、旋转不变性

存在的问题

我现在存在的问题就是,给我一个模板,我能识别出来,但是多个目标就不行。

GPT给了我一个在原图上检测出所有与模板相似的目标的的做法,用的是滑动窗口技术。

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

int main() {
    cv::Mat originalImage = cv::imread("original_image.jpg", cv::IMREAD_GRAYSCALE);
    cv::Mat templateImage = cv::imread("template_image.jpg", cv::IMREAD_GRAYSCALE);

    // 创建 ORB 检测器
    cv::Ptr<cv::ORB> orb = cv::ORB::create();

    // 检测关键点和计算描述符
    std::vector<cv::KeyPoint> keypointsOriginal, keypointsTemplate;
    cv::Mat descriptorsOriginal, descriptorsTemplate;
    orb->detectAndCompute(originalImage, cv::noArray(), keypointsOriginal, descriptorsOriginal);
    orb->detectAndCompute(templateImage, cv::noArray(), keypointsTemplate, descriptorsTemplate);

    // 创建 BFMatcher 进行匹配
    cv::BFMatcher matcher(cv::NORM_HAMMING);

    // 设置滑动窗口的步长
    int stepSize = 20;

    // 设置窗口的大小
    int windowSize = templateImage.rows;

    for (int y = 0; y < originalImage.rows - windowSize; y += stepSize) {
        for (int x = 0; x < originalImage.cols - windowSize; x += stepSize) {
            // 获取当前窗口
            cv::Rect windowRect(x, y, windowSize, windowSize);
            cv::Mat window = originalImage(windowRect);

            // 检测关键点和计算描述符
            std::vector<cv::KeyPoint> keypointsWindow;
            cv::Mat descriptorsWindow;
            orb->detectAndCompute(window, cv::noArray(), keypointsWindow, descriptorsWindow);

            // 进行匹配
            std::vector<cv::DMatch> matches;
            matcher.match(descriptorsTemplate, descriptorsWindow, matches);

            // 判断匹配是否足够
            if (matches.size() > /*设置一个阈值*/) {
                // 匹配成功,可以在原图上标记目标
                cv::rectangle(originalImage, windowRect, cv::Scalar(0, 255, 0), 2);
            }
        }
    }

    // 显示结果
    cv::imshow("Object Detection", originalImage);
    cv::waitKey(0);
    cv::destroyAllWindows();

    return 0;
}

如果只有一个目标,sift特征可以很好的匹配上,但如果有多个目标,sift特征就不能很好的匹配上

 

匹配的结果很差,为什么呢?

问题一:多目标匹配困难 

解决措施:采用滑动窗口 

在用sift进行匹配的时候,如果原始图像里只有一个目标,就能很好的匹配上,原始图像里有多个目标,就不能很好的匹配上 

这里是一些做测试的代码

 //
 std::vector<std::vector<cv::DMatch>> knnMatches;
 matcher.knnMatch(descriptorsTemplate, descriptorsOriginal, knnMatches, 2);

 //**可视化一下未经比率测试的sift特征匹配

 //cv::Mat imgMatches;
// cv::drawMatches(templateImage, keypointsTemplate, originalImage, keypointsOriginal, knnMatches, imgMatches);

 //cv::imshow("Resizable Window", imgMatches);
// cv::waitKey(0);

 // 比率测试,以获取良好的匹配
 std::vector<cv::DMatch> goodMatches;
 for (size_t i = 0; i < knnMatches.size(); ++i) {
     if (knnMatches[i][0].distance < 0.85 * knnMatches[i][1].distance) {
         goodMatches.push_back(knnMatches[i][0]);
     }
 }
  //**可视化一下经过比率测试的sift特征
 cv::Mat imgMatches;
 cv::drawMatches(templateImage, keypointsTemplate, originalImage, keypointsOriginal, goodMatches, imgMatches);

 cv::imshow("Resizable Window", imgMatches);
 cv::waitKey(0);

//     为每个目标创建容器来存储匹配点和透视变换矩阵

 std::vector<std::vector<cv::Point2f>> allMatchedPoints;
 std::vector<cv::Mat> allHomographies;

 // 获取匹配点的位置

 for (const auto& match : goodMatches) {
     std::vector<cv::Point2f> matchedPointsTemplate, matchedPointsOriginal;

     matchedPointsTemplate.push_back(keypointsTemplate[match.queryIdx].pt);
     matchedPointsOriginal.push_back(keypointsOriginal[match.trainIdx].pt);

    //打印匹配点数量
    
     std::cout << "Matched Points:" << std::endl;
     for (size_t i = 0; i < matchedPointsTemplate.size(); ++i) {
         std::cout << "Template: " << matchedPointsTemplate[i] << " - Original: " << matchedPointsOriginal[i] << std::endl;
     }


     // 计算透视变换矩阵
     cv::Mat homography = cv::findHomography(matchedPointsTemplate, matchedPointsOriginal, cv::RANSAC);

     // 存储匹配点和透视变换矩阵
     allMatchedPoints.push_back(matchedPointsTemplate);
     allHomographies.push_back(homography);
 }

 
  //在原图像上绘制矩阵框

 cv::Mat resultImage = originalImage.clone();
 for (size_t i = 0; i < allHomographies.size(); ++i) {
     std::vector<cv::Point2f> templateCorners(4);
     templateCorners[0] = cv::Point2f(0, 0);
     templateCorners[1] = cv::Point2f(static_cast<float>(templateImage.cols), 0);
     templateCorners[2] = cv::Point2f(static_cast<float>(templateImage.cols), static_cast<float>(templateImage.rows));
     templateCorners[3] = cv::Point2f(0, static_cast<float>(templateImage.rows));
     std::vector<cv::Point2f> transformedCorners(4);

     // 应用透视变换
     cv::perspectiveTransform(templateCorners, transformedCorners, allHomographies[i]);

     // 转换坐标为整数类型
     std::vector<cv::Point> transformedCornersInt(4);
     for (int j = 0; j < 4; ++j) {
         transformedCornersInt[j] = cv::Point(static_cast<int>(transformedCorners[j].x), static_cast<int>(transformedCorners[j].y));
     }

     // 在原图像上绘制矩形框
     cv::polylines(resultImage, transformedCornersInt, true, cv::Scalar(0, 255, 0), 2, cv::LINE_AA);
 }


 // 显示结果




 cv::imshow("Resizable Window", resultImage);
 cv::waitKey(0);
 cv::destroyAllWindows();

 return 0;

问题二: 窗口大小

窗口大小对于多目标的检测至关重要! 

问题三:关键点

很好,调整了一下成这样了

参数:

最终算法还是存在问题

最终算法并不能实现多目标的检测

换一种特征试试呢

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值