Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to achieve adaptive threshold filter with color

I'm looking for a algorithm similar adaptive thresholding, but that keeps color. I'm trying take an image like this:

original image

And make it look like this:

processed image

If it matters, I'm working in ios.

like image 265
nwales Avatar asked Dec 25 '22 23:12

nwales


2 Answers

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:

  1. the whiteboard color does not locally vary much
  2. the markers subtract from whiteboard color and
  3. that for each pixel, it or a nearby pixel (10 pixels N,S,E or W) don't have any markings. In effect the kernel assumes is that marked lines are thinner than 10 pixels though that constant could be adjusted)

Here's what the output of cmax looks like:

enter image description here

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.

Result:

like image 75
David Hayward Avatar answered Dec 28 '22 07:12

David Hayward


Thresholding always results in a binary mask, i.e. pixels that are below the (local adaptive) threshold and pixels that are above. If you have that mask you can of course keep the color information of the original image.

Therefore a simple approach would result in the following workflow:

  • Image with red, green, blue value
  • Produce gray scale image by adding red+green+blue
  • Create mask of gray scaled image by local adaptive treshold on gray scale image
  • Apply mask to original image with red, green, blue values

Alternatively maybe:

  • Image with red, green, blue value
  • Create three masks for the image with only red (or green or blue respectively) values
  • Combine all three masks (logical and) to obtain a single mask
  • Apply mask to original image with red, green, blue values

These two ways might not be ideal but probably work already for a large number of cases including the example in the question.

like image 26
Trilarion Avatar answered Dec 28 '22 08:12

Trilarion