2012-09-09 36 views
10

Al trabajar con objetos Mat de 1 canal (por ejemplo, CV_8UC1) en OpenCV, esto crea una Mat de todos los: cv::Mat img = cv::Mat::ones(x,y,CV_8UC1).OpenCV cv :: Mat 'unos' para matriz multicanal?

Sin embargo, cuando uso imágenes de 3 canales (por ejemplo, CV_8UC3), las cosas se vuelven un poco más complicadas. Haciendo cv::Mat img = cv::Mat::ones(x,y,CV_8UC3) pone unos en el canal 0, pero los canales 1 y 2 contienen ceros. Entonces, ¿cómo uso cv::Mat::ones() para imágenes multicanal?

Aquí hay algo de código que podría ayudar a ver lo que quiero decir:

void testOnes() { 
int x=2; int y=2; //arbitrary 

// 1 channel 
cv::Mat img_C1 = cv::Mat::ones(x,y,CV_8UC1); 
uchar px1 = img_C1.at<uchar>(0,0); //not sure of correct data type for px in 1-channel img 
printf("px of 1-channel img: %d \n", (int)px1); //prints 1 

// 3 channels 
cv::Mat img_C3 = cv::Mat::ones(x,y,CV_8UC3); //note 8UC3 instead of 8UC1 
cv::Vec3b px3 = img_C3.at<cv::Vec3b>(0,0); 
printf("px of 3-channel img: %d %d %d \n", (int)px3[0], (int)px3[1], (int)px3[2]); //prints 1 0 0 
} 

Por lo tanto, lo que habría esperado ver esta copia impresa: px of 3-channel img: 1 1 1, pero en lugar de eso ver esto: px of 3-channel img: 1 0 0.

P.S. Hice muchas búsquedas antes de publicar esto. No pude resolver esto buscando SO para "[opencv] Mat :: ones" o "[opencv] + mat + ones".

+1

Nota al margen: No estoy seguro de si debería usar ' uchar' en lugar de 'cv :: Vec3b' para un píxel de imagen de 1 canal. OpenCV ofrece muchas clases vectoriales de 2, 3 y 4 elementos, pero no hay analogía para un singleton. (Busque 'Vec3b' en esta página: http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#vec) – solvingPuzzles

Respuesta

6

No uso OpenCV, pero creo que sé lo que está sucediendo aquí. Usted define un tipo de datos, pero está solicitando el valor '1' para eso. La clase Mat parece no prestar atención al hecho de que tiene un tipo de datos multicanal, por lo que simplemente arroja '1' como un carácter no firmado de 3 bytes.

Así que en lugar de utilizar la función ones, sólo tiene que utilizar el constructor escalar:

cv::Mat img_C3(x, y, CV_8UC3, CV_RGB(1,1,1)); 
+0

Acabo de probar su solución. 'cv :: Mat img_C3 = cv :: Mat :: ones (x, y, CV_8UC3) * CV_RGB (1,1,1);' no compila, porque no hay un operador sobrecargado '*' para el 'cv :: Mat' tipo. 'cv :: Mat img_C3 (x, y, CV_8UC3, CV_RGB (1,1,1));' compila, pero define los canales de un píxel como '1 0 0', al igual que en el ejemplo' ones' de mi pregunta . Estoy investigando tu respuesta más profundamente ahora. – solvingPuzzles

+1

Oh, espera, 'cv :: Mat img_C3 (x, y, CV_8UC3, CV_RGB (1,1,1));' ¡FUNCIONA CORRECTAMENTE! – solvingPuzzles

+0

Esperaría que la primera solución funcione, según dónde la encontré (http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#cv-mat-ones), pero quizás no funcione con el tipo de retorno para 'CV_RGB'. Originalmente escribí 0x10101 antes de tropezar con esa macro. Pruébalo y, si funciona, ajustaré tus ediciones propuestas. – paddy

1

También puede inicializar como esto:

Mat img; 

/// Lots of stuff here ... 

// Need to initialize again for some reason: 
img = Mat::Mat(Size(width, height), CV_8UC3, CV_RGB(255,255,255)); 
Cuestiones relacionadas