OpenCV: howto use mask parameter for feature point detection (SURF)
Solution 1
Two things about the mask.
- the mask should be a 1-channel matrix of 8-bit unsigned chars, which translates to opencv type
CV_8U
. In your case the mask is of type srcImage.type(), which is a 3-channel matrix - you are passing
roi
to the detector but you should be passingmask
. When you are making changes toroi
, you are also changingmask
.
the following should work
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
Solution 2
I tacked your ROI code onto some existing code I was working on, with the following changes it worked for me
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);
Without the changes to the type and the use of mask
instead of roi
as your mask, I'd get a runtime error as well. This makes sense, as the detect method wants a mask -- it should be the same size as the original image, and roi isn't (it's a 100x100 rectangle). To see this visually, try displaying the mask and the roi
cv::imshow("Mask", mask);
cv::waitKey(0);
cv::imshow("ROI", roi);
cv::waitKey(0);
The type has to match also; the mask should be single channel, while your image type is likely of type 16, which maps to CV_8UC3
, a triple channel image
Hyndrix
Updated on September 26, 2020Comments
-
Hyndrix over 3 years
I want to limit a SurfFeatureDetector to a set of regions (mask). For a test I define only a single mask:
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
When I pass the "roi" as the mask I get this error:
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
What is wrong with this? How can I correctly pass a mask to the SurfFeatureDetector's "detect" method?
Regards,
-
Martin R. over 8 yearsI think it should be
Scalar(255);
as the mask is 1-dimensional.