CIAdditionCompositing дает неправильный эффект

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

func darkenImage(by multiplier: CGFloat) -> CIImage? {
    let divImage = CIImage(color: CIColor(red: multiplier, green: multiplier, blue: multiplier))

    let divImageResized = divImage.cropped(to: self.extent) //Set multiplier image to same size as image to be darkened

    if let divFilter = CIFilter(name: "CIMultiplyBlendMode", parameters: ["inputImage":self, "inputBackgroundImage":divImageResized]) {

        return divFilter.outputImage
    }

    print("Failed to darken image")
    return nil
}

После этого я беру каждое затемненное изображение и складываю их вместе (добавляю изображение 1 и 2 вместе, затем добавляю результат вместе с изображением 3 и т. д.):

func blend(with image: CIImage, blendMode: BlendMode) -> CIImage? { 
    if let filter = CIFilter(name: blendMode.format) { //blendMode.format is CIAdditionCompositing
        filter.setDefaults()

        filter.setValue(self, forKey: "inputImage")
        filter.setValue(image, forKey: "inputBackgroundImage")

        let resultImage = filter.outputImage

        return resultImage
    }

    return nil
}

Этот код выполняется и создает новое изображение, но чем больше изображений я усредняю ​​вместе, тем темнее становятся тени. Яркость светлых участков остается примерно такой же, как и на каждом отдельном изображении, но более темные части становятся все темнее и темнее. Кто-нибудь знает, что может быть не так?

Исходное изображение: Исходное изображение

В среднем по 2 изображениям: 2x в среднем

В среднем 8 изображений: В среднем в 8 раз

В среднем 20 изображений: 20-кратное среднее

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


person Jorn    schedule 18.12.2019    source источник
comment
Я подозреваю, что ваша техника затемнения (будь то CI или Lightroom) не работает в линейном цветовом пространстве. Если имеется нелинейная гамма-кривая, то умножение значений компонентов на долю не дает изображения, которое представляет собой эту долю как свет. Таким образом, добавление их вместе не приведет к тому, что вы ожидаете. Я бы порекомендовал провести некоторые тесты с изображениями с известными значениями цветового представления (т.е. посмотреть на фактические значения растровых изображений) с различными цветовыми пространствами для интерпретации этих значений. Посмотрите, дает ли умножение ожидаемый результат. Точно так же посмотрите, работает ли сложение.   -  person Ken Thomases    schedule 14.03.2020


Ответы (1)


Это может прийти немного поздно, но некоторые.

Первая попытка

Я подозреваю, что проблема в том, что цветовая гамма нелинейна, как упоминал Кен Томас. К сожалению, преобразование всех изображений в линейные с помощью фильтра "CISRGBToneCurveToLinear" и после того, как все изображения были сложены, преобразование их обратно с помощью "CILinearToSRGBToneCurve" не решает проблему.

Решение

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

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

if let evFilter = CIFilter(name: "CIExposureAdjust", parameters: ["inputImage":self, "inputEV":NSNumber(-1)]) {
    return evFilter.outputImage?.insertingIntermediate()
}

P.S.: Обратите внимание, что для получения правильного результата изображения должны быть добавлены друг к другу и уменьшены вдвое по экспозиции, чтобы каждое изображение имело одинаковый вес с результирующим изображением. простое добавление следующего изображения в строку и последующее уменьшение экспозиции всегда будет придавать весу последнего добавленного изображения 50% общего результата.

person Enie    schedule 23.01.2021