OpenCV documentation says that "uchar" is "unsigned integer" datatype. How?

18,547

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.

Share:
18,547
user2756695
Author by

user2756695

Updated on June 13, 2022

Comments

  • user2756695
    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
    user2756695 about 10 years
    sorry but i am unable to understand do they also mean that "uchar" means "unsigned char" or not?
  • user2756695
    user2756695 about 10 years
    so will it be ok if i do float value = c; where uchar c = 255; ? Would i be able to get value =255.0 if i try to print it?
  • LihO
    LihO about 10 years
    +1 Basically, that was my original answer, it's really simple as that.
  • Steve Jessop
    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
    LihO about 10 years
    @user2756695: There is implicit type conversion, or, to be more accurate: uchar will be "promoted" to float, so yes, it is ok.
  • Константин Ван
    Константин Ван over 3 years
    But, a byte is not necessarily 8 bits, isn’t it?