Я пытаюсь использовать 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 в серый. Разве это не обычная операция при обработке изображений?
Я написал очень простую функцию, которая работает с импортированным изображением imread
за 5 минут. Это ужасно неэффективно, но именно поэтому я надеялся на встроенную профессиональную реализацию.
Себастьян улучшил мою функцию, но я все еще надеюсь найти встроенную.
Реализация 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)
. Может быть,rgb[...,:3]
если это на самом деле RGBA.gray = np.mean(rgb, -1)
отлично работает. Спасибо. Есть ли причина не использовать это? Почему бы вместо этого использовать решения в ответах ниже?np.mean(rgb, -1)
.0.2989 * R + 0.5870 * G + 0.1140 * B
Я предполагаю, что это стандартный способ сделать это.Ответы:
Как насчет того, чтобы сделать это с подушкой :
Используя matplotlib и формулу
Вы могли бы сделать:
источник
matplotlib
по какой-то другой причине, он должен быть в состоянии использовать встроеннуюcolorsys.rgb_to_yiq()
функцию для преобразования плюс часть, чтобы получить только канал яркости..convert('LA')
? почему нет.convert('gray')
? Кажется излишне загадочным. В документации PIL ничего не говорится о «LA» для функции convert.cannot write mode LA as JPEG
мне нужно было использовать режим L, а не LAimg = Image.open('image.png').convert('LA')
должно бытьimg = Image.open('image.png').convert('L')
LA
режим имеет яркость (яркость) и альфа. Если вы используетеLA
режим, тоgreyscale.png
будет изображение RGBA с сохраненным альфа-каналомimage.png
. Если вы используетеL
режим, тоgreyscale.png
будет изображение RGB (без альфа).Вы также можете использовать scikit-image , который предоставляет некоторые функции для преобразования изображения
ndarray
, напримерrgb2gray
.Ноты : веса, использованные в этом преобразовании, откалиброваны для современных люминофорных ЭЛТ: Y = 0,2125 R + 0,7154 G + 0,0721 B
Кроме того, вы можете прочитать изображение в оттенках серого с помощью:
источник
cmap
какgray' then only the image is shown as gray in
pyplot.imshow () `? Есть предположения ? Где я не прав?Три из предложенных методов были протестированы на скорость с 1000 PNG-изображениями RGBA (224 x 256 пикселей), работающими с Python 3.5 на Ubuntu 16.04 LTS (Xeon E5 2670 с SSD).
Среднее время выполнения
pil :
1,037 секундыscipy:
1,040 секундыsk :
2.120 секундPIL и SciPy дали одинаковые
numpy
массивы (от 0 до 255). SkImage дает массивы от 0 до 1. Кроме того, цвета немного преобразуются, см. Пример из набора данных CUB-200.SkImage:
PIL :
SciPy :
Original:
Diff :
Код
Производительность
источник
Вы всегда можете прочитать файл изображения в градациях серого с самого начала, используя
imread
OpenCV:Кроме того, если вы хотите прочитать изображение как RGB, выполните некоторую обработку, а затем конвертируйте его в шкалу серого, которую вы можете использовать
cvtcolor
из OpenCV:источник
0
флаг естьcv2.CV_LOAD_IMAGE_GRAYSCALE
.Самый быстрый и актуальный способ - использовать подушку , установленную через
pip install Pillow
.Код тогда:
источник
convert
возвращает преобразованную копию изображенияУчебник обманывает, потому что он начинается с изображения в градациях серого, закодированного в RGB, поэтому они просто обрезают один цветной канал и рассматривают его как оттенки серого. Основные шаги, которые вам нужно сделать, - это преобразовать цветовое пространство RGB в цветовое пространство, которое кодирует с помощью чего-то, приближающего модель яркости / цветности, например, YUV / YIQ или HSL / HSV, затем отрезать канал, подобный яркости, и использовать его как ваше изображение в градациях серого.
matplotlib
не предоставляет механизм для преобразования в YUV / YIQ, но он позволяет преобразовать в HSV.Попробуйте использовать
matplotlib.colors.rgb_to_hsv(img)
затем вырезание последнего значения (V) из массива для градаций серого. Это не совсем то же самое, что значение яркости, но это означает, что вы можете сделать все это вmatplotlib
.Задний план:
Кроме того, вы можете использовать PIL или встроенную
colorsys.rgb_to_yiq()
функцию для преобразования в цветовое пространство с истинным значением яркости. Вы также можете пойти ва-банк и выпустить свой собственный конвертер только для яркости, хотя это, вероятно, излишне.источник
Используя эту формулу
Мы можем сделать
Тем не менее, программа GIMP, преобразующая цвета в изображения в градациях серого, имеет три алгоритма для выполнения этой задачи.
источник
Если вы уже используете NumPy / SciPy, вы также можете использовать :
scipy.ndimage.imread(file_name, mode='L')
источник
scipy.ndimage.imread()
иscipy.misc.imread()
являются официально осуждается в SciPy 1.0.0 и будут удалены в SciPy 1.2.0. В то время как документация SciPy рекомендуетimageio.imread()
в качестве подходящей замены, API этой функции - просто до абсурда. Он не поддерживает преобразование в градациях серого и, таким образом, остается непригодным для многих приложений, включая наши.</sigh>
Вы могли бы сделать:
источник
Используйте img.Convert (), поддерживает «L», «RGB» и «CMYK». Режим
Вывод:
источник
img = img.convert('L')
?Я пришел к этому вопросу через Google, ища способ конвертировать уже загруженное изображение в оттенки серого.
Вот способ сделать это с помощью SciPy:
источник
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 и будут удалены в SciPy 1.2.0. Вы , наверное , просто хотите использовать поддержку преобразования встроенных полутоновую подушки ( в ала unutbu «s ответ ), вместо этого.Вы можете использовать
greyscale()
непосредственно для преобразования.источник