OpenCV: как использовать параметр маски для определения характерной точки (SURF)

Я хочу ограничить 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 «обнаружить»?

С Уважением,

6

Решение

Две вещи о маске.

  • маска должна быть 1-канальной матрицей 8-битных беззнаковых символов, что переводится в тип 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
15

Другие решения

Я прикрепил ваш код 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 — нет (это прямоугольник 100×100). Чтобы увидеть это визуально, попробуйте отобразить маску и

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

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

Тип должен также соответствовать; маска должна быть одноканальной, в то время как ваш тип изображения, скорее всего, имеет тип 16, который соответствует CV_8UC3трехканальное изображение

2

Если вы хотите применить то же самое для маски неправильной формы, то:

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);
0
По вопросам рекламы [email protected]