2

I've perused this site for an explanation but to no avail...hopefully someone knows the answer.

I'm using simpleBlobDetector to track some blobs. I would like to specify a mask via the detect method, but for some reason the mask doesn't seem to work - my keypoints show up for the whole image. Here are some snippets of my code:

Mat currFrame;
Mat mask;
Mat roi;
cv::Ptr<cv::FeatureDetector> blob_detector = new cv::SimpleBlobDetector(params);//custom set of params I've left out for legibility 
blob_detector->create("SimpleBlob");

vector<cv::KeyPoint> myblob;

while(true)
{   
    captured >> currFrame; // get a new frame from camera >> is grab and retrieve in one go, note grab does not allow frame to be modified but edges can be

    // do nothing if frame is empty
    if(currFrame.empty())
    {
        break;
    }

    /******************** make mask***********************/
    mask = Mat::zeros(currFrame.size(),CV_8U);
    roi = Mat(mask,Rect(400,400,400,400));
    roi = 255;

    /******************** image cleanup with some filters*/
    GaussianBlur(currFrame,currFrame, Size(5,5), 1.5, 1.5);
    cv::medianBlur(currFrame,currFrame,3);

    blob_detector->detect(fgMaskMOG,myblob,mask);//fgMaskMOG is currFrame after some filtering and background subtraction
    cv::drawKeypoints(fgMaskMOG,myblob,fgMaskMOG,Scalar::all(-1), DrawMatchesFlags::DRAW_RICH_KEYPOINTS );

    imshow("mogForeground", fgMaskMOG);
    imshow("original", currFrame);
    imshow("mask",mask);
    if(waitKey(1) != -1)
        break;
}

The thing is, I confirmed that my mask is correctly made by using SurfFeatureDetector as described here (OpenCV: howto use mask parameter for feature point detection (SURF)) If anyone can see whats wrong with my mask, I'd really appreciate the help. Sorry about the messy code!

Community
  • 1
  • 1
loktinl
  • 21
  • 2

2 Answers2

0

I had the same issue and couldn't find the solution, so I solved it by checking the mask myself:

blob_detector->detect(img, keypoints);

std::vector<cv::KeyPoint> keypoints_in_range;

for (cv::KeyPoint &kp : keypoints)
    if (mask.at<char>(kp.pt) > 0)
         keypoints_in_range.push_back(kp)
Astone
  • 1
  • 1
0

I found i opencv2.4.8 this code:

void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, const cv::Mat&) const
{
    //TODO: support mask
    keypoints.clear();
    Mat grayscaleImage;

which means that this option is not supported yet.

Solution with filtering keyPoints is not quite good, because it is time taking ( you have to detect blobs in whole image ).

Better workaround is to cut ROI before detection and move each KeyPoint after detection:

int x = 500;
int y = 200;
int width = 700;
int height = 700;

Mat roi = frame(Rect(x,y,width,height));

blob_detector.detect(roi, keypoints);

for (KeyPoint &kp : keypoints)
{
    kp.pt.x +=x;
    kp.pt.y +=y;
}

drawKeypoints(frame, keypoints, frame,Scalar::all(-1), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
klaxon
  • 415
  • 6
  • 10