Как использовать CoreImage для создания сглаженного порогового фильтра?
Существуют ли фильтры, которые можно использовать как плавный порог? Под этим я подразумеваю, что значения пикселей должны быть пороговыми между двумя значениями, но промежуточные значения интерполируются.
По сути, я пытаюсь реализовать это:
2 ответа
Вам нужно будет написать свой собственный, используя Core Image Kernel Language и CIColorKernel
,
Я бы использовал smoothstep
и передать в два значения края вместе с яркостью текущего пикселя. CIKL может выглядеть примерно так:
kernel vec4 color(__sample pixel, float inputEdgeO, float inputEdge1)
{
float luma = dot(pixel.rgb, vec3(0.2126, 0.7152, 0.0722));
float threshold = smoothstep(inputEdgeO, inputEdge1, luma);
return vec4(threshold, threshold, threshold, 1.0);
}
Вы можете обернуть это в CIFilter
со следующим кодом:
class SmoothThreshold: CIFilter
{
var inputImage : CIImage?
var inputEdgeO: CGFloat = 0.25
var inputEdge1: CGFloat = 0.75
var colorKernel = CIColorKernel(string:
"kernel vec4 color(__sample pixel, float inputEdgeO, float inputEdge1)" +
"{" +
" float luma = dot(pixel.rgb, vec3(0.2126, 0.7152, 0.0722));" +
" float threshold = smoothstep(inputEdgeO, inputEdge1, luma);" +
" return vec4(threshold, threshold, threshold, 1.0);" +
"}"
)
override var outputImage: CIImage!
{
guard let inputImage = inputImage,
colorKernel = colorKernel else
{
return nil
}
let extent = inputImage.extent
let arguments = [inputImage,
inputEdgeO,
inputEdge1]
return colorKernel.applyWithExtent(extent,
arguments: arguments)
}
}
Обратите внимание, что вам нужно убедиться, inputEdge0
меньше чем inputEdge1
, или smoothstep
немного сойдет с ума. Вы можете захотеть saturate
их тоже, чтобы убедиться, что они между 0 и 1.
Посмотри на CIFilter.registerFilterName
который позволит вам создать экземпляр SmoothThreshold
со знакомым синтаксисом, хотя это будет работать нормально:
let image = CIImage(image: UIImage(named: "monalisa.jpg")!)!
let filter = SmoothThreshold()
filter.inputImage = image
let final = filter.outputImage
Ура!
Саймон
Это сработало для меня:
[CIColorKernel kernelWithString:
@"kernel vec4 threshold(__sample s, float thresh) {\n"
"float avg = (s.r + s.g + s.b) / 3.0;\n"
"float val = smoothstep(0.0, thresh, avg);"
"return vec4(val, val, val, 1.0);\n}"];