我正在尝试使用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 导入的图像。但这是非常低效的,所以我希望有专业的内置实现。
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
最佳解决思路
PIL来做是可以的吧:
from PIL import Image
img = Image.open('image.png').convert('LA')
img.save('greyscale.png')
基于matplotlib和公式
Y' = 0.299 R + 0.587 G + 0.114 B
可以这样做:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
def rgb2gray(rgb):
return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
img = mpimg.imread('image.png')
gray = rgb2gray(img)
plt.imshow(gray, cmap = plt.get_cmap('gray'))
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_grey=True)
第三种解决思路
可以始终使用OpenCV中的imread 将图像文件从一开始就读取为灰度图:
img = cv2.imread('messi5.jpg', 0)
此外,如果想读取图像为RGB,做一些处理,然后转换为灰度,可以使用OpenCV中的cvtcolor :
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
第四种思路
最快和最新的方法是使用Pillow,通过pip install Pillow 安装。
代码是:
from PIL import Image
img = Image.open('input_file.jpg').convert('L')
img.save('output_file.jpg')
第五种思路
在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.中的示例
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
参考资料
- How can I convert an RGB image into grayscale in Python?
|