Редактировать значения пикселей в изображении в виде массива - PullRequest
0 голосов
/ 13 сентября 2018

Я читаю изображение так:

img = np.array(Image.open(test_dir + image_name))

Что я хочу сделать, так это найти область в массиве с высоким значением (250 или более) и уменьшить его на 10:

rows = img.shape[0]
cols = img.shape[1]
pixel = []
for x in range(0,rows):
    for y in range(0, cols):
        if x >= 122 and x <= 160 and y >= 34  and y <= 71:
            if img[x,y]>= 250:
                img[x,y] = img[x,y] -10
                pixel.append(img[x,y])

Таким образом, область, на которую я смотрю в соответствии с неизмененным изображением, должна быть рамкой от (122, 34) до (160,71), и она должна иметь несколько пикселей свыше 250, но каким-то образом, когда я запускаю этот код, я заканчиваю ничего не попало в список пикселей

Ответы [ 4 ]

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

Самый простой способ - одна строка:

im[im>250]-=10

Демонстрация

Начните с этого изображения градиента 8x8:

enter image description here

Здесь увеличено:

enter image description here

Затем используйте IPython , например:

# Load image as L (greyscale)
im = np.array(Image.open('image.png').convert('L'))

# View contents
im
Out[16]: 
array([[255, 255, 255, 255, 255, 255, 255, 255],
       [219, 219, 219, 219, 219, 219, 219, 219],
       [182, 182, 182, 182, 182, 182, 182, 182],
       [146, 146, 146, 146, 146, 146, 146, 146],
       [109, 109, 109, 109, 109, 109, 109, 109],
       [ 73,  73,  73,  73,  73,  73,  73,  73],
       [ 36,  36,  36,  36,  36,  36,  36,  36],
       [  0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8)

# Do required processing
im[im>250]-=10

# Review contents
In [18]: im
Out[18]: 
array([[245, 245, 245, 245, 245, 245, 245, 245],
       [219, 219, 219, 219, 219, 219, 219, 219],
       [182, 182, 182, 182, 182, 182, 182, 182],
       [146, 146, 146, 146, 146, 146, 146, 146],
       [109, 109, 109, 109, 109, 109, 109, 109],
       [ 73,  73,  73,  73,  73,  73,  73,  73],
       [ 36,  36,  36,  36,  36,  36,  36,  36],
       [  0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8)

Давайте попробуем уменьшить еще больше пикселей, просто для удовольствия:

In [19]: im[im>100]-=10

In [20]: im
Out[20]: 
array([[235, 235, 235, 235, 235, 235, 235, 235],
       [209, 209, 209, 209, 209, 209, 209, 209],
       [172, 172, 172, 172, 172, 172, 172, 172],
       [136, 136, 136, 136, 136, 136, 136, 136],
       [ 99,  99,  99,  99,  99,  99,  99,  99],
       [ 73,  73,  73,  73,  73,  73,  73,  73],
       [ 36,  36,  36,  36,  36,  36,  36,  36],
       [  0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8)
0 голосов
/ 13 сентября 2018

Если ваше изображение в оттенках серого, это будет сделано.

inds = np.where(img>=250)
inds = inds[(inds.T[0]>=122)&(inds.T[0]<=160)&(inds.T[1]>=34)&(inds.T[1]<=71)]
img[inds]-=10
0 голосов
/ 13 сентября 2018

Является ли img 3-мерным массивом? Если это так, то ваш тест img[x, y] >= 250 проверяет, является ли массив из 3 элементов больше 250. Это приведет к ошибке и завершит выполнение вашего сценария в этой точке. Вы не сказали, происходит ли это.

Если это трехмерный массив, и вы хотите проверить, имеют ли все каналы значение больше 250 в позиции x, y, то вам нужно проверить np.all(img[x, y] >= 250) вместо img[x, y] >= 250.

Как правило, вы хотите избежать циклов и использовать векторизованные операции для ускорения процесса.

min_row = 122
max_row = 161
min_col = 34
max_col = 72
threshold = 250

row_slice = slice(min_row, max_row)
col_slice = slice(min_col, max_col)
roi = img[row_slice, col_slice] >= threshold
img[row_slice, col_slice][roi] -= 10

или более кратко, но менее читабельно,

roi = img[min_row:max_row, min_col:max_col] >= threshold
img[min_row:max_row, min_col:max_col][roi] -= 10
0 голосов
/ 13 сентября 2018

Для более компактного решения вы можете попробовать

roi = img[122:161, 34:72]
pixel = roi[roi >= 250]
roi[roi >= 250] -= 10
...