import struct import scipy import scipy.misc import scipy.cluster import codecs # from IPython.display import Markdown, display, HTML import colorsys import math import numpy as np NUM_CLUSTERS = 64 def getColourAsHex(colour): return '#' + ''.join(format(c, '02x') for c in colour.astype(int)) def getColoursForImageByClusters(image): """ Adapted on answers by Peter Hansen (http://stackoverflow.com/a/3244061) & Johan Mickos (http://stackoverflow.com/a/34140327) """ im = image.copy().resize((150, 150)) # optional, to reduce time ar = scipy.misc.fromimage(im) shape = ar.shape ar = ar.reshape(scipy.product(shape[:2]), shape[2]) # print( 'finding clusters') codes, dist = scipy.cluster.vq.kmeans(ar.astype(float), NUM_CLUSTERS) # print ('cluster centres:\n', codes) vecs, dist = scipy.cluster.vq.vq(ar, codes) # assign codes counts, bins = scipy.histogram(vecs, len(codes)) # count occurrences # When only looking for single color: # index_max = scipy.argmax(counts) # find most frequent # peak = codes[index_max] # colour = ''.join(chr(c) for c in peak).encode('hex') # print( 'most frequent is %s (#%s)' % (peak, colour)) percentages = 100 * counts / sum(counts) # print("Percentages", percentages) # colours = [ in codes] # print(colours) return list(zip(codes, percentages)) def getColoursForImageByPxAvg(image): im = image.copy().resize((8, 8)) pixels = np.concatenate(scipy.misc.fromimage(im)) # colours = ['#' + ''.join(format(c, '02x') for c in color.astype(int)) for color in pixels] percentages = np.zeros(len(pixels)) + (100 / len(pixels)) return list(zip(pixels, percentages)) def getColoursAsHTML(colours): return " ".join(['%s - (%s %%)' % (getColourAsHex(colour[0]), getColourAsHex(colour[0]), colour[1]) for colour in colours]); def loadColoursFromDbImages(images): return [i.colours for i in images] def getSvgFromDbImages(images, elId = ""): # sum concatenates all colour arrays allColours = [] for c in loadColoursFromDbImages(images): allColours += c # box 160, because center or circle = 100 => +/- 50 => + r of colour circle (max: 10) => 160 svg = '' % elId radius = 100 for colour in allColours: rgb, percentage = colour rgbNorm = rgb/255 hsv = colorsys.rgb_to_hsv(rgbNorm[0], rgbNorm[1], rgbNorm[2]) # find position on circle radians = 2 * math.pi * hsv[0] x = math.cos(radians) y = math.sin(radians) # based on saturation, we move inwards/outwards # min = 0.5, max = 1.5 (dus + 0.5) pos = np.array([x,y]) * (0.5 + hsv[1]) * radius # Posibilitiy: determine position based on avg(saturation, value) => dark & grey inside, shiney and colourful outside # pos = np.array([x,y]) * (0.5 + (hsv[1]+hsv[2])/2) * radius r = max(1,-10/percentage+10) # as r, we converge to maximum radius 10, but don't want to get smaller radi then 1 c = '' % (pos[0], pos[1], r, getColourAsHex(rgb)) svg += c svg += "" return svg