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,
SIFT and SURF detect more features then ORB, but ORB is faster. We then load one by one the three algorythms. We find the keypoints and descriptors of each spefic algorythm. A keypoint is the position where the feature has been detected, while the descriptor is an array containing numbers to describe that feature.
SURF is better than SIFT in rotation invariant, blur and warp transform. SIFT is better than SURF in different scale images. SURF is 3 times faster than SIFT because using of integral image and box filter. SIFT and SURF are good in illumination changes images.
Example: SIFT detector in Python jpg” generates the “image-with-keypoints. jpg” which contains the interest points, detected using the SIFT module in OpenCV, marked using circular overlays. Note: SIFT detector has been removed in the latest versions of OpenCV ( ≥ 3.4. 2.16).
Two things about the mask.
CV_8U
. In your case the mask is of type srcImage.type(), which is a 3-channel matrixroi
to the detector but you should be passing mask
. When you are making changes to roi
, you are also changing mask
.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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With