Python 3: я пытаюсь найти все зеленые пиксели на изображении, обойдя все пиксели с помощью np.array, но не могу обойти ошибку индекса - PullRequest
0 голосов
/ 05 сентября 2018

Мой код в настоящее время состоит из загрузки изображения, что успешно, и я не думаю, что имеет какое-либо отношение к проблеме.

Затем я преобразую цветное изображение в массив np.ar с именем rgb

.
    # convert image into array
    rgb = np.array(img)
    red = rgb[:,:,0]
    green = rgb[:,:,1]
    blue = rgb[:,:,2]

Чтобы дважды проверить мое понимание этого массива, в случае, если это может быть корнем проблемы, это массив такой, что rgb [x-координата, y-координата, цветная полоса], который содержит значение в диапазоне 0-255 красного, зеленого или синего цвета.

Затем моя идея состояла в том, чтобы создать вложенный цикл for для прохождения всех пикселей моего изображения (620px, 400px) и отсортировать их по соотношению зеленого, синего и красного в попытке выделить зеленые пиксели и установить все остальные черным или 0.

for i in range(xsize):
for j in range(ysize):
    color = rgb[i,j]  <-- Index error occurs here
    if(color[0] > 128):
        if(color[1] < 128):
            if(color[2] > 128):
                rgb[i,j] = [0,0,0]

Ошибка, которую я получаю при попытке запуска, выглядит следующим образом:

IndexError: индекс 400 выходит за пределы оси 0 с размером 400

Я подумал, что это может иметь какое-то отношение к границам, которые я давал i и j, поэтому я попытался отсортировать только небольшую внутреннюю часть изображения, но все равно получил ту же ошибку. На данный момент я заблудился относительно того, что является даже корнем ошибки, не говоря уже о решении.

1 Ответ

0 голосов
/ 05 сентября 2018

В прямом ответе на ваш вопрос сначала указывается ось y в массивах numpy, а затем ось x, поэтому поменяйте местами свои индексы.


Менее прямо, вы обнаружите, что циклы for очень медленны в Python, и вам лучше использовать вместо этого numpy векторизованные операции. Кроме того, вам часто будет легче найти оттенки зеленого в HSV colourspace .

Давайте начнем с цветового круга HSL:

enter image description here

и предположим, что вы хотите превратить всю зелень в черную. Итак, со страницы Wikipedia оттенок, соответствующий зеленому, равен 120 градусам, что означает, что вы можете сделать это:

#!/usr/local/bin/python3
import numpy as np
from PIL import Image

# Open image and make RGB and HSV versions
RGBim = Image.open("image.png").convert('RGB')
HSVim = RGBim.convert('HSV')

# Make numpy versions
RGBna = np.array(RGBim)
HSVna = np.array(HSVim)

# Extract Hue
H = HSVna[:,:,0]

# Find all green pixels, i.e. where 100 < Hue < 140
lo,hi = 100,140
# Rescale to 0-255, rather than 0-360 because we are using uint8
lo = int((lo * 255) / 360)
hi = int((hi * 255) / 360)
green = np.where((H>lo) & (H<hi))

# Make all green pixels black in original image
RGBna[green] = [0,0,0]

count = green[0].size
print("Pixels matched: {}".format(count))
Image.fromarray(RGBna).save('result.png')

Что дает:

enter image description here


Вот немного улучшенная версия, которая сохраняет альфа / прозрачность и сочетает красные пиксели для дополнительного удовольствия:

#!/usr/local/bin/python3
import numpy as np
from PIL import Image

# Open image and make RGB and HSV versions
im = Image.open("image.png")

# Save Alpha if present, then remove
if 'A' in im.getbands():
    savedAlpha = im.getchannel('A')
    im = im.convert('RGB')

# Make HSV version
HSVim = im.convert('HSV')

# Make numpy versions
RGBna = np.array(im)
HSVna = np.array(HSVim)

# Extract Hue
H = HSVna[:,:,0]

# Find all red pixels, i.e. where 340 < Hue < 20
lo,hi =  340,20
# Rescale to 0-255, rather than 0-360 because we are using uint8
lo = int((lo * 255) / 360)
hi = int((hi * 255) / 360)
red = np.where((H>lo) | (H<hi))

# Make all red pixels black in original image
RGBna[red] = [0,0,0]

count = red[0].size
print("Pixels matched: {}".format(count))

result=Image.fromarray(RGBna)

# Replace Alpha if originally present
if savedAlpha is not None:
    result.putalpha(savedAlpha)

result.save('result.png')

enter image description here

...