2011-08-01 12 views
5

Quiero escribir datos directamente en la matriz imageData de una imagen Ipl, pero no puedo encontrar mucha información sobre cómo está formateada. Una cosa que me preocupa especialmente es que, a pesar de crear una imagen con tres canales, hay cuatro bytes por cada píxel.escribiendo en IplImage imageData

La función que estoy usando para crear la imagen es:

IplImage *frame = cvCreateImage(cvSize(1, 1), IPL_DEPTH_8U, 3); 

Según todos los indicios, esto debe crear una imagen de tres canales RGB, pero eso no parece ser el caso.

¿Cómo podría, por ejemplo, escribir un único píxel rojo en esa imagen?

Gracias por cualquier ayuda, me deja perplejo.

+0

http://stackoverflow.com/questions/6868723/get -rgb-pixels-from-input-image-and-reconstruct-an-output-image-in-opencv/6875991 # 6875991 – karlphillip

+0

Esa respuesta supone que, de hecho, habrá tres bits por píxel. Confirmé que nChannels de mi imagen es 3, pero todavía hay 4 bits por cada píxel. Por lo que vale, en realidad no están agrupados con los píxeles. parecen estar almacenados al final de cada fila, todo configurado en 0. – wyatt

Respuesta

8

Si está mirando frame->imageSize tenga en cuenta que es frame->height * frame->widthStep, no frame->height * frame->width.

BGR es el formato nativo de OpenCV, no RGB.

Además, si recién está comenzando, debería considerar usar la interfaz C++ (donde Mat reemplaza a IplImage) ya que esa es la dirección futura y es mucho más fácil trabajar con ella.

He aquí algunos ejemplos de código que tiene acceso a los datos de píxeles directamente:

int main (int argc, const char * argv[]) { 

    IplImage *frame = cvCreateImage(cvSize(41, 41), IPL_DEPTH_8U, 3); 

    for(int y=0; y<frame->height; y++) { 
     uchar* ptr = (uchar*) (frame->imageData + y * frame->widthStep); 
     for(int x=0; x<frame->width; x++) { 
      ptr[3*x+2] = 255; //Set red to max (BGR format) 
     } 
    } 

    cvNamedWindow("window", CV_WINDOW_AUTOSIZE); 
    cvShowImage("window", frame); 
    cvWaitKey(0); 
    cvReleaseImage(&frame); 
    cvDestroyWindow("window"); 
    return 0; 
} 
+0

Gracias por eso. Finalmente descubrí esto, me había cegado el desafortunado hecho de que para una y dos filas de píxeles, que utilicé en las pruebas, el redondeo de filas agrega uno y dos píxeles respectivamente. Echaré un vistazo a la alfombra, al navegar parece ser un sistema más opaco, pero supongo que es solo una falta de familiaridad. – wyatt

+0

No soy una autoridad mundial en OpenCV, pero no veo dónde Mat es más opaco que IplImage.Y las campanas y silbatos de C++ como la sobrecarga del operador hacen que sea más fácil trabajar con él. La documentación está en http://opencv.itseez.com/modules/core/doc/basic_structures.html#mat – SSteve

0

unsigned char * imageData = [r1, g1, b1, r2, g2, b2, ..., rN, bn, gn]; // n = alto * ancho de la imagen marco-> imageData = imageData.

Tome su imagen que es una matriz dimensional de altura N y ancho M y colóquela en un vector de hilera de longitud N * M. Haga esto de tipo char sin signo * para imágenes IPL_DEPTH_8U.

+1

El problema es que hay cuatro bytes por cada píxel. Los bytes adicionales parecen estar agrupados al final de cada fila, y todos están configurados en cero, pero no sé por qué. Además, no sé si es significativo, pero las imágenes parecen estar almacenadas en BGR, no en RGB. – wyatt

+1

¿No está seguro de los 4 bytes adicionales? ¿Cómo ve eso? Intente asignar los datos de imagen a una matriz char * de todos modos. Eso es lo que funciona para mí. Sí, algunas bibliotecas de C++ usan BGR y otras usan RGB. Si las capas de color se ven cambiadas cuando visualiza, use cvCvtColor (marco, marco, CV_BRG2RGB) para cambiar las capas R y B. – rossb83

+0

El tamaño de la imagen es consistentemente igual a 4 * cantidad de píxeles. Encontré las posiciones simplemente imprimiendo la matriz imageData para tratar de descubrir cómo se almacenaron los datos. De todos modos, intentaré eso. – wyatt

0

recto a su respuesta, pintando el píxel rojo:

IplImage *frame = cvCreateImage(cvSize(1, 1), IPL_DEPTH_8U, 3); 
int y,x; 
x=0;y=0; //Pixel coordinates. Use this for bigger images than a single pixel. 
int C=2; //0 for blue, 1 for green and 2 for red (BGR is the default format). 
frame->imageData[y*frame->widthStep+3*x+C]=(uchar)255;