I want to limit a SurfFeatureDetector to a set of regions (mask). For a test I define only a single mask:
我想把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
When I pass the "roi" as the mask I get this error:
当我通过“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
What is wrong with this? How can I correctly pass a mask to the SurfFeatureDetector's "detect" method?
这有什么问题?如何正确地将口罩传递给SurfFeatureDetector的“检测”方法?
Regards,
问候,
3 个解决方案
#1
13
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 - 掩码应该是一个8位无符号字符的1通道矩阵,转换为opencv类型CV_8U。在您的例子中,掩码的类型是srci .type(),它是一个3通道矩阵
- you are passing
roi
to the detector but you should be passingmask
. When you are making changes toroi
, you are also changingmask
. - 你将roi传递给检测器,但你应该通过掩码。当您对roi进行更改时,您也在更改蒙版。
the following should work
下面的工作
Mat srcImage; //RGB source image
Mat mask = Mat::zeros(srcImage.size(), CV_8U); // type of mask is CV_8U
Mat roi(mask, cv::Rect(10,10,100,100));
roi = Scalar(255, 255, 255);
SurfFeatureDetector detector();
std::vector<KeyPoint> keypoints;
detector.detect(srcImage, keypoints, mask); // passing `mask` as a parameter
#2
1
I tacked your ROI code onto some existing code I was working on, with the following changes it worked for me
我将您的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);
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
如果不改变类型和使用掩码,而不是使用roi作为您的掩码,我也会得到一个运行时错误。这是有意义的,因为检测方法需要一个蒙版——它应该与原始图像的大小相同,而roi不是(它是一个100x100的矩形)。要直观地看到这一点,请尝试显示蒙版和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
类型也必须匹配;该掩码应该是单一通道,而您的图像类型可能是16型,它映射到CV_8UC3,这是一个三重通道图像。
#3
0
If you are looking to apply the same for irregular mask then:
如果你想在不定期口罩上使用同样的方法,请:
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
}
Then as usual, generate SIFT/SURF/... pointer
然后像往常一样生成SIFT/SURF/…指针
// Create smart pointer for SIFT feature detector.
//为SIFT feature detector创建智能指针。
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);
#1
13
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 - 掩码应该是一个8位无符号字符的1通道矩阵,转换为opencv类型CV_8U。在您的例子中,掩码的类型是srci .type(),它是一个3通道矩阵
- you are passing
roi
to the detector but you should be passingmask
. When you are making changes toroi
, you are also changingmask
. - 你将roi传递给检测器,但你应该通过掩码。当您对roi进行更改时,您也在更改蒙版。
the following should work
下面的工作
Mat srcImage; //RGB source image
Mat mask = Mat::zeros(srcImage.size(), CV_8U); // type of mask is CV_8U
Mat roi(mask, cv::Rect(10,10,100,100));
roi = Scalar(255, 255, 255);
SurfFeatureDetector detector();
std::vector<KeyPoint> keypoints;
detector.detect(srcImage, keypoints, mask); // passing `mask` as a parameter
#2
1
I tacked your ROI code onto some existing code I was working on, with the following changes it worked for me
我将您的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);
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
如果不改变类型和使用掩码,而不是使用roi作为您的掩码,我也会得到一个运行时错误。这是有意义的,因为检测方法需要一个蒙版——它应该与原始图像的大小相同,而roi不是(它是一个100x100的矩形)。要直观地看到这一点,请尝试显示蒙版和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
类型也必须匹配;该掩码应该是单一通道,而您的图像类型可能是16型,它映射到CV_8UC3,这是一个三重通道图像。
#3
0
If you are looking to apply the same for irregular mask then:
如果你想在不定期口罩上使用同样的方法,请:
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
}
Then as usual, generate SIFT/SURF/... pointer
然后像往常一样生成SIFT/SURF/…指针
// Create smart pointer for SIFT feature detector.
//为SIFT feature detector创建智能指针。
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);