Подтвердить что ты не робот

Получение списка значений пикселей из PIL

Ребята, я ищу немного помощи. Я программист новичков, и одна из проблем, с которыми я столкнулась в данный момент, пытается преобразовать черно-белое изображение .jpg в список, который затем смогу модулировать в звуковой сигнал. Это часть проекта lager для создания программы SSTV на питоне.

Я импортировал модуль PIL и пытаюсь вызвать встроенную функцию: list(im.getdata()). Когда я это называю, происходит сбой python. Есть ли способ разбить изображение (всегда 320x240) на 240 строк, чтобы упростить вычисления? Или я просто вызываю неправильную функцию.

Если у кого есть предложения, пожалуйста, уберите их. Если у кого-то есть опыт создания модулированных звуковых тонов с использованием питона, я с радостью принимаю любые "жемчужины мудрости", которые они готовы передать. Спасибо заранее

4b9b3361

Ответ 1

Python не должен падать при вызове getdata(). Образ может быть поврежден или что-то не так с вашей установкой PIL. Попробуйте это с другим изображением или опубликуйте изображение, которое вы используете.

Это должно сломать изображение так, как вы хотите:

from PIL import Image
im = Image.open('um_000000.png')

pixels = list(im.getdata())
width, height = im.size
pixels = [pixels[i * width:(i + 1) * width] for i in xrange(height)]

Ответ 2

Если у вас установлен numpy, вы можете попробовать:

data = numpy.asarray(im)

(я говорю "попробуйте" здесь, потому что неясно, почему getdata() не работает для вас, и я не знаю, использует ли asarray getdata, но стоит тест.)

Ответ 3

Я предполагаю, что вы получаете ошибку, например.. TypeError: 'PixelAccess' object is not iterable...?

Смотрите документацию Image.load для доступа к пикселям.

В принципе, чтобы получить список пикселей в изображении, используя PIL:

from PIL import Image
i = Image.open("myfile.png")

pixels = i.load() # this is not a list, nor is it list()'able
width, height = i.size

all_pixels = []
for x in range(width):
    for y in range(height):
        cpixel = pixels[x, y]
        all_pixels.append(cpixel)

Это добавляет каждый пиксель к all_pixels - если файл является RGB-изображением (даже если он содержит только черно-белое изображение), это будет кортеж, например:

(255, 255, 255)

Чтобы преобразовать изображение в монохромное, вы просто усредняете три значения - так что последние три строки кода станут..

cpixel = pixels[x, y]
bw_value = int(round(sum(cpixel) / float(len(cpixel))))
# the above could probably be bw_value = sum(cpixel)/len(cpixel)
all_pixels.append(bw_value)

Или получить яркость (средневзвешенное значение):

cpixel = pixels[x, y]
luma = (0.3 * cpixel[0]) + (0.59 * cpixel[1]) + (0.11 * cpixel[2])
all_pixels.append(luma)

Или чистый 1-бит, выглядящий черно-белым:

cpixel = pixels[x, y]
if round(sum(cpixel)) / float(len(cpixel)) > 127:
    all_pixels.append(255)
else:
    all_pixels.append(0)

В PIL, вероятно, есть методы для более быстрого преобразования RGB -> BW, но это работает и не особенно медленнее.

Если вы хотите выполнять вычисления только для каждой строки, вы можете пропустить добавление всех пикселей в промежуточный список. Например, чтобы вычислить среднее значение каждой строки:

from PIL import Image
i = Image.open("myfile.png")

pixels = i.load() # this is not a list
width, height = i.size
row_averages = []
for y in range(height):
    cur_row_ttl = 0
    for x in range(width):
        cur_pixel = pixels[x, y]
        cur_pixel_mono = sum(cur_pixel) / len(cur_pixel)
        cur_row_ttl += cur_pixel_mono

    cur_row_avg = cur_row_ttl / width
    row_averages.append(cur_row_avg)

print "Brighest row:",
print max(row_averages)

Ответ 4

Не PIL, но scipy.misc.imread может быть интересным:

import scipy.misc
im = scipy.misc.imread('um_000000.png', flatten=False, mode='RGB')
print(im.shape)

дает

(480, 640, 3)

так это (высота, ширина, каналы). Таким образом, вы можете перебирать его через

for y in range(im.shape[0]):
    for x in range(im.shape[1]):
        color = tuple(im[y][x])
        r, g, b = color

Ответ 5

Или если вы хотите считать белые или черные пиксели

Это также решение:

from PIL import Image
import operator

img = Image.open("your_file.png").convert('1')
black, white = img.getcolors()

print black[0]
print white[0]

Ответ 6

Как я уже отмечал выше, проблема заключается в преобразовании из внутреннего формата списка PIL в стандартный тип списка python. Я обнаружил, что Image.tostring() работает намного быстрее, и в зависимости от ваших потребностей этого может быть достаточно. В моем случае мне нужно было вычислить дайджест CRC32 данных изображения, и он подходит отлично.

Если вам нужно выполнить более сложные вычисления, то tom10-ответ, включающий numpy, может быть тем, что вам нужно.

Ответ 7

Похоже, что PILlow, возможно, изменил tostring() на tobytes(). При попытке извлечь RGBA-пиксели, чтобы получить их в текстуру OpenGL, для меня работало следующее (в рамках вызова glTexImage2D, который я опускаю для краткости).

from PIL import Image
img = Image.open("mandrill.png").rotate(180).transpose(Image.FLIP_LEFT_RIGHT)

# use img.convert("RGBA").tobytes() as texels

Ответ 8

data = numpy.asarray(im)

Примечание. В PIL img является RGBA. В cv2 img является BGRA.

Мое надежное решение:

def cv_from_pil_img(pil_img):
    assert pil_img.mode=="RGBA"
    return cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGBA2BGRA)

Ответ 9

pixVals = list(pilImg.getdata())

выводит список всех значений RGB с картинки:

[(248, 246, 247), (246, 248, 247), (244, 248, 247), (244, 248, 247), (246, 248, 247), (248, 246, 247), (250, 246, 247), (251, 245, 247), (253, 244, 247), (254, 243, 247)]