Dominant colour of an image with an alpha band. #3692
Replies: 6 comments 7 replies
-
Hi @kipcole9, I think I would do this in two passes:
|
Beta Was this translation helpful? Give feedback.
-
@jcupitt, I've finally got this back to the top of my list (as always, thanks for your guidance). I'm good on all the steps above I think, except:
I don't know how to perform step 3 in such a way that I can then call What would you suggest? Many thanks, --Kip |
Beta Was this translation helpful? Give feedback.
-
Hey @kipcole9, I faced same issue and solved something like this based on @jcupitt suggestions. Find Dominant ColorMix.install([
{:kino, "~> 0.11.2"},
{:vix, "~> 0.24.0"}
])
alias Vix.Vips.{Image, Operation, MutableOperation}
use Vix.Operator
defmodule Dominant do
def find(img) do
{count, _} =
img[3]
|> Operation.relational_const!(:VIPS_OPERATION_RELATIONAL_EQUAL, [0])
|> Operation.hist_find!()
|> Operation.max!()
black_pixels = round(count)
max_band_value = 256
bins = 10
bin_size = max_band_value / bins
midpoint = bin_size / 2
{:ok, histogram} =
img
|> Operation.flatten!()
|> Operation.hist_find_ndim(bins: bins)
[black | rest_pixel] = Operation.getpoint!(histogram, 0, 0)
{:ok, histogram} =
Image.mutate(histogram, fn img ->
pixel = [min(black - black_pixels, 0) | rest_pixel]
MutableOperation.draw_rect!(img, pixel, 0, 0, 1, 1)
end)
{v, %{x: x, y: y}} = Operation.max!(histogram)
pixel = Operation.getpoint!(histogram, x, y)
z = Enum.find_index(pixel, &(&1 == v))
r = x * bin_size + midpoint
g = y * bin_size + midpoint
b = z * bin_size + midpoint
[round(r), round(g), round(b)]
end
end
path = "~/Downloads/netflix.png"
{:ok, img} = Image.new_from_file(path)
img = Operation.resize!(img, 0.2)
v = Dominant.find(img)
IO.inspect(v, charlists: :as_lists)
{:ok, color} = Image.new_from_image(img, v)
color |
Beta Was this translation helpful? Give feedback.
-
@akash-akya, super helpful, thank you. I figured mutating the histogram was going to be the most likely path. |
Beta Was this translation helpful? Give feedback.
-
I had a "duh, of course" moment yesterday. One of the problems with using The simple fix is to use
And unfolds it to a 9x3 mono image like this:
Now you can run Sample code: #!/usr/bin/env python3
import sys
import pyvips
# number of bins in each axis
BINS = 16
BIN_SIZE = 256 / BINS
image = pyvips.Image.new_from_file(sys.argv[1], access="sequential")
hist = image.hist_find_ndim(bins=BINS).bandunfold()
_, result = hist.max(size=26, out_array=True, x_array=True, y_array=True)
print(f"26 most common colours:")
for v, x, y in zip(result["out_array"], result["x_array"], result["y_array"]):
r = BIN_SIZE / 2 + BIN_SIZE * (x // BINS)
g = BIN_SIZE / 2 + BIN_SIZE * y
b = BIN_SIZE / 2 + BIN_SIZE * (x % BINS)
print(f"count = {v}, rgb = {r}, {g}, {b}") |
Beta Was this translation helpful? Give feedback.
-
John, I just wanted to add my thanks for all your efforts, and for helping on this topic. It motivated me to make some updates to my image library adding better dominant colour identification (using your current example), k-means clustering, colour reduction (using k-means clustering), colour difference (using your vips_de* functions) and colour sorting (using a kind of hlv colourspace comparison which seems to produce a reasonable result perceptually). |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I am calculating the dominant color based upon this example. No issues when the image does not have an alpha band. But I'm not conceptually sure how to manage an image with an alpha band.
Flattening the image will understandably mean that the background colour will dominate the transparent areas. And in many images that are designed to be composited that means the dominant colour often becomes that value (or some other greyscale value depending on transparency).
Some thoughts I'm experimenting with:
out
array and omitting those positions that are the background colour?attention
and then calculateI'd appreciate any suggestions on how to exclude the background colour from the dominant colour calculation. Or more specifically, calculate the dominant colour of an image with and alpha band.
Beta Was this translation helpful? Give feedback.
All reactions