简体   繁体   中英

OpenCV - How to see which algorithm is used behind a function? (imread)

There are several ways in python to generate a greyscale image from an RGB version. One of those is just to read an image as greyscale using OpenCV.

im = cv2.imread(img, 0)

While 0 equals cv2.IMREAD_GRAYSCALE

There are many different algorithms to handle this operation well explained here.

I'm wondering how OpenCV handles this task and which algorithm stands behind cv2.IMREAD_GRAYSCALE but could neither find any documentation nor reference. Does someone have any idea? A paper reference would be great.

Thanks in advance

ps I'm working with jpg and png.

I think basically @Dan Mašek already answered the question in the comment section.
I will try to summarize the findings for jpg files as an answer and I am glad about any improvements.

CMYK to Grayscale

If you want to convert your jpg file from CMYK we have to look into grfmt_jpeg.cpp . There exist other files like this for different image codes. Depending on the numbers of color channels cinfo is assigned. For CMYK images the cinfo is set to 4 and the function on line 504 icvCvt_CMYK2Gray_8u_C4C1R is called.
This function can be found in utils.cpp :

void icvCvt_CMYK2Gray_8u_C4C1R( const uchar* cmyk, int cmyk_step,
                                uchar* gray, int gray_step, Size size )
{
    int i;
    for( ; size.height--; )
    {
        for( i = 0; i < size.width; i++, cmyk += 4 )
        {
            int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
            c = k - ((255 - c)*k>>8);
            m = k - ((255 - m)*k>>8);
            y = k - ((255 - y)*k>>8);
            int t = descale( y*cB + m*cG + c*cR, SCALE );
            gray[i] = (uchar)t;
        }
        gray += gray_step;
        cmyk += cmyk_step - size.width*4;
    }
}

and uses fixed variables for the conversion:

#define  SCALE  14
#define  cR  (int)(0.299*(1 << SCALE) + 0.5)
#define  cG  (int)(0.587*(1 << SCALE) + 0.5)
#define  cB  ((1 << SCALE) - cR - cG)

RGB/BGR to Grayscale

If your image only contains three color channels it seems that libjpeg is used for the conversion. This can be seen in line 717 . (I am not 100% sure if this is the correct line).

In jdcolor.c it can be seen that there a definitions and standards for converting color channels starting from line 41 .

The most important part for your specific question is:

the conversion equations to be implemented are therefore
R = Y + 1.402 * Cr
G = Y - 0.344136286 * Cb - 0.714136286 * Cr
B = Y + 1.772 * Cb
Y = 0.299 * R + 0.587 * G + 0.114 * B

which relate to standards of the ITU-R and are used in many other sources I found. More detailed information can be found here and here .

The second source relating to a StackOverflow question makes it clear that the conversion does not only depend on the pure RGB values but also on other parameters as gamma value.

The standard OpenCV uses seems to be Rec. 601 .

in OpenCV documentation you can find:

IMREAD_GRAYSCALE = 0,  //!< If set, always convert image to the single channel grayscale image (codec internal conversion).

Also

When using IMREAD_GRAYSCALE, the codec's internal grayscale conversion will be used, if available. Results may differ to the output of cvtColor()

So it depends on codec's internal grayscale conversion.

More Info: from OpenCV documentation

When using IMREAD_GRAYSCALE, the codec's internal grayscale conversion will be used, if available. Results may differ to the output of cvtColor() On Microsoft Windows* OS and MacOSX*, the codecs shipped with an OpenCV image (libjpeg, libpng, libtiff, and libjasper) are used by default. So, OpenCV can always read JPEGs, PNGs, and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers. But beware that currently these native image loaders give images with different pixel values because of the color management embedded into MacOSX. On Linux*, BSD flavors and other Unix-like open-source operating systems, OpenCV looks for codecs supplied with an OS image. Install the relevant packages (do not forget the development files, for example, "libjpeg-dev", in Debian* and Ubuntu*) to get the codec support or turn on the OPENCV_BUILD_3RDPARTY_LIBS flag in CMake.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM