OpenCV documentation says that "uchar" is "unsigned integer" datatype. How?
Solution 1
If you try to find definition of uchar
(which is pressing F12 if you are using Visual Studio), then you'll end up in OpenCV's core/types_c.h:
#ifndef HAVE_IPL
typedef unsigned char uchar;
typedef unsigned short ushort;
#endif
which standard and reasonable way of defining unsigned integral 8bit type (i.e. "8-bit unsigned integer") since standard ensures that char
always requires exactly 1 byte of memory. This means that:
cout << " " << image.at<uchar>(i,j);
uses the overloaded operator<<
that takes unsigned char
(char
), which prints passed value in form of character, not number.
Explicit cast, however, causes another version of <<
to be used:
cout << " " << (int) image.at<uchar>(i,j);
and therefore it prints numbers. This issue is not related to the fact that you are using OpenCV at all.
Simple example:
char c = 56; // equivalent to c = '8'
unsigned char uc = 56;
int i = 56;
std::cout << c << " " << uc << " " << i;
outputs: 8 8 56
And if the fact that it is a template confuses you, then this behavior is also equivalent to:
template<class T>
T getValueAs(int i) { return static_cast<T>(i); }
typedef unsigned char uchar;
int main() {
int i = 56;
std::cout << getValueAs<uchar>(i) << " " << (int)getValueAs<uchar>(i);
}
Solution 2
Simply, because although uchar
is an integer type, the stream operation <<
prints the character it represents, not a sequence of digits. Passing the type int
you get a different overload of that same stream operation, which does print a sequence of digits.
user2756695
Updated on June 13, 2022Comments
-
user2756695 almost 2 years
I got confused with the openCV documentation mentioned here.
As per the documentation, if i create an image with "uchar", the pixels of that image can store unsigned integer values but if i create an image using the following code:
Mat image; image = imread("someImage.jpg" , 0); // Read an image in "UCHAR" form
or by doing
image.create(10, 10, CV_8UC1); for(int i=0; i<image.rows; i++) { for(int j=o; j<image.cols; j++) { image.at<uchar>(i,j) = (uchar)255; } }
and then if i try to print the values using
cout<<" "<<image.at<uchar>(i,j);
then i get some wierd results at terminal but if i use the following statement then i can get the values inbetween 0-255.
cout<<" "<<(int)image.at<uchar>(i,j); // with TYPECAST
Question: Why do i need to do typecast to get print the values in range 0-255 if the image itself can store "unsigned integer" values.
-
user2756695 about 10 yearssorry but i am unable to understand do they also mean that "uchar" means "unsigned char" or not?
-
user2756695 about 10 yearsso will it be ok if i do
float value = c;
whereuchar c = 255;
? Would i be able to getvalue =255.0
if i try to print it? -
LihO about 10 years+1 Basically, that was my original answer, it's really simple as that.
-
Steve Jessop about 10 years@LihO: yes indeed, I skimmed your answer and was just about to read it through to make sure it didn't contain any inaccuracies before upvoting it, when I thought that a much shorter version might also be useful :-)
-
LihO about 10 years@user2756695: There is implicit type conversion, or, to be more accurate:
uchar
will be "promoted" tofloat
, so yes, it is ok. -
Константин Ван over 3 yearsBut, a byte is not necessarily 8 bits, isn’t it?