Convert an Image to Grayscale

How can I convert an RGB image into grayscale in Python?

How about doing it with Pillow:

from PIL import Image
img = Image.open('image.png').convert('L')
img.save('greyscale.png')

If an alpha (transparency) channel is present in the input image and should be preserved, use mode LA:

img = Image.open('image.png').convert('LA')

Using matplotlib and the formula

Y' = 0.2989 R + 0.5870 G + 0.1140 B 

you could do:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

def rgb2gray(rgb):
return np.dot(rgb[...,:3], [0.2989, 0.5870, 0.1140])

img = mpimg.imread('image.png')
gray = rgb2gray(img)
plt.imshow(gray, cmap=plt.get_cmap('gray'), vmin=0, vmax=1)
plt.show()

Convert Color Image to Grayscale in Python without OpenCV

You could write it, based on the conversion formula "Standard" RGB to Grayscale Conversion:

import numpy as np

def rgb2gray(rgb):

r, g, b = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
gray = 0.2989 * r + 0.5870 * g + 0.1140 * b

return gray

Converting image to grayscale

You've encountered a spot where Python's type system isn't protecting you in the way that C++ would.

cv2.IMREAD_GRAYSCALE and cv2.COLOR_BGR2GRAY are values from different enumerations. The former, whose numerical value is 0, applies to cv2.imread(). The latter, whose numerical value is 6, applies to cv2.cvtColor(). C++ would have told you that cv2.IMREAD_GRAYSCALE can't be passed to cv2.cvtColor(). Python quietly accepts the corresponding int value.

Thus, you think you're asking cv2 to convert a color image to gray, but by passing cv2.IMREAD_GRAYSCALE, cv2.cvtColor() sees the value 0, and thinks you're passing cv2.COLOR_BGR2BGRA. Instead of a grayscale image, you get the original image with an alpha channel added.

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

is what you need instead.

The other issue you're seeing, assuming you're using a Jupyter notebook, is that cv2 layers color planes in BGR order instead of RGB. To display them properly, first do

image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

and then display the result.

Converting an image to grayscale using numpy

Here is a working code:

def grayConversion(image):
grayValue = 0.07 * image[:,:,2] + 0.72 * image[:,:,1] + 0.21 * image[:,:,0]
gray_img = grayValue.astype(np.uint8)
return gray_img

orig = cv2.imread(r'C:\Users\Jackson\Desktop\drum.png', 1)
g = grayConversion(orig)

cv2.imshow("Original", orig)
cv2.imshow("GrayScale", g)
cv2.waitKey(0)
cv2.destroyAllWindows()

Convert Color image to grayscale image using Octave

According to Octave documentation on rgb2gray, the conversion is done as follows:

I = 0.298936*R + 0.587043*G + 0.114021*B

So converting a 3D RGB image matrix to a 2D gray-scale can be done by this code:

gray_img = (...
0.298936 * resized_img1(:,:,1) +...
0.587043 * resized_img1(:,:,2) +...
0.114021 * resized_img1(:,:,3));

When you call imread than the pixels are integers of type uint8, in this case you can round the result for better accuracy by adding 0.5:

gray_img = (...
0.298936 * resized_img1(:,:,1) +...
0.587043 * resized_img1(:,:,2) +...
0.114021 * resized_img1(:,:,3) + 0.5);

To get the pixels into a range between 0-1 use im2double

Convert an image to grayscale using a limited amount of shades?

You can use PIL to quantize this:

Sample Image

into this:

Sample Image

like this:

#!/usr/bin/env python3

from PIL import Image

# Load image and make greyscale
im = Image.open('artistic-swirl.jpg').convert('L')

# Quantize down to 5 shades and save
qu = im.quantize(5)
qu.save('result.png')

print(f'Colours: {qu.getcolors()}')

Sample Output

You can see the list of 5 resulting colours (palette indices) and their frequency of occurrence below:

Colours: [(32047, 0), (34515, 1), (59838, 2), (70181, 3), (53419, 4)]

You can equally check the colours with ImageMagick like this:

magick identify -verbose result.png

Sample Output

