繁体   English   中英

如何在 Python 中将 RGB 图像转换为灰度?

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

我正在尝试使用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

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()

您还可以使用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)

在 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 : PIL

SciPy : SciPy

Original: 原来的

Diff : 在此处输入图片说明

代码

  1. 表现

    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)

    \n\n
    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)
    \n\n

    对于 k, v in run_times.items(): print('{:5}: {:0.3f} seconds'.format(k, sum(v) / len(v)))

  2. 输出
    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))
  3. 比较
    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'))
  4. 进口
    import skimage.color import skimage.io import random import time from PIL import Image import numpy as np import scipy.ndimage import IPython.display
  5. 版本
    skimage. version 0.13.0 scipy. version 0.19.1 np. version 1.13.1

您始终可以使用 OpenCV 中的imread从一开始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')

该教程是作弊的,因为它从以 RGB 编码的灰度图像开始,因此他们只是将单个颜色通道切片并将其视为灰度。 您需要做的基本步骤是从 RGB 颜色空间转换为使用近似亮度/色度模型(例如 YUV/YIQ 或 HSL/HSV)进行编码的颜色空间,然后切掉类似亮度的通道并将其用作你的灰度图像。 matplotlib似乎没有提供转换为 YUV/YIQ 的机制,但它确实可以让您转换为 HSV。

尝试使用matplotlib.colors.rgb_to_hsv(img)然后从数组中切出最后一个值 (V) 以获得灰度。 它与亮度值并不完全相同,但这意味着您可以在matplotlib完成所有操作。

背景:

或者,您可以使用 PIL 或内置colorsys.rgb_to_yiq()转换为具有真实亮度值的色彩空间。 您也可以全力以赴并推出自己的仅亮度转换器,尽管这可能有点矫枉过正。

使用这个公式

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将颜色转换为灰度图像软件具有三种算法来完成任务。

如果您已经在使用 NumPy/SciPy,您也可以使用

scipy.ndimage.imread(file_name, mode='L')

你可以这样做:

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()

使用 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]]

我通过谷歌来到这个问题,寻找一种将已经加载的图像转换为灰度的方法。

这是使用 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)

使用 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)

在此处输入图片说明

当所有 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

输入图像: 输入图像

输出图像: 输出图像

image=myCamera.getImage().crop(xx,xx,xx,xx).scale(xx,xx).greyscale()

您可以直接使用greyscale()进行转换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM