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:
into this:
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
Deserializing Json Data to C# Using Json.Net
If Async-Await Doesn't Create Any Additional Threads, Then How Does It Make Applications Responsive
What Are the Pros and Cons to Keeping SQL in Stored Procs Versus Code
Difference Between Shadowing and Overriding in C#
Find Control by Name from Windows Forms Controls
How to Get the Cpu Usage in C#
Is There Any Significant Difference Between Using If/Else and Switch-Case in C#
How to Handle Accessviolationexception
A Generic Error Occurred in Gdi+, Jpeg Image to Memorystream
How to Specify a Custom Location to "Search For Views" in ASP.NET MVC
How to Split CSV Whose Columns May Contain ,
C# Data Connections Best Practice
How to Extract Text That Lies Between Parentheses (Round Brackets)
How Should the Viewmodel Close the Form
Maximum Number of Threads in a .Net App