Как применить преобразование к определенному диапазону тонов в VIPS/Python

Мне приходится применять различные преобразования к разным тональным диапазонам 16-битных файлов TIFF в VIPS (и Python). Мне удалось это сделать, но я новичок в VIPS и не уверен, что делаю это эффективно. Эти изображения весят несколько сотен мегабайт каждое, и удаление каждого лишнего шага может сэкономить мне несколько секунд на изображение.

Интересно, есть ли более эффективный способ добиться тех же результатов, которые я получаю из приведенного ниже кода, например, с помощью таблиц поиска (я не мог понять, как они работают в VIPS). Код отделяет тени в красном канале и пропускает их через преобразование.

im = Vips.Image.new_from_file("test.tiff")

# Separate the red channel
band = im[0]

# Find the tone limit for the bottom 5%
lim = band.percent(5) 

# Create a mask using the tone limit
mask = (band <= lim) 

# Convert the mask to 16 bits
mask = mask.cast(band.BandFmt, shift = True) 

# Run the transformation on the image and keep only the shadow areas
new_shadows = (65535 * (shadows / lim * 0.1)) & mask 

После запуска более-менее похожих кодов для каждого тонального диапазона (блики, тени, средние тона) я складываю все получившиеся изображения вместе, чтобы воссоздать исходную полосу:

new_band = (new_shadows.add(new_highlights).add(new_midtones)).cast(band.BandFmt)

person retrography    schedule 26.08.2016    source источник
comment
Да, вы должны быть в состоянии сделать это немного быстрее. Например, вы запускаете (наверное?) percent три раза, по одному разу для каждого диапазона. Вместо этого сначала найдите гистограмму вашего изображения, а затем проанализируйте ее, чтобы получить процент для каждой полосы. Пожалуйста, опубликуйте крошечный, но полный пример, который мы можем попробовать запустить. edit: и, как вы говорите, конечно, вы также можете использовать LUT, что должно дать еще одно огромное ускорение.   -  person jcupitt    schedule 26.08.2016


Ответы (1)


Я сделал для вас демонстрационную программу, показывающую, как сделать что-то подобное с функциями гистограммы vips:

import sys
import pyvips

im = pyvips.Image.new_from_file(sys.argv[1])

# find the image histogram 
# 
# we'll get a uint image, one pixel high and 256 or
# 65536 pixels across, it'll have three bands for an RGB image source
hist = im.hist_find()

# find the normalised cumulative histogram 
#
# for a 16-bit source, we'll have 65535 as the right-most element in each band
norm = hist.hist_cum().hist_norm()

# search from the left for the first pixel > 5%: the position of this pixel 
# will give us the pixel value that 5% of pixels fall below
# 
# .profile() gives back a pair of [column-profile, row-profile], we want index 1
# one. .getpoint() reads out a pixel as a Python array, so for an RGB Image 
# we'll have something like [19.0, 16.0, 15.0] in shadows
shadows = (norm > 5.0 / 100.0 * norm.width).profile()[1].getpoint(0, 0)

# Now make an identity LUT that matches our original image
lut = pyvips.Image.identity(bands=im.bands,  
                            ushort=(im.format == "ushort"))

# do something to the shadows ... here we just brighten them a lot
lut = (lut < shadows).ifthenelse(lut * 100, lut)

# make sure our lut is back in the original format, then map the image through
# it
im = im.maplut(lut.cast(im.format))

im.write_to_file(sys.argv[2])

Он выполняет одну операцию поиска-гистограммы на исходном изображении, затем одну операцию карты-гистограммы, поэтому он должен быть быстрым.

Это просто настройка теней, вам нужно будет немного расширить его, чтобы сделать средние тона и блики, но вы можете сделать все три модификации из одной исходной гистограммы, поэтому она не должна быть медленнее.

Пожалуйста, откройте вопрос на трекере libvips, если у вас есть еще вопросы:

https://github.com/libvips/libvips/issues

person jcupitt    schedule 14.09.2016