Image:
Filename: result.png
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: PseudoClass
Geometry: 500x500+0+0
Units: Undefined
Colorspace: sRGB
Type: Grayscale
Base type: Undefined
Endianness: Undefined
Depth: 8-bit
Channel depth:
Red: 8-bit
Green: 8-bit
Blue: 8-bit
Channel statistics:
Pixels: 250000
Red:
min: 106 (0.415686)
max: 166 (0.65098)
mean: 133.412 (0.523186)
median: 139 (0.545098)
standard deviation: 19.4166 (0.0761436)
kurtosis: -0.979496
skewness: 0.129338
entropy: 0.972589
Green:
min: 106 (0.415686)
max: 166 (0.65098)
mean: 133.412 (0.523186)
median: 139 (0.545098)
standard deviation: 19.4166 (0.0761436)
kurtosis: -0.979496
skewness: 0.129338
entropy: 0.972589
Blue:
min: 106 (0.415686)
max: 166 (0.65098)
mean: 133.412 (0.523186)
median: 139 (0.545098)
standard deviation: 19.4166 (0.0761436)
kurtosis: -0.979496
skewness: 0.129338
entropy: 0.972589
Image statistics:
Overall:
min: 106 (0.415686)
max: 166 (0.65098)
mean: 133.412 (0.523186)
median: 139 (0.545098)
standard deviation: 19.4166 (0.0761436)
kurtosis: -0.979485
skewness: 0.129339
entropy: 0.972589
Colors: 5
Histogram:
53419: (106,106,106) #6A6A6A srgb(106,106,106)
70181: (125,125,125) #7D7D7D grey49
59838: (139,139,139) #8B8B8B srgb(139,139,139)
34515: (153,153,153) #999999 grey60
32047: (166,166,166) #A6A6A6 grey65
Colormap entries: 5
Colormap:
0: (166,166,166,1) #A6A6A6FF grey65
1: (153,153,153,1) #999999FF grey60
2: (139,139,139,1) #8B8B8BFF srgba(139,139,139,1)
3: (125,125,125,1) #7D7D7DFF grey49
4: (106,106,106,1) #6A6A6AFF srgba(106,106,106,1)
Rendering intent: Perceptual
Gamma: 0.454545
Chromaticity:
red primary: (0.64,0.33)
green primary: (0.3,0.6)
blue primary: (0.15,0.06)
white point: (0.3127,0.329)
Matte color: grey74
Background color: white
Border color: srgb(223,223,223)
Transparent color: none
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 500x500+0+0
Dispose: Undefined
Iterations: 0
Compression: Zip
Orientation: Undefined
Properties:
date:create: 2022-06-30T13:25:02+00:00
date:modify: 2022-06-30T13:25:02+00:00
png:IHDR.bit-depth-orig: 4
png:IHDR.bit_depth: 4
png:IHDR.color-type-orig: 3
png:IHDR.color_type: 3 (Indexed)
png:IHDR.interlace_method: 0 (Not interlaced)
png:IHDR.width,height: 500, 500
png:PLTE.number_colors: 5
png:sRGB: intent=0 (Perceptual Intent)
signature: ff62d5806f38bc0228513619c9822015bc70ee8466714b0317441e89ff3b815b
Artifacts:
verbose: true
Tainted: False
Filesize: 15193B
Number pixels: 250000
Pixel cache type: Memory
Pixels per second: 90.1415MP
User time: 0.000u
Elapsed time: 0:01.002
Version: ImageMagick 7.1.0-33 Q16-HDRI arm 20040 https://imagemagick.org

Keywords: Python, image processing, quantize, reduce colours.

Impact of converting image to grayscale

In consideration with colours, there can be 2 cases in an image processing problem:

  • Colours are not relevant in object-identification

    In this case, converting a coloured image to a grayscale image will not matter, because eventually the model will be learning from the geometry present in the image. The image-binarization will help in sharpening the image by identifying the light and dark areas.

  • Colours are relevant in object-identification

    As you might know that all the colours can be represented as some combination of three primary RGB colours. Each of these R, G and B values usually vary from 0 to 255 for each pixel. However, in gray-scaling, a certain pixel value will be one-dimensional instead of three-dimensional, and it will just vary from 0 to 255. So, yes, there will be some information loss in terms of actual colours, but, that is in tradeoff with the image-sharpness.

    So, there can be a combined score of R, G, B values at each point (probably their mean (R+G+B)/3), which can give a number between 0 to 255, which can eventually be used as their representative. So that, instead of specific colour information, the pixel just carries the intensity information.

Reference:
https://en.wikipedia.org/wiki/Grayscale

How OpenCV convert image to grayscale?

There are many ITU-R standards that define color conversions.
OpenCV uses BT.709 and your formula is BT.601. For more check here
https://mymusing.co/bt601-yuv-to-rgb-conversion-color/



Related Topics



Leave a reply



Submit