Reputation: 1094
Are there existing filters that could be used as a smooth threshold? By this I mean that pixel values should be thresholded between two values, but the intermediate values are interpolated.
Basically, I'm trying to implement this:
https://www.filterforge.com/wiki/index.php/Thresholds#Interpolation_.28.22Blending.22.29
Upvotes: 3
Views: 3010
Reputation: 1094
This ended up working for me:
[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}"];
Upvotes: 1
Reputation: 3633
You'll need to write your own using Core Image Kernel Language and a CIColorKernel
.
I would use a smoothstep
and pass in two edge values along with the luminance of the current pixel. The CIKL could look something like this:
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);
}
You can wrap this into a CIFilter
with the following code:
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)
}
}
Note that you'll need to ensure inputEdge0
is less than inputEdge1
, or the smoothstep
will go a little crazy. You may want to saturate
them too, to ensure they're between 0 and 1.
Have a look at CIFilter.registerFilterName
which will allow you to create an instance of SmoothThreshold
with familiar syntax, although this will work fine:
let image = CIImage(image: UIImage(named: "monalisa.jpg")!)!
let filter = SmoothThreshold()
filter.inputImage = image
let final = filter.outputImage
Cheers!
Simon
Upvotes: 9