Cv2 Rgb To Gray

  1. Cv2 Rgb To Gray Code
  2. Cv2 Rgb To Gray Converter

Occasionally the need arises to convert a color image to grayscale. This need came up when loading images taken on the surface of Mars as part of End-to-End Machine Learning Course 313, Advanced Neural Network Methods. We were working with a mixture of color and grayscale images and needed to transform them into a uniform format - all grayscale. We'll be working in Python using the Pillow, Numpy, and Matplotlib packages.

By the way, all the interesting information in this post all comes from the Wikipedia entry on Grayscale. (If you find it helpful, maybe send them a dollar.)

Read in a color image


The code we're working from loads jpeg images for an autoencoder to use as inputs. This is accomplished with using Pillow and Numpy:

Parameter: cv2.COLORBGR2RGB – BGR image is converted to RGB.; cv2.COLORRGB2BGR – RGB image is converted to BGR. Converting a BGR image to RGB and vice versa can have several reasons, one of them being that several image processing libraries have different pixel orderings. The following are 30 code examples for showing how to use cv2.COLORRGB2GRAY.These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. Working with images: Conversion from rgb to grayscale, using OpenCV in Java; if you want to save the image just uncomment the line in the codeblog melarde.


This reads the image in and converts it into a Numpy array. For a detailed description of what this does and why, check out the prequel post to this one: How to Convert a Picture into Numbers. For grayscale images, the result is a two-dimensional array with the number of rows and columns equal to the number of pixel rows and columns in the image. Low numeric values indicate darker shades and higher values lighter shades. The range of pixel values is often 0 to 255. We divide by 255 to get a range of 0 to 1.

Color images are represented as three-dimensional Numpy arrays - a collection of three two-dimensional arrays, one each for red, green, and blue channels. Each one, like grayscale arrays, has one value per pixel and their ranges are identical.

Easy peasy: Average the channels


An intuitive way to convert a color image 3D array to a grayscale 2D array is, for each pixel, take the average of the red, green, and blue pixel values to get the grayscale value. This combines the lightness or luminance contributed by each color band into a reasonable gray approximation.

img = numpy.mean(color_img, axis=2)

The axis=2 argument tells numpy.mean() to average values across all three color channels. (axis=0 would average across pixel rows and axis=1 would average across pixel columns.)

Well, actually...channel-dependent luminance perception


To our eyes green looks about ten times brighter than blue. Through many repetitions of carefully designed experiments, psychologists have figured out how different we perceive the luminance or red, green, and blue to be. They have provided us a different set of weights for our channel averaging to get total luminance.

The results are noticeably different and, to my eye, more accurate.

Well, actually...gamma compression


We are able to see small differences when luminance is low, but at high luminance levels, we are much less sensitive to them. In order to avoid wasting effort representing imperceptible differences at high luminance, the color scale is warped, so that it concentrates more values in the lower end of the range, and spreads them out more widely in the higher end. This is called gamma compression.

To undo the effects of gamma compression before calculating the grayscale luminance, it's necessary to apply the inverse operation, gamma expansion:

The benefit of gamma compression is that it gets rid of banding in smoothly varying dark colors, like a photo of the sky at twilight. The downside is that if we want to do anything like adding, subtracting, or averaging bands, we first have to undo the compression and get the luminance back into a linear representation.

There is lightening throughout the image after accounting for gamma compression. It brings the luminance up to be a closer match to that of the original image. Finally, we have a high quality grayscale representation.

Well, actually...a linear approximation


The gamma decompression and re-compression rack up quite a large computation cost, compared to the weighted averages we were working with before. Sometimes speed is more desirable than accurate-as-possible luminance calculations. For situations like these, there is a linear approximation:

This lets you get a result that's a little closer to the gamma-compression-corrected version, but without the extra computation time.

As you can see, the results are not bad at all. They tend to be a little darker, especially through the red mid-range values, but arguably just as good in most practical respects.

This method of calculating luminance is codified in the standard ITU-R BT.601 Studio encoding parameters of digital television for standard 4:3 and wide screen 16:9 aspect ratios. which incidentally was awarded an Emmy in 1983.

