6

I want to write data directly into the imageData array of an IplImage, but I can't find a lot of information on how it's formatted. One thing that's particularly troubling me is that, despite creating an image with three channels, there are four bytes to each pixel.

The function I'm using to create the image is:

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

By all indications, this should create a three channel RGB image, but that doesn't seem to be the case.

How would I, for example, write a single red pixel to that image?

Thanks for any help, it's get me stumped.

wyatt
  • 3,188
  • 10
  • 36
  • 48
  • http://stackoverflow.com/questions/6868723/get-rgb-pixels-from-input-image-and-reconstruct-an-output-image-in-opencv/6875991#6875991 – karlphillip Aug 01 '11 at 13:47
  • That answer presumes that there will in fact be three bits per pixel. I've confirmed that my image's nChannels is 3, but there are still 4 bits for each pixel. For what it's worth, they're not actually grouped with the pixels. they seem to be stored at the end of each row, all set to 0. – wyatt Aug 01 '11 at 13:52

3 Answers3

8

If you are looking at frame->imageSize keep in mind that it is frame->height * frame->widthStep, not frame->height * frame->width.

BGR is the native format of OpenCV, not RGB.

Also, if you're just getting started, you should consider using the C++ interface (where Mat replaces IplImage) since that is the future direction and it's a lot easier to work with.

Here's some sample code that accesses pixel data directly:

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;
}
SSteve
  • 10,550
  • 5
  • 46
  • 72
  • Thanks for that. I did finally discover this, had been blinded by the unfortunate fact that for one and two pixel rows, which I used in testing, the row rounding adds one and two pixels respectively. I'll have a look at mat, in browsing it seemed to be a more opaque system, but I suppose that's just a lack of familiarity. – wyatt Aug 01 '11 at 17:48
  • I'm not a world authority on OpenCV, but I don't see where Mat is any more opaque than IplImage. And the C++ bells and whistles like operator overloading make it easier to work with. The documentation is at http://opencv.itseez.com/modules/core/doc/basic_structures.html#mat – SSteve Aug 01 '11 at 20:53
0

Straight to your answer, painting the pixel red:

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;
LovaBill
  • 5,107
  • 1
  • 24
  • 32
0

unsigned char* imageData = [r1, g1, b1, r2, g2, b2, ..., rN, bn, gn]; // n = height*width of image frame->imageData = imageData.

Take Your image that is a dimensional array of height N and width M and arrange it into a row-wise vector of length N*M. Make this of type unsigned char* for IPL_DEPTH_8U images.

rossb83
  • 1,694
  • 4
  • 21
  • 40
  • 1
    The trouble is that there are four bytes to each pixel. The extra bytes seem to be grouped at the end of each row, and are all set to zero, but I don't know why. Also, I don't know if it's significant, but the images seem to be stored in BGR, not RGB. – wyatt Aug 01 '11 at 13:56
  • 1
    Not sure about the extra 4 bytes? How do you see that? Try assigning the imagedata to a char* array anyway. Thats what works for me. Yes some c++ libraries use BGR and some use RGB. If the color layers look switched when you display then use cvCvtColor(frame, frame, CV_BRG2RGB) to switch the R and B layers. – rossb83 Aug 01 '11 at 14:02
  • Image size is consistently equal to 4 * number of pixels. I found the positions just by printing the imageData array in trying to figure out how the data was stored. Anyway, I'll try that. – wyatt Aug 01 '11 at 14:06