【问题标题】:Please advise me about this Computer Vision task请告诉我有关此计算机视觉任务的信息
【发布时间】:2015-06-07 05:17:10
【问题描述】:

我有一些带有图像的磁铁。只有一小部分不同的图像(比如说 20 张图像),它们将在固定的棋盘中对齐(图片中仍然没有显示)。

我已经有一种算法可以从板上提取每张磁卡,对原始图像应用透视变换以防止透视失真。

我想听听您的建议,以便检测板上的每个图像,我的意思是,检测磁铁是否是:熊猫、兔子、狗、胡萝卜……因为我的主要目标是分析图像并提取包含所有棋盘元素的矩阵。

我的第一次尝试非常基础:根据平均颜色猜测图像。它不是很健壮,因为有几张图像的平均颜色相似(特别是那些冻结的卡片),而且浅色会改变很多颜色。

您能指点我正确的方向来提取包含板上所有图像的矩阵吗?我不需要具体的实现,而是需要我应该遵循的步骤的概念或应用于主图像的技术,以获得稳健(而不是太复杂)的算法。

我将使用 OpenCV 来实现它,但我想使用任何其他计算机视觉库都是一样的。

非常感谢您的宝贵时间!

【问题讨论】:

标签: image opencv image-processing computer-vision


【解决方案1】:

虽然 SIFT 或其他特征检测器运行良好且广泛适用,但我总是从最简单的可行方法开始:在您的情况下,可能是 template matching。毕竟,您已经完成了消除透视失真、旋转和不同比例的艰苦工作。

基本思想是获取 20 张模板图像中的每一张,并将其与搜索图像中的每个可能位置进行比较。由于卷积定理,这是一个相对便宜的操作。

【讨论】:

    【解决方案2】:

    下面是一些示例代码:

    void KeypointMatcher::computeMatches(cv::Mat image1, cv::Mat image2) {
            cv::initModule_nonfree();
            //Vector of keypoints   
            std::vector<cv::KeyPoint> keypoints1;
            std::vector<cv::KeyPoint> keypoints2;
            //Detect features
            cv::SiftFeatureDetector detector;
            detector.detect(image1, keypoints1);
            detector.detect(image2, keypoints2);
    
            //Compute descriptors
            cv::Mat descriptors1, descriptors2;
            cv::SiftDescriptorExtractor extractor;
            extractor.compute(image1, keypoints1, descriptors1);
            extractor.compute(image2, keypoints2, descriptors2);
    
            //Find matches
            cv::BFMatcher matcher(4, true);
            std::vector<cv::DMatch> matches;
            matcher.match(descriptors1, descriptors2, matches);
    
            //Find good points for a homography
            std::vector<cv::Point2d> matchingPoints1, matchingPoints2;
            for (cv::DMatch& match : matches) {
                matchingPoints1.push_back(keypoints1[match.queryIdx].pt);
                matchingPoints2.push_back(keypoints2[match.trainIdx].pt);
            }
            cv::Mat mask;
            cv::findHomography(matchingPoints1, matchingPoints2, CV_RANSAC, 3, mask);
    
            //Just visualisation
            std::vector<char> vectorMask;
            mask.col(0).copyTo(vectorMask);
            cv::Mat result;
            cv::drawMatches(image1, keypoints1, image2, keypoints2, matches, result, cv::Scalar::all(-1), cv::Scalar::all(-1), vectorMask);
            //cv::drawMatches(image1, keypoints1, image2, keypoints2, matches, result);
            cv::imshow("Matches", result);
            cv::waitKey();
        }
    

    它执行以下操作:它使用 SIFT 从两个图像中提取特征点。然后它找到两个图像的特征之间的匹配。但是,这仍然会包含很多垃圾匹配。但是我们知道我们正在比较的两幅图像之间的变换是透视变换,因此必须可以计算它们之间的单应性。为了找到“好”匹配,它现在使用 RANSAC 异常值过滤方法计算单应性。哪些 RANSAC 考虑异常值,哪些内部值保存在矩阵mask 中(0 表示异常值,1 表示内部值)。你现在可以例如计算该矩阵中的那些以获得良好匹配的数量。然后您可以对所有卡片的图像执行此操作并比较匹配数(例如选择匹配最多的一张)。

    代码的最后一部分将找到的匹配项可视化。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2011-05-23
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 2022-06-28
      • 2011-10-31
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      相关资源
      最近更新 更多