Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 264
user2756695 Avatar asked Mar 01 '14 13:03

user2756695


2 Answers

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);
}
like image 168
LihO Avatar answered Sep 28 '22 01:09

LihO


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.

like image 31
Steve Jessop Avatar answered Sep 28 '22 01:09

Steve Jessop