Which one should I use?


If close is good enough or if you really care about speed, use the linear approximation of gamma correction. This is the approach used by MATLAB, Pillow, and OpenCV. It is included in my Lodgepole image and video processing toolbox:


But if you simply must have the best results, splurge on the whole gamma decompression - perceptual luminance corrected - gamma re-compression pipeline:


If after reading this far you insist on straight up averaging the three channels together, I will judge you.

Now go make beautiful grayscale images!


Original. Reposted with permission.

Related:

I’m trying to use matplotlib to read in an RGB image and convert it to grayscale.

In matlab I use this:

In the matplotlib tutorial they don’t cover it. They just read in the image

and then they slice the array, but that’s not the same thing as converting RGB to grayscale from what I understand.

EDIT:

I find it hard to believe that numpy or matplotlib doesn’t have a built-in function to convert from rgb to gray. Isn’t this a common operation in image processing?

I wrote a very simple function that works with the image imported using imread in 5 minutes. It’s horribly inefficient, but that’s why I was hoping for a professional implementation built-in.

Sebastian has improved my function, but I’m still hoping to find the built-in one.

Cv2 Rgb To Gray Code

matlab’s (NTSC/PAL) implementation:

Answers:

How about doing it with PIL:

Using matplotlib and the formula

you could do:

Answers:

You can also use scikit-image, which provides some functions to convert an image in ndarray, like rgb2gray.

Notes: The weights used in this conversion are calibrated for contemporary CRT phosphors: Y = 0.2125 R + 0.7154 G + 0.0721 B

Alternatively, you can read image in grayscale by:

Answers:

You can always read the image file as grayscale right from the beginning using imread from OpenCV:

Furthermore, in case you want to read the image as RGB, do some processing and then convert to Gray Scale you could use cvtcolor from OpenCV:

Answers:

The fastest and current way is to use Pillow, installed via pip install Pillow.

The code is then:

Answers:

The tutorial is cheating because it is starting with a greyscale image encoded in RGB, so they are just slicing a single color channel and treating it as greyscale. The basic steps you need to do are to transform from the RGB colorspace to a colorspace that encodes with something approximating the luma/chroma model, such as YUV/YIQ or HSL/HSV, then slice off the luma-like channel and use that as your greyscale image. matplotlib does not appear to provide a mechanism to convert to YUV/YIQ, but it does let you convert to HSV.

Try using matplotlib.colors.rgb_to_hsv(img) then slicing the last value (V) from the array for your grayscale. It’s not quite the same as a luma value, but it means you can do it all in matplotlib.

Background:

Alternatively, you could use PIL or the builtin colorsys.rgb_to_yiq() to convert to a colorspace with a true luma value. You could also go all in and roll your own luma-only converter, though that’s probably overkill.

Cv2 Rgb To Gray Converter

Answers:

If you’re using NumPy/SciPy already you may as well use:

scipy.ndimage.imread(file_name, mode='L')

Hth,
dtk

Answers:

I came to this question via Google, searching for a way to convert an already loaded image to grayscale.

Here is a way to do it with SciPy:

Answers:

Three of the suggested methods were tested for speed with 1000 RGBA PNG images (224 x 256 pixels) running with Python 3.5 on Ubuntu 16.04 LTS (Xeon E5 2670 with SSD).

Rgb

Average run times

pil : 1.037 seconds

scipy: 1.040 seconds

sk : 2.120 seconds

PIL and SciPy gave identical numpy arrays (ranging from 0 to 255). SkImage gives arrays from 0 to 1. In addition the colors are converted slightly different, see the example from the CUB-200 dataset.

SkImage:

PIL :

SciPy :

Original:

Diff :

Code

  1. Performance

    for k, v in run_times.items():
    print('{:5}: {:0.3f} seconds'.format(k, sum(v) / len(v)))

  2. Output
  3. Comparison
  4. Imports
  5. Versions
Answers:

You can use greyscale() directly for the transformation.

Tags: image, python