【问题标题】:OpenCV: howto use mask parameter for feature point detection (SURF)OpenCV:如何使用掩码参数进行特征点检测(SURF)
【发布时间】:2013-04-28 05:22:46
【问题描述】:

我想将 SurfFeatureDetector 限制为一组区域(掩码)。对于测试,我只定义了一个掩码:

Mat srcImage; //RGB source image
Mat mask = Mat::zeros(srcImage.size(), srcImage.type());
Mat roi(mask, cv::Rect(10,10,100,100));
roi = Scalar(255, 255, 255);
SurfFeatureDetector detector();
std::vector<KeyPoint> keypoints;
detector.detect(srcImage, keypoints, roi); // crash
//detector.detect(srcImage, keypoints); // does not crash

当我将“roi”作为掩码传递时,我收到此错误:

OpenCV Error: Assertion failed (mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size())) in detect, file /Users/ux/Downloads/OpenCV-iOS/OpenCV-iOS/../opencv-svn/modules/features2d/src/detectors.cpp, line 63

这有什么问题?如何正确地将掩码传递给 SurfFeatureDetector 的“检测”方法?

问候,

【问题讨论】:

    标签: c++ opencv feature-detection surf roi


    【解决方案1】:

    关于面具的两件事。

    • 掩码应该是一个 8 位无符号字符的 1 通道矩阵,转换为 opencv 类型 CV_8U。在您的情况下,掩码的类型为 srcImage.type(),它是一个 3 通道矩阵
    • 您正在将roi 传递给检测器,但您应该传递mask。当您对roi 进行更改时,您也在更改mask

    以下应该可以工作

    Mat srcImage; //RGB source image
    Mat mask = Mat::zeros(srcImage.size(), CV_8U);  // type of mask is CV_8U
    // roi is a sub-image of mask specified by cv::Rect object
    Mat roi(mask, cv::Rect(10,10,100,100));
    // we set elements in roi region of the mask to 255 
    roi = Scalar(255);  
    SurfFeatureDetector detector();
    std::vector<KeyPoint> keypoints;
    detector.detect(srcImage, keypoints, mask);     // passing `mask` as a parameter
    

    【讨论】:

    • 我认为应该是Scalar(255);,因为掩码是一维的。
    【解决方案2】:

    我将您的 ROI 代码添加到我正在处理的一些现有代码上,并进行了以下对我有用的更改

    cv::Mat mask = cv::Mat::zeros(frame.size(), CV_8UC1);  //NOTE: using the type explicitly
    cv::Mat roi(mask, cv::Rect(10,10,100,100));
    roi = cv::Scalar(255, 255, 255);
    
    //SURF feature detection
    const int minHessian = 400;
    cv::SurfFeatureDetector detector(minHessian);
    std::vector<cv::KeyPoint> keypoints;
    detector.detect(frame, keypoints, mask);              //NOTE: using mask here, NOT roi
    cv::Mat img_keypoints; 
    drawKeypoints(frame, keypoints, img_keypoints, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);
    cv::imshow("input image + Keypoints", img_keypoints);
    cv::waitKey(0);
    

    如果不更改类型并使用 mask 而不是 roi 作为掩码,我也会收到运行时错误。这是有道理的,因为检测方法需要一个掩码——它应该与原始图像的大小相同,而 roi 不是(它是一个 100x100 的矩形)。要直观地看到这一点,请尝试显示蒙版和 roi

    cv::imshow("Mask", mask);
    cv::waitKey(0);
    
    cv::imshow("ROI", roi);
    cv::waitKey(0);
    

    类型也必须匹配;掩码应该是单通道,而您的图像类型可能是类型 16,它映射到 CV_8UC3,三通道图像

    【讨论】:

      【解决方案3】:

      如果您希望对不规则蒙版应用相同的方法,那么:

      Mat& obtainIregularROI(Mat& origImag, Point2f topLeft, Point2f topRight, Point2f botLeft, Point2f botRight){
      
              static Mat black(origImag.rows, origImag.cols, origImag.type(), cv::Scalar::all(0));
              Mat mask(origImag.rows, origImag.cols, CV_8UC1, cv::Scalar(0));
              vector< vector<Point> >  co_ordinates;
              co_ordinates.push_back(vector<Point>());
              co_ordinates[0].push_back(topLeft);
              co_ordinates[0].push_back(botLeft);
              co_ordinates[0].push_back(botRight);
              co_ordinates[0].push_back(topRight);
              drawContours( mask,co_ordinates,0, Scalar(255),CV_FILLED, 8 );
      
             // origImag.copyTo(black,mask);
              //BasicAlgo::getInstance()->writeImage(black);
              return mask;  // returning the mask only
          }
      

      然后像往常一样,生成SIFT/SURF/...指针

      // 为 SIFT 特征检测器创建智能指针。

      Ptr<FeatureDetector> SIFT_FeatureDetector = FeatureDetector::create("SIFT");
      vector<KeyPoint> SIFT_Keypoints;
      vector<KeyPoint> SIFT_KeypointsRotated; 
      Mat maskedImg = ImageDeformationOperations::getInstance()->obtainIregularROI( rotatedImg,rotTopLeft,rotTopRight,rotBotLeft,rotBotRight);
      SIFT_FeatureDetector->detect(rotatedImg, SIFT_KeypointsRotated, maskedImg);
      Mat outputSIFTKeyPt;
      drawKeypoints(rotatedImg, SIFT_KeypointsRotated, outputSIFTKeyPt, keypointColor, DrawMatchesFlags::DEFAULT);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-30
        • 2023-03-21
        • 2017-07-09
        • 2013-03-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-24
        • 1970-01-01
        相关资源
        最近更新 更多