Metal Custom CIFilter другое возвращаемое значение

Я пишу CIFilter, но цвета результирующих пикселей отличаются от значений, возвращаемых функцией metal.

ядро.металл

#include <CoreImage/CoreImage.h>

extern "C" { namespace coreimage {

    float4 foo(sample_t rgb){

        return float4(0.3f, 0.5f, 0.7f, 1.0f);

    }
}

MetalFilter.swift

import CoreImage

class MetalFilter: CIFilter {

    private let kernel: CIColorKernel

    var inputImage: CIImage?

    override init() {
        let url = Bundle.main.url(forResource: "default", withExtension: "metallib")!
        let data = try! Data(contentsOf: url)
        kernel = try! CIColorKernel(functionName: "foo", fromMetalLibraryData: data)
        super.init()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func outputImage() -> CIImage? {
        guard let inputImage = inputImage else {return nil}
        return kernel.apply(extent: inputImage.extent, arguments: [inputImage])
    }
}

Когда я получаю outputImage, у меня есть следующие значения:
R = 0,58431372549019611
G = 0,73725490196078436
B = 0,85490196078431369

Это своего рода постобработка (например, pow (x, 1 / 2.373) после того, как функция metal возвращает значения.


person Roman Kazov    schedule 04.12.2018    source источник
comment
Похоже, текстура, лежащая в основе вашего выходного изображения, имеет кодировку sRGB.   -  person warrenm    schedule 04.12.2018
comment
Для ясности, это ожидаемое поведение: вы возвращаете значение линейного пространства из своего ядра, и оно получает кодировку sRGB в соответствии с цветовым пространством по умолчанию выходного изображения. Если вы хотите, чтобы значения на изображении были буквально теми, которые вы указали выше, вам необходимо вручную отменить гамму с помощью функции srgb_to_linear перед возвратом значения. Это будет отменено преобразованием linear-to-srgb, которое происходит при выводе. Автоматическое преобразование sRGB - это то, что вам нужно большую часть времени, и на современных графических процессорах Apple это фактически бесплатно.   -  person warrenm    schedule 04.12.2018
comment
Поскольку вы пишете собственный фильтр, я думаю, вы уже добились успеха с тем, на чем я застрял. Я пытаюсь применить простой фильтр виньетки к прямой трансляции с камеры с использованием металла. Результаты довольно медленные и запаздывающие, проверьте это, если вы можете сказать мне, чего не хватает: stackoverflow.com/q/53898780/1364053 < / а>   -  person nr5    schedule 23.12.2018
comment
такая же проблема здесь, ты исправил это?   -  person krosshj    schedule 17.06.2021


Ответы (1)


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

Эти цветовые пространства настроены со значениями по умолчанию, которые, по моему опыту, зависят от устройства (и его дисплея), на котором вы работаете. Однако вы можете определить оба цветовых пространства, используя kCIContextWorkingColorSpace и _ 3_ параметры при создании вашего CIContext.

Если вы установите оба значения на NSNull(), Core Image не будет выполнять какое-либо сопоставление цветов, обрабатывая все значения цвета так, как они находятся в буферах изображения. Однако ваш фильтр, вероятно, имеет некоторые предположения о цветовом пространстве входных образцов. Так что имейте это в виду, когда вы имеете дело с входами от таких источников, как камера, которые могут иметь разные цветовые пространства в зависимости от устройства и конфигурации камеры.

Другой способ убедиться, что входные образцы всегда находятся в нужном цветовом пространстве, - это установить _6 _ при создании CISampler, который служит входными данными для вашего настраиваемого ядра.

person Frank Schlegel    schedule 22.06.2019