vips - Как добиться эффекта растушевки краев

Я использую библиотеку vips для управления некоторыми изображениями, в частности ее привязкой Lua, lua-vips, и я пытаюсь найти способ сделать эффект пера на краю изображения.

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

Предположим, что существует метод «feather_edges», это будет что-то вроде:

local bg = vips.Image.new_from_file("foo.png")
local img = vips.Image.new_from_file("bar.png") --smaller than `bg`
img = img:feather_edges(6) --imagine a 6px feather
bg:composite(img, 'over')

Но все же было бы неплохо указать, какие части изображения следует растушевать. Любые идеи о том, как это сделать?


person PiFace    schedule 08.03.2019    source источник


Ответы (2)


Вам нужно вытащить альфу из верхнего изображения, замаскировать края черной рамкой, размыть альфу, чтобы растушевать края, снова прикрепить, а затем скомпоновать.

Что-то вроде:

#!/usr/bin/luajit

vips = require 'vips'

function feather_edges(image, sigma)
    -- split to alpha + image data 
    local alpha = image:extract_band(image:bands() - 1)
    local image = image:extract_band(0, {n = image:bands() - 1})

    -- we need to place a black border on the alpha we can then feather into,
    -- and scale this border with sigma
    local margin = sigma * 2
    alpha = alpha
        :crop(margin, margin,
            image:width() - 2 * margin, image:height() - 2 * margin)
        :embed(margin, margin, image:width(), image:height())
        :gaussblur(sigma)

    -- and reattach
    return image:bandjoin(alpha)
end

bg = vips.Image.new_from_file(arg[1], {access = "sequential"})
fg = vips.Image.new_from_file(arg[2], {access = "sequential"})
fg = feather_edges(fg, 10)
out = bg:composite(fg, "over", {x = 100, y = 100})
out:write_to_file(arg[3])
person jcupitt    schedule 09.03.2019
comment
Это почти то, что мне нужно. Одна проблема заключается в том, что черная рамка становится видимой. Но ты дал мне отличные советы, потому что я не мог понять, как работать с конкретными группами. - person PiFace; 11.03.2019
comment
Мне удалось внести небольшую корректировку в вашу функцию, и она решила эту проблему! Должен ли я опубликовать это как ответ на свой вопрос или просто отредактировать свой пост? - person PiFace; 11.03.2019
comment
Привет, PiFace, я бы написал как ответ на твой вопрос, а затем прими это. - person jcupitt; 11.03.2019
comment
Я обновил решение проблемы с черной рамкой. - person jcupitt; 15.03.2019

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

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

local function featherEdges(img, sigma)
    local copy = img:copy()
        :resize(1, { vscale = (img:height() - sigma * 2) / img:height() })
        :embed(0, sigma, img:width(), img:height())
    local alpha = copy
        :extract_band(copy:bands() - 1)
        :gaussblur(sigma)
    return img
        :extract_band(0, { n = img:bands() - 1 })
        :bandjoin(alpha)
end
person PiFace    schedule 11.03.2019
comment
Ницца! Но вместо того, чтобы уменьшать альфу, как насчет маскировки краев? Это будет намного быстрее и будет работать для изображений сложной формы (поскольку вы не потеряете выравнивание между изображением и альфа-каналом). Я обновил свой ответ другой альтернативой. - person jcupitt; 15.03.2019
comment
Вы также можете удалить copy --- все операции libvips неразрушающие и возвращают новые изображения, а не изменяют свои аргументы. - person jcupitt; 15.03.2019
comment
ооо я вижу, это правда, копировать не надо. И я не подумал об обрезке вместо изменения размера :P Кстати, с какими сложными фигурами это сработает? - person PiFace; 15.03.2019
comment
Обычно я использую это для тестирования маскирования сложной формы en.wikipedia.org/ wiki/Portable_Network_Graphics#/media/ - person jcupitt; 15.03.2019