Last active
February 15, 2023 16:14
-
-
Save jcupitt/ee3afcbb931b41b4d7f4 to your computer and use it in GitHub Desktop.
find dominant colour in an 8-bit RGB Image with libvips python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import sys | |
from gi.repository import Vips | |
N_BINS = 10 | |
BIN_SIZE = 256 / N_BINS | |
im = Vips.Image.new_from_file(sys.argv[1], access = Vips.Access.SEQUENTIAL) | |
# turn to lab | |
im = im.colourspace("lab") | |
# turn to 8-bit unsigned so we can make a histogram | |
# use 0 - 255 to be -128 - +127 for a/b | |
# and 0 - 255 for 0 - 100 L | |
im += [0, 128, 128] | |
im *= [255.0 / 100, 1, 1] | |
im = im.cast("uchar") | |
# make a 3D histogram of the 8-bit LAB image | |
hist = im.hist_find_ndim(bins = N_BINS) | |
# find the position of the maximum | |
v, x, y = hist.maxpos() | |
# get the pixel at (x, y) | |
pixel = hist(x, y) | |
# find the index of the max value in the pixel | |
band = pixel.index(v) | |
# scale up for the number of bins | |
x = x * BIN_SIZE + BIN_SIZE / 2 | |
y = y * BIN_SIZE + BIN_SIZE / 2 | |
band = band * BIN_SIZE + BIN_SIZE / 2 | |
# turn the index back into the LAB colour | |
L = x * (100.0 / 255) | |
a = y - 128 | |
b = band - 128 | |
print "dominant colour:" | |
print " L = ", L | |
print " a = ", a | |
print " b = ", b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import sys | |
from gi.repository import Vips | |
im = Vips.Image.new_from_file(sys.argv[1], access = Vips.Access.SEQUENTIAL) | |
N_BINS = 10 | |
BIN_SIZE = 256 / N_BINS | |
# make a 3D histogram of the RGB image ... 10 bins in each axis | |
hist = im.hist_find_ndim(bins = N_BINS) | |
# find the position of the maximum | |
v, x, y = hist.maxpos() | |
# get the pixel at (x, y) | |
pixel = hist(x, y) | |
# find the index of the max value in the pixel | |
band = pixel.index(v) | |
print "dominant colour:" | |
print " R = ", x * BIN_SIZE + BIN_SIZE / 2 | |
print " G = ", y * BIN_SIZE + BIN_SIZE / 2 | |
print " B = ", band * BIN_SIZE + BIN_SIZE / 2 |
You need to ask for the output array, eg.:
john@banana ~/pics $ python3
Python 3.10.7 (main, Nov 24 2022, 19:45:47) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyvips
>>> x = pyvips.Image.new_from_file("k2.jpg")
>>> x.max(size=12)
255.0
>>> x.max(size=12, out_array=True)
[255.0, {'out_array': [255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0]}]
You can get the positions of the maxima like this:
>>> x.max(size=12, out_array=True, x_array=True, y_array=True)
[255.0, {'out_array': [255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0], 'x_array': [376, 377, 378, 378, 379, 385, 386, 387, 390, 391, 391, 392], 'y_array': [2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032]}]
@jcupitt, you helped a lot, I really appreciate it! Maybe we’ll continue in the discussion?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@jcupitt, I use
max()
, but it returns a single result... Where could I be wrong?yields