Libvips: Is it possible to replace variety of colors with one?

Created on 19 Feb 2018  路  5Comments  路  Source: libvips/libvips

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?

question

All 5 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

BorntraegerMarc picture BorntraegerMarc  路  3Comments

Boojs picture Boojs  路  5Comments

sonyarianto picture sonyarianto  路  4Comments

volkan picture volkan  路  5Comments

solisoft picture solisoft  路  3Comments