如何在 Python 中将 RGB 图像转换为灰度?
- 2024-12-11 08:47:00
- admin 原创
- 183
问题描述:
我正在尝试matplotlib
读取 RGB 图像并将其转换为灰度。
在 matlab 中我使用这个:
img = rgb2gray(imread('image.png'));
在matplotlib 教程中,他们没有介绍它。他们只是在图像中读取
import matplotlib.image as mpimg
img = mpimg.imread('image.png')
然后他们对数组进行切片,但据我所知,这与将 RGB 转换为灰度不同。
lum_img = img[:,:,0]
我很难相信 numpy 或 matplotlib 没有内置函数来将 rgb 转换为灰色。这不是图像处理中的常见操作吗?
我编写了一个非常简单的函数,可以在 5 分钟内处理导入的图像imread
。它的效率非常低,但这就是我希望内置专业实现的原因。
Sebastian 改进了我的功能,但我仍然希望找到内置的功能。
matlab(NTSC/PAL)的实现:
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
解决方案 1:
使用Pillow来做怎么样:
from PIL import Image
img = Image.open('image.png').convert('L')
img.save('greyscale.png')
如果输入图像中存在 alpha(透明度)通道且应保留,则使用模式LA
:
img = Image.open('image.png').convert('LA')
使用 matplotlib 和公式
Y' = 0.2989 R + 0.5870 G + 0.1140 B
你可以这样做:
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()
解决方案 2:
您还可以使用scikit-image,它提供了一些将图像转换为 的函数ndarray
,例如rgb2gray
。
from skimage import color
from skimage import io
img = color.rgb2gray(io.imread('image.png'))
注:此转换中使用的权重已针对当代 CRT 荧光粉进行了校准:Y = 0.2125 R + 0.7154 G + 0.0721 B
或者,您可以通过以下方式读取灰度图像:
from skimage import io
img = io.imread('image.png', as_gray=True)
解决方案 3:
使用在 Ubuntu 16.04 LTS(带有 SSD 的 Xeon E5 2670)上的 Python 3.5 运行的 1000 个 RGBA PNG 图像(224 x 256 像素)对三种建议的方法的速度进行了测试。
平均运行时间
pil :
1.037 秒
scipy:
1.040 秒
sk :
2.120 秒
PIL 和 SciPy 给出了相同的numpy
数组(范围从 0 到 255)。SkImage 给出的数组范围从 0 到 1。此外,颜色转换略有不同,请参见 CUB-200 数据集中的示例。
SkImage:
PIL :
SciPy :
Original:
Diff :
代码
表现
run_times = dict(sk=list(), pil=list(), scipy=list())
for t in range(100):
start_time = time.time()
for i in range(1000):
z = random.choice(filenames_png)
img = skimage.color.rgb2gray(skimage.io.imread(z))
run_times['sk'].append(time.time() - start_time)
start_time = time.time()
for i in range(1000):
z = random.choice(filenames_png)
img = np.array(Image.open(z).convert('L'))
run_times['pil'].append(time.time() - start_time)
start_time = time.time()
for i in range(1000):
z = random.choice(filenames_png)
img = scipy.ndimage.imread(z, mode='L')
run_times['scipy'].append(time.time() - start_time)
for k, v in run_times.items():
print('{:5}: {:0.3f} seconds'.format(k, sum(v) / len(v)))
输出
z = 'Cardinal_0007_3025810472.jpg'
img1 = skimage.color.rgb2gray(skimage.io.imread(z)) * 255
IPython.display.display(PIL.Image.fromarray(img1).convert('RGB'))
img2 = np.array(Image.open(z).convert('L'))
IPython.display.display(PIL.Image.fromarray(img2))
img3 = scipy.ndimage.imread(z, mode='L')
IPython.display.display(PIL.Image.fromarray(img3))
比较
img_diff = np.ndarray(shape=img1.shape, dtype='float32')
img_diff.fill(128)
img_diff += (img1 - img3)
img_diff -= img_diff.min()
img_diff *= (255/img_diff.max())
IPython.display.display(PIL.Image.fromarray(img_diff).convert('RGB'))
导入
import skimage.color
import skimage.io
import random
import time
from PIL import Image
import numpy as np
import scipy.ndimage
import IPython.display
版本
skimage.version
0.13.0
scipy.version
0.19.1
np.version
1.13.1
解决方案 4:
imread
您可以从一开始就使用OpenCV将图像文件读取为灰度:
img = cv2.imread('messi5.jpg', 0)
此外,如果您想将图像读取为 RGB,请进行一些处理,然后转换为灰度,您可以使用cvtcolor
OpenCV:
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
解决方案 5:
目前最快且最有效的方法是使用Pillow,通过 安装pip install Pillow
。
代码如下:
from PIL import Image
img = Image.open('input_file.jpg').convert('L')
img.save('output_file.jpg')
解决方案 6:
使用此公式
Y' = 0.299 R + 0.587 G + 0.114 B
我们可以做到
import imageio
import numpy as np
import matplotlib.pyplot as plt
pic = imageio.imread('(image)')
gray = lambda rgb : np.dot(rgb[... , :3] , [0.299 , 0.587, 0.114])
gray = gray(pic)
plt.imshow(gray, cmap = plt.get_cmap(name = 'gray'))
但是,GIMP将彩色图像转换为灰度图像的软件有三种算法来完成这项任务。
解决方案 7:
本教程有点作弊,因为它从用 RGB 编码的灰度图像开始,所以他们只是切分单个颜色通道并将其视为灰度。您需要执行的基本步骤是从 RGB 颜色空间转换为使用近似亮度/色度模型进行编码的颜色空间,例如 YUV/YIQ 或 HSL/HSV,然后切分类似亮度的通道并将其用作灰度图像。 matplotlib
似乎没有提供转换为 YUV/YIQ 的机制,但它确实允许您转换为 HSV。
尝试使用matplotlib.colors.rgb_to_hsv(img)
然后从数组中切出最后一个值 (V) 作为灰度。它与亮度值不太一样,但这意味着您可以在 中完成所有操作matplotlib
。
背景:
或者,您可以使用 PIL 或内置函数colorsys.rgb_to_yiq()
转换为具有真实亮度值的色彩空间。您也可以全力以赴,推出自己的仅限亮度的转换器,尽管这可能有点过头了。
解决方案 8:
你可以这样做:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
def rgb_to_gray(img):
grayImage = np.zeros(img.shape)
R = np.array(img[:, :, 0])
G = np.array(img[:, :, 1])
B = np.array(img[:, :, 2])
R = (R *.299)
G = (G *.587)
B = (B *.114)
Avg = (R+G+B)
grayImage = img.copy()
for i in range(3):
grayImage[:,:,i] = Avg
return grayImage
image = mpimg.imread("your_image.png")
grayImage = rgb_to_gray(image)
plt.imshow(grayImage)
plt.show()
解决方案 9:
如果你已经在使用 NumPy/SciPy,那么你也可以使用:
scipy.ndimage.imread(file_name, mode='L')
解决方案 10:
使用 OpenCV 很简单:
import cv2
im = cv2.imread("flower.jpg")
# To Grayscale
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
cv2.imwrite("grayscale.jpg", im)
# To Black & White
im = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)[1]
cv2.imwrite("black-white.jpg", im)
解决方案 11:
使用img.Convert(),支持“L”、“RGB”和“CMYK”模式。
import numpy as np
from PIL import Image
img = Image.open("IMG/center_2018_02_03_00_34_32_784.jpg")
img.convert('L')
print np.array(img)
输出:
[[135 123 134 ..., 30 3 14]
[137 130 137 ..., 9 20 13]
[170 177 183 ..., 14 10 250]
...,
[112 99 91 ..., 90 88 80]
[ 95 103 111 ..., 102 85 103]
[112 96 86 ..., 182 148 114]]
解决方案 12:
我通过谷歌找到了这个问题,寻找一种将已加载的图像转换为灰度的方法。
以下是使用 SciPy 实现的方法:
import scipy.misc
import scipy.ndimage
# Load an example image
# Use scipy.ndimage.imread(file_name, mode='L') if you have your own
img = scipy.misc.face()
# Convert the image
R = img[:, :, 0]
G = img[:, :, 1]
B = img[:, :, 2]
img_gray = R * 299. / 1000 + G * 587. / 1000 + B * 114. / 1000
# Show the image
scipy.misc.imshow(img_gray)
解决方案 13:
当像素中所有 3 个颜色通道(RGB)的值相同时,该像素将始终为灰度格式。
将 RGB 图像转换为灰度的一个简单直观的方法是取每个像素中所有颜色通道的平均值,然后将该值分配回该像素。
import numpy as np
from PIL import Image
img=np.array(Image.open('sample.jpg')) #Input - Color image
gray_img=img.copy()
for clr in range(img.shape[2]):
gray_img[:,:,clr]=img.mean(axis=2) #Take mean of all 3 color channels of each pixel and assign it back to that pixel(in copied image)
#plt.imshow(gray_img) #Result - Grayscale image
输入图像:
输出图像:
解决方案 14:
假设我的图像原始形式为 3 通道
my_image = cv2.imread("./5d10e5939c5101174c54bb98.png")
#greyscaling the image
image_sum = my_image.sum(axis=2)
new_image = image_sum/image_sum.max()
new_image
这是我的单通道灰度图像
plt.figure(figsize=[12,8])
plt.imshow(new_image, cmap=plt.cm.gray)
plt.show()
[这没有使用 cv2 的cv2.COLOR_BGR2GRAY
参数或 PIL 的.convert('L')
方法]
解决方案 15:
image=myCamera.getImage().crop(xx,xx,xx,xx).scale(xx,xx).greyscale()
可以greyscale()
直接用来进行转换。
扫码咨询,免费领取项目管理大礼包!