我正在尝试使用 matplotlib
读取 RGB 图像并将其转换为灰度。
在matlab中我使用这个:
img = rgb2gray(imread('image.png'));
在 matplotlib tutorial 他们没有涵盖它。他们只是在图像中阅读
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
gray = np.mean(rgb, -1)
。如果它实际上是 rgba,可能会出现 rgb[...,:3]
。
gray = np.mean(rgb, -1)
工作正常。谢谢。有什么理由不使用它吗?为什么我要使用以下答案中的解决方案?
np.mean(rgb, -1)
完全不同。
0.2989 * R + 0.5870 * G + 0.1140 * B
我假设这是执行此操作的标准方式。
用 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 和 the formula
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()
您还可以使用 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)
cmap
用作 gray' then only the image is shown as gray in
pyplot.imshow()` 吗?有什么想法吗 ?我哪里错了?
在 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 dataset. 中的示例
https://i.stack.imgur.com/ZLd5vm.png
https://i.stack.imgur.com/eQ4KIm.png
https://i.stack.imgur.com/DTjVSm.png
https://i.stack.imgur.com/43cy1m.png
https://i.stack.imgur.com/f5fy9m.png
代码
性能 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。选择(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 导入 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
您始终可以使用 OpenCV 中的 imread
从一开始就将图像文件读取为灰度:
img = cv2.imread('messi5.jpg', 0)
此外,如果您想将图像读取为 RGB,请进行一些处理,然后转换为灰度,您可以使用 OpenCV 中的 cvtcolor
:
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
0
标志是 cv2.CV_LOAD_IMAGE_GRAYSCALE
。
最快和当前的方法是使用通过 pip install Pillow
安装的 Pillow。
那么代码是:
from PIL import Image
img = Image.open('input_file.jpg').convert('L')
img.save('output_file.jpg')
convert
会返回图像的转换副本
该教程是作弊的,因为它是从以 RGB 编码的灰度图像开始的,所以他们只是对单个颜色通道进行切片并将其视为灰度。您需要做的基本步骤是从 RGB 颜色空间转换为使用近似亮度/色度模型(例如 YUV/YIQ 或 HSL/HSV)进行编码的颜色空间,然后切掉类似亮度的通道并将其用作你的灰度图像。 matplotlib
似乎没有提供转换为 YUV/YIQ 的机制,但它确实允许您转换为 HSV。
尝试使用 matplotlib.colors.rgb_to_hsv(img)
,然后从数组中切出最后一个值 (V) 以获得灰度。它与亮度值不太一样,但这意味着您可以在 matplotlib
中完成所有操作。
背景:
http://matplotlib.sourceforge.net/api/colors_api.html
http://en.wikipedia.org/wiki/HSL_and_HSV
或者,您可以使用 PIL 或内置 colorsys.rgb_to_yiq()
转换为具有真实亮度值的色彩空间。您也可以全力以赴并推出自己的 luma-only 转换器,尽管这可能有点过头了。
使用 this formula
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 将颜色转换为灰度图像的软件有三种算法来完成这项任务。
你可以这样做:
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()
如果您已经在使用 NumPy/SciPy,您可以as well use:
scipy.ndimage.imread(file_name, mode='L')
scipy.ndimage.imread()
和 scipy.misc.imread()
在 SciPy 1.0.0 中都是 formally deprecated,将在 SciPy 1.2.0 中永久删除。虽然 SciPy 的文档推荐 imageio.imread()
作为合适的替代品,但这个函数的 API 是赤裸裸的到荒谬的地步。它no支持灰度转换,因此仍然不适合许多应用程序——包括我们的应用程序。 </sigh>
使用 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]]
img = img.convert('L')
吗?
我通过谷歌来到这个问题,寻找一种将已经加载的图像转换为灰度的方法。
这是使用 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)
img_gray = numpy.average(img, weights=[0.299, 0.587, 0.114], axis=2)
numpy.average
有点快,但实际上并没有什么不同。你的解决方案很清楚,并且有关于 R、G、B 的相关信息,所以我会保留它。我的评论更多的是一个额外的选择,而不是替代品。
scipy.ndimage.imread()
和 scipy.misc.imread()
在 SciPy 1.0.0 中都是 formally deprecated,将在 SciPy 1.2.0 中永久删除。您可能只想使用 Pillow 的内置灰度转换支持(ala unutbu 的 answer),而不是。
使用 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)
https://i.stack.imgur.com/J4eEv.png
当所有 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
https://i.stack.imgur.com/0F6KF.jpg
https://i.stack.imgur.com/Xy0hW.jpg
image=myCamera.getImage().crop(xx,xx,xx,xx).scale(xx,xx).greyscale()
您可以直接使用 greyscale()
进行转换。
matplotlib
出于其他原因,他应该能够使用内置的colorsys.rgb_to_yiq()
进行变换加上一个切片来获取亮度通道。.convert('LA')
?为什么不.convert('gray')
?似乎不必要的神秘。 PIL documentation 没有提及转换函数的“LA”。cannot write mode LA as JPEG
,我需要使用 L 模式而不是 LAimg = Image.open('image.png').convert('LA')
必须是img = Image.open('image.png').convert('L')
LA
模式具有亮度(亮度)和 alpha。如果您使用LA
模式,则greyscale.png
将是保留image.png
的 Alpha 通道的 RGBA 图像。如果您使用L
模式,则greyscale.png
将是 RGB 图像(没有 alpha)。