Border between two colours

I have loaded an image into Processing.

loadImage("setup.png");

Here (below) is a greatly magnified screenshot. I want an easy way to make the pixels along the border either red or blue. The choice could be change to the nearest colour, or it could be a flip of a two-sided coin, or some other method.

Or, perhaps, a combination of nearest colour and flip a coin if not nearer to one or the other.

There are other borders in the image, but only about eight colours in all so I could have a line of code for each pair of colours that have a border.

Red (218, 95, 68)

Blue (136, 57, 155)

  • Create a HashMap of color to integer count.
  • For each pixel in the image, increment the count of its color.
  • Sort the colors in the map based on their count and use some cutoff to decide on your target palette (either take the top 8 colors or all the colors with a count above some fraction of the total pixel count).
  • Put the palette colors in a new HashMap with a dummy value.
  • For each pixel in the image, if its color is not in the palette hash, find its nearest neighbor color in the palette and write that as its new color.

That’s good, but it boils down to this:

And that is my question. How do you find the nearest colour? I thought of using approximate equality but often the Red value of a colour will send you one way and the Blue value the other way…

If your pixel is on the border between two different colors, then, yes, it would have to get sent one way or the other.

I would treat the colors as triples of values and compute distance as with vectors. For colors c0 and c1, the square distance is sq(c1.r-c0.r) + sq(c1.g-c0.g) + sq(c1.b-c0.b). Then choose the palette entry that minimized the squared distance.

That’s not the most perceptually accurate, so there are a variety of ways you could improve it. Our eyes are much more sensitive to green than red and the least to blue so you could scale up the green difference a lot and the red a little before squaring. 2x red, 7x green, and 1x blue is pretty good. In the extreme, you could try to convert the colors to some perceptually accurate CIE colorspace and compute distances there, but I’ll bet that’s overkill and won’t make much difference anyways.

Or you could try to dig into the source code for some image editing software such as https://www.gimp.org/ to see how their posterize code works.

That’s exactly what I did in the end, thank you! It would have been overkill, but I already had the code. I converted the RGB to LCH then ignored the Lum and the Chr and went for the nearest Hue.