«Растягивание» гистограмм (уровней) в Numpy, Python - PullRequest
3 голосов
/ 07 апреля 2019

У меня есть изображение в градациях серого, фон которого по цветовой шкале 0-255 имеет средне-белый цвет со средним значением цвета пикселя 246;передний план имеет средне-серый цвет со средним значением цвета пикселя 186.

Я хотел бы «сдвинуть» каждый пиксель выше 246 до 255, каждый пиксель ниже 186 до нуля и «растянуть» все, что между ними.Есть ли какой-нибудь готовый алгоритм / процесс, чтобы сделать это в numpy или python, или новые уровни / гистограммы должны вычисляться «вручную» (как я делал до сих пор)?

Это эквивалентно,в Gimp или Photoshop, открыв окно уровней и выбрав белую и черную пипетку соответственно, светлую область, которую мы хотим сделать белым, и более темную область, которую мы хотим сделать черным: приложение изменяет уровни / гистограмму («растягивает»значения между выбранными точками) соответственно.

Некоторые изображения того, что я пытаюсь:

page after page shadow elimination Sampled colours Result

Ответы [ 2 ]

1 голос
/ 08 апреля 2019

Если ваше изображение имеет формат uint8 и типичный размер изображения, одним из эффективных способов является настройка таблицы соответствия:

L, H = 186, 246
lut = np.r_[0:0:(L-1)*1j, 0.5:255.5:(H-L+3)*1j, 255:255:(255-H-1)*1j].astype('u1')

# example
from scipy.misc import face
f = face()

rescaled = lut[f]

Для небольших изображений это быстрее (в моей настройке он пересекает около 100 000 пикселей серой шкалы) для непосредственного преобразования:

fsmall = (f[::16, ::16].sum(2)//3).astype('u1')

slope = 255/(H-L+2)
rescaled = ((1-L+0.5/slope+fsmall)*slope).clip(0, 255).astype('u1')
1 голос
/ 07 апреля 2019

Вот один из способов -

def stretch(a, lower_thresh, upper_thresh):
    r = 255.0/(upper_thresh-lower_thresh+2) # unit of stretching
    out = np.round(r*(a-lower_thresh+1)).astype(a.dtype) # stretched values
    out[a<lower_thresh] = 0
    out[a>upper_thresh] = 255
    return out

В соответствии с ФП, набор критериев был:

  • «сдвиг» каждого пикселя выше 246 до 255, следовательно, 247 и выше должны стать 255.

  • каждый пиксель ниже 186 до zero, следовательно, 185 и ниже должны стать 0.

  • Следовательно, исходя из вышеупомянутых двух требований, 186 должно стать чем-то большим, чем 0 и так далее, до 246, которое должно быть меньше, чем 255.

В качестве альтернативы, мы также можем использовать np.where, чтобы сделать его немного более компактным -

def stretch(a, lower_thresh, upper_thresh):
    r = 255.0/(upper_thresh-lower_thresh+2) # unit of stretching
    out = np.round(r*np.where(a>=lower_thresh,a-lower_thresh+1,0)).clip(max=255)
    return out.astype(a.dtype)

Пробный прогон -

# check out first row input, output for variations
In [216]: a
Out[216]: 
array([[186, 187, 188, 246, 247],
       [251, 195, 103,   9, 211],
       [ 21, 242,  36,  87,  70]], dtype=uint8)

In [217]: stretch(a, lower_thresh=186, upper_thresh=246)
Out[217]: 
array([[  4,   8,  12, 251, 255], 
       [255,  41,   0,   0, 107],
       [  0, 234,   0,   0,   0]], dtype=uint8)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...