2016-11-21 3 views
2

Я пытаюсь создать программу python, которая принимает полутоновый, 24 * 24-пиксельный файл изображения (я не решил тип, поэтому предложения приветствуются) и преобразует его в список значений пикселей от 0 (белый) до 255 (черный).Как преобразовать изображение в оттенках серого в список значений пикселей?

Я планирую использовать этот массив для создания байтового файла изображения MNIST, который может быть распознан алгоритмами распознавания рукописного ввода Tensor-Flow.

Я нашел Pillow library, чтобы быть наиболее полезными в решении этой задачи, путем перебора каждого пикселя и добавления его значение в массиве от PIL импорта изображения

img = Image.open('eggs.png').convert('1') 
rawData = img.load() 
data = [] 
for y in range(24): 
    for x in range(24): 
     data.append(rawData[x,y]) 

Однако это решение имеет две задачи (1) Значения пикселей не сохраняются как целые числа, а пиксельные объекты, которые не могут быть подвергнуты математическому манипулированию и поэтому бесполезны. (2) Даже Pillow docs заявляют, что:

Доступ к отдельным пикселям довольно медленный. Если вы перебираете все пиксели в изображении, скорее всего, более быстрый способ использования других частей> Pillow API.

+0

Когда я запускаю свой код на своей машине, 'data' представляет собой список регулярных целых чисел. – Kevin

+1

Документация может ссылаться на [getdata] (https://pillow.readthedocs.io/en/3.4.x/reference/Image.html#PIL.Image.Image.getdata), который, как я ожидаю, быстрее, чем доступ на один пиксель. – Kevin

+0

Я не знаю ни одной библиотеки Python, которая не замедляет доступ к отдельным пикселям. – Douglas

ответ

3

Вы можете преобразовать данные изображения в список Python (или список-из-списков), как это:

from PIL import Image 

img = Image.open('eggs.png').convert('L') # convert image to 8-bit grayscale 
WIDTH, HEIGHT = img.size 

data = list(img.getdata()) # convert image data to a list of integers 
# convert that to 2D list (list of lists of integers) 
data = [data[offset:offset+WIDTH] for offset in range(0, WIDTH*HEIGHT, WIDTH)] 

# At this point the image's pixels are all in memory and can be accessed 
# individually using data[row][col]. 

# For example: 
for row in data: 
    print(' '.join('{:3}'.format(value) for value in row)) 

# Here's another more compact representation. 
chars = '@%#*+=-:. ' # Change as desired. 
scale = (len(chars)-1)/255. 
print() 
for row in data: 
    print(' '.join(chars[int(value*scale)] for value in row)) 

Вот увеличенный вариант небольшого 24x24 RGB eggs.png изображений я использовал для тестирования:

enlarged version of eggs.png

Вот выход из первого примера доступа:

screenshot output from test image

А вот выход из второго примера:

@ @ % * @ @ @ @ % - . * @ @ @ @ @ @ @ @ @ @ @ @ 
@ @ . . + @ # .  = @ @ @ @ @ @ @ @ @ @ @ @ 
@ *    . . * @ @ @ @ @ @ @ @ @ @ @ @ 
@ #  . . . .  + % % @ @ @ @ # = @ @ @ @ 
@ %  . : - - - :  % @ % :  # @ @ @ 
@ #  . = = - - - = - . . = =   % @ @ @ 
@ =  - = : - - : - = . .  . : . % @ @ @ 
%  . = - - - - : - = . . - = = = - @ @ @ 
= . - = - : : = + - : . - = - : - = : * % 
- . . - = + = - . . - = : - - - = .  - 
= . : : . - - .  : = - - - - - = . . % 
% : : .  . : - - . : = - - - : = :  # @ 
@ # : . . = = - - = . = + - - = - . . @ @ 
@ @ #  . - = : - : = - . - = = : . .  # @ 
@ @ %  : = - - - : = -  : - . . . - @ 
@ @ *  : = : - - - = . . - . .  . + @ 
@ #  . = - : - = :  : : . - % @ @ @ 
*  . . . : = = - : . . - .  - @ @ @ @ @ 
* . .  . : . . . - = . = @ @ @ @ @ @ 
@ :  - -  . . . .  # @ @ @ @ @ @ @ @ 
@ @ = # @ @ *  . .  . - @ @ @ @ @ @ @ @ @ 
@ @ @ @ @ @ @ . . . # @ @ @ @ @ @ @ @ @ @ @ 
@ @ @ @ @ @ @ -  . % @ @ @ @ @ @ @ @ @ @ @ @ 
@ @ @ @ @ @ @ # . : % @ @ @ @ @ @ @ @ @ @ @ @ @ 

Доступ к пикселю данных теперь должен быть быстрее, чем при использовании объекта img.load() возвращает (и значения будут целыми числами в диапазоне 0..255).

1

Вы можете получить доступ к значению оттенка серого каждого отдельного пикселя, обратившись к значениям r, g или b, которые будут одинаковыми для изображения с оттенками серого.

I.e.

img = Image.open('eggs.png').convert('1') 
rawData = img.load() 
data = [] 
for y in range(24): 
    for x in range(24): 
     data.append(rawData[x,y][0]) 

Это не решает проблему скорости доступа.

Я больше знаком с scikit-image, чем подушка. Мне кажется, что если все, что вам нужно, перечисляет значения оттенков серого, вы можете использовать scikit-изображение, которое хранит изображения в виде массивов numpy и использует img_as_ubyte для представления изображения в виде массива uint, содержащего значения от 0 до 255.

Images are NumPy Arrays является хорошей отправной точкой для просмотра кода.

Смежные вопросы