I'm trying to extract pixels from an OpenCV Mat
object. When I extract them as Vec4b
, it works nicely, but when I use a Scalar
, which is the standard (afaik), then I get weird numbers. How to use Scalar
and interpret the numbers correctly?
Code for extracting pixel (0, 0), once as Vec4b
and once as Scalar
(which is in fact a Scalar_<double>
):
cv::Vec4b vec = stroke.at<cv::Vec4b>(0, 0);
printf("vec: %i, %i, %i\n", vec[0], vec[1], vec[2]);
cv::Scalar sca = stroke.at<cv::Scalar>(0, 0);
printf("sca: %5.1f, %5.1f, %5.1f\n", sca[0], sca[1], sca[2]);
Output:
vec: 223, 178, 77
sca: -91331626426359316704088074967484318223735050578187982644502863694523413598032925912253837118690612448172200441235555626964757579094862898778997953403371230682094365379726071857064466448183314663075981261984082516073752896735112503485663679145991425485597914964276617645535969580912538709979773360278601728.0, ...
I'm expecting some creamy yellow color, so I think that the Vec3b
is correct.
For the .at<_Tp>()
function to work correctly, you must specify the component data type of the image matrix correctly. If you lack to do so, the binary data of the pixel is misinterpreted and you get unexpected results.
After you extracted the pixel value correctly, you can convert it to any other generic Scalar_<_Tp>
type you want. Usually, you convert it to Scalar
, which is in fact an alias for Scalar_<double>
. The conversion is implicitly done by using the assignment operator (=
).
More details:
Most image matrices come with type code CV_8UC4
(4 channels, red, green, blue, and alpha). E.g. when you load a color image from a JPG file, then the image matrix will be of this format. The 8U
means "8 bits per channel, unsigned integer" and the C4
means "4 channels per matrix element". The corresponding C++ type of the elements is Scalar_<uchar>
. You have to specity this to the generic .at<_Tp>()
function to make it work:
mat.at<Scalar_<uchar>>(y, x)
After the correct extraction of a Scalar_<uchar>
, you can automatically convert it to Scalar
(which is in fact Scalar_<double>
) simply by assignment:
cv::Scalar scalar = mat.at<cv::Scalar_<uchar>>(0, 0);