如何使用 CoreImage 创建平滑的阈值过滤器?
How to use CoreImage to create a smooth threshold filter?
是否存在可用作平滑阈值的现有过滤器?我的意思是像素值应该在两个值之间进行阈值处理,但中间值是内插的。
基本上,我正在尝试实现这个:
https://www.filterforge.com/wiki/index.php/Thresholds#Interpolation_.28.22Blending.22.29
这最终对我有用:
[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}"];
您需要使用 Core Image 内核语言和 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
干杯!
西蒙
是否存在可用作平滑阈值的现有过滤器?我的意思是像素值应该在两个值之间进行阈值处理,但中间值是内插的。
基本上,我正在尝试实现这个:
https://www.filterforge.com/wiki/index.php/Thresholds#Interpolation_.28.22Blending.22.29
这最终对我有用:
[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}"];
您需要使用 Core Image 内核语言和 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
干杯!
西蒙