I'm looking for a algorithm similar adaptive thresholding, but that keeps color. I'm trying take an image like this:
And make it look like this:
If it matters, I'm working in ios.
Here's a CIKernel that works well on your sample image
kernel vec4 coreImageKernel (sampler i)
{
vec2 dc = destCoord();
// center pixel color
vec4 c = unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,0.0))));
// for a whiteboard, the max of a neighborhood is likely to be the color
// of the whiteboard
vec4 cmax = c;
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(10.0,0.0)))), cmax);
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(-10.0,0.0)))), cmax);
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,10.0)))), cmax);
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,-10.0)))), cmax);
// normalize the center color according to the whiteboard color
vec4 r = c / cmax;
return premultiply(r);
}
So how does this work? Well the first part of the kernel, the part that calculates cmax, is calculating the local color of the whiteboard. This is the tricky part. Basically it determines (approximately) the color that whiteboard would be if there where no markings on it. To do this the kernel makes three key assumptions:
Here's what the output of cmax looks like:
Once the local whiteboard color is approximated it is just a matter of dividing the current pixel by the local background. This is similar to how a color cast is removed from an image.
This algorithm is similar to the Haze Removal example from the WWDC13 Core Image presentation. In that example a local min is subtracted to make blacker blacks. In this case a local max is divided to make whiter whites.
: