jnovacho
jnovacho

Reputation: 2903

Accessing pixel values OpenCV 2.3 - C++

How to access individual pixels in OpenCV 2.3 using C++?
For my U8C3 image I tried this:

Scalar col = I.at<Scalar>(i, j);

and

p = I.ptr<uchar>(i);

First is throwing an exception, the second one is returning some unrelated data. Also all examples I was able to find are for old IIPimage(?) for C version of OpenCV.

All I need is to get color of pixel at given coordinates.

Upvotes: 7

Views: 14183

Answers (1)

Christian Rau
Christian Rau

Reputation: 45968

The type you call cv::Mat::at with needs to match the type of the individual pixels. Since cv::Scalar is basically a cv::Vec<double,4>, this won't work for a U8C3 image (it would work for a F64C4 image, of course).

In your case you need a cv::Vec3b, which is a typedef for cv::Vec<uchar,3>:

Vec3b col = I.at<Vec3b>(i, j);

You can then convert this into a cv::Scalar if you really need to, but the type of the cv::Mat::at instantiation must match the type of your image, since it just casts the image data without any conversions.

Your second code snippet returns a pointer to the ith row of the image. It is no unrelated data, but just a pointer to single uchar values. So in case of a U8C3 image, every consecutive 3 elements in the data returned to p should represent one pixel. Again, to get every pixel as a single element use

Vec3b *p = I.ptr<Vec3b>(i);

which again does nothing more than an appropriate cast of the row pointer before returning it.

EDIT: If you want to do many pixel accesses on the image, you can also use the cv::Mat_ convenience type. This is nothing more than a typed thin wrapper around the image data, so that all accesses to image pixels are appropriately typed:

Mat_<Vec3b> &U = reinterpret_cast<Mat_<Vec3b>&>(I);

You can then freely use U(i, j) and always get a 3-tuple of unsigned chars and therefore pixels, again without any copying, just type casts (and therefore at the same performance as I.at<Vec3b>(i, j)).

Upvotes: 10

Related Questions