Hi! There is a command of ImageMagick to remove from the picture everything but the desired color:
convert input.jpg -fill white -fuzz 20% +opaque "#E7482C" output.jpg
Is it possible to achieve the same result with libvips?
Hello @nattfodd, in Ruby (for example) you could do something like:
require 'vips'
image = Vips::Image.new_from_file ARGV[0], access: :sequential
# the colour we search for as an RGB triple
match = [40, 100, 90]
# find euclidean distance between each RGB pixels in the input and our match
# colour
distance = Vips::Image.sum(((image - match) ** 2).bandsplit) ** 0.5
# swap pixels more than 50 away for white
image = (distance > 50).ifthenelse([255, 255, 255], image)
image.write_to_file ARGV[1]
That's no faster than your IM command, but it does use less memory at least.
Or you could use dE 1976:
require 'vips'
image = Vips::Image.new_from_file ARGV[0], access: :sequential
# the colour we search for as a CIELAB coordinate
match = [40, -20, 0]
# calculate dE 1976 colour difference
distance = image.dE76(image.new_from_image(match))
# swap pixels more than 50 away for white
image = (distance > 50).ifthenelse([255, 255, 255], image)
image.write_to_file ARGV[1]
Again, no faster than IM, but working in CIELAB should give more visually consistent results.
... the strange image.new_from_image(match) is necessary because .dE() does not support distance(image, constant), only distance(image, image). So it makes a constant image the size of image, then calculates the difference between the two images.
Thank you so much, @jcupitt ! Seems like the second way does what I need!
OK, glad that helps!
Of course you can skip the sqrt on version 1 above:
require 'vips'
image = Vips::Image.new_from_file ARGV[0], access: :sequential
# the colour we search for as an RGB triple
match = [40, 100, 90]
# find euclidean distance between each RGB pixels in the input and our match
# colour
distance = Vips::Image.sum(((image - match) ** 2).bandsplit)
# swap pixels more than 50 away for white
image = (distance > 50 ** 2).ifthenelse([255, 255, 255], image)
image.write_to_file ARGV[1]
Which makes it slightly faster than IM.