2013-05-03 23 views
5

Desidero limitare un parametro SurfFeature a un insieme di regioni (maschera). Per un test definisco una sola maschera:OpenCV: utilizzo del parametro maschera per il rilevamento del punto funzione (SURF)

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 

quando passo il "roi", come la maschera ottengo questo errore:

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 

Cosa c'è di sbagliato in questo? Come posso passare correttamente una maschera al metodo "detect" di SurfFeatureDetector?

saluti,

risposta

13

due cose circa la maschera.

  • la maschera dovrebbe essere una matrice 1 canale a 8 bit senza segno caratteri, che si traduce in opencv tipo CV_8U. Nel tuo caso la maschera è di tipo srcImage.type(), che è una matrice a 3 canali
  • stai passando roi al rilevatore ma dovresti passare mask. Quando si apportano modifiche a roi, si modifica anche mask.

il seguente dovrebbe funzionare

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 
+1

Grazie, questo funziona. – Hyndrix

+0

Penso che dovrebbe essere 'Scalare (255);' come la maschera è monodimensionale. –

+0

'roi' ha 3 canali, come' srcImage' ('roi' è una sottomatrice di' srcImage') – Alexey

1

ho virato il proprio codice ROI su qualche codice esistente su cui stavo lavorando, con le seguenti modifiche ha funzionato per 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); 

Senza le modifiche il tipo e l'uso di mask invece di roi come maschera, ricevo anche un errore di runtime. Questo ha senso, poiché il metodo di rilevamento richiede una maschera - dovrebbe avere le stesse dimensioni dell'immagine originale e il roi non lo è (è un rettangolo 100x100). Per vedere questo visivamente, provare a visualizzare la maschera e il ROI

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

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

Il tipo deve corrispondere anche; la maschera dovrebbe essere singolo canale, mentre il tipo di immagine è probabilmente di tipo 16, che associa ad CV_8UC3, un'immagine a tre canali

0

Se stai cercando di applicare lo stesso per la maschera irregolare, allora:

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 
    } 

Quindi, come al solito, genera SIFT/SURF/... puntatore

// Crea puntatore intelligente per il rilevatore di funzionalità 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);