To begin, just note that I'm avare of Accessing certain pixel RGB value in openCV and Pixel access in OpenCV 2.2. Neither of those address my problem.
What I would like to do, is to reliably read / write the pixel RGB values in OpenCV's IplImage
. So far, I have seen this:
uint8_t cr = CV_IMAGE_ELEM(color_img, uint8_t, y, x * color_img->nChannels + 2);
uint8_t cg = CV_IMAGE_ELEM(color_img, uint8_t, y, x * color_img->nChannels + 1);
uint8_t cb = CV_IMAGE_ELEM(color_img, uint8_t, y, x * color_img->nChannels + 0);
Now that seems plain wrong to me.
const uint8_t *p_color_pixel = cvPtr2D(color_img, y, x, NULL);
uint8_t cr = p_color_pixel[2], cg = p_color_pixel[1], cb = p_color_pixel[0];
This is still a bit painful, but probably the fastest way. One could also use cvGet2D()
, although that also seems to involve the awkward multiplication of x
by the number of channels.
Anyway, my issue is that those are all quite "unsafe", in the sense that the image may be RGB
or BGR
or ARGB
. Also, the pixels may not be uint8_t
. So the result feels still pretty random, depending on what kind of image and format I'm reading. I'm actually processing images that store some 24-bit integer values, packed to RGB
, so the correct order is crucial (a wrong order will essentially yield noise). The only approach I've seen that seems "semi-safe" so far is quite morbid, both code and performance-wise:
CvSize t_image_size = cvGetSize(image);
IplImage *ir = cvCreateImage(t_image_size, 8, 1);
IplImage *ig = cvCreateImage(t_image_size, 8, 1);
IplImage *ib = cvCreateImage(t_image_size, 8, 1);
cvSplit(image, left_b, left_g, left_r, 0);
double cr = cvGetReal2D(ir, x, y),
cg = cvGetReal2D(ig, x, y), cvGetReal2D(ib, x, y);
cvReleaseImage(&ir);
cvReleaseImage(&ig);
cvReleaseImage(&ib);
I mean ... come on, we are in the 21st century, why is it so damn hard to get correct RGB
?!
Note that I'd prefer using the "C" interface, as the C++ one is quite unstable at the moment. But if there was a reliable way in C++, I'd take it.