Skip to content

Instantly share code, notes, and snippets.

@ankitshekhawat
Last active January 9, 2023 19:59
Show Gist options
  • Save ankitshekhawat/b743d69d6c69b28f10d2 to your computer and use it in GitHub Desktop.
Save ankitshekhawat/b743d69d6c69b28f10d2 to your computer and use it in GitHub Desktop.
A quick python code to detect color of an item from ecommerce website using just kmeans without OpenCV. Nowhere close to accurate but good for a quick hack. Can be improved with Sobel edge detection and skin detection.
import numpy as np
from PIL import Image, ImageDraw
import colorsys, random
from pylab import plot,show
from numpy import vstack,array
from numpy.random import rand
from scipy.cluster.vq import kmeans,vq
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
res = 2 # Resolution
clusters = 4
import glob, os
os.chdir("./images")
for file in glob.glob("*.jpg"):
print(file)
files = glob.glob("*.jpg")
files.append(glob.glob("*.jpeg"))
filename = files[random.randint(0,len(files))]
im = Image.open("./" + filename)
im = im.crop((int(im.width*0.13), 0, int(im.width*0.87), im.height)) # crop the left/right bands that appear in some images to make bg removal easy
orig = im
##### Background removal code ########
border_clusters = 2
border_pixels = []
for i in range(0, im.width):
px = im.getpixel((i, 0))
border_pixels.append([px[0],px[1],px[2]])
px = im.getpixel((i, im.height-1))
border_pixels.append([px[0],px[1],px[2]])
for i in range(0, im.height):
px = im.getpixel((0, i))
border_pixels.append([px[0],px[1],px[2]])
px = im.getpixel((im.width-1, i))
border_pixels.append([px[0],px[1],px[2]])
border_data = array(border_pixels)
# computing K-Means with K = 2 (2 clusters)
border_centroids,_ = kmeans(border_data, border_clusters)
# assign each sample to a cluster
border_idx,_ = vq(border_data, border_centroids)
border_counts = []
for i in range(0, border_clusters):
border_counts.append(border_data[border_idx==i,1].size)
bg = border_counts.index(max(border_counts))
print border_centroids
bgR = border_data[border_idx==bg,0]
bgG = border_data[border_idx==bg,1]
bgB = border_data[border_idx==bg,2]
bgHSV = []
for i in range(0,bgR.size):
bgHSV.append(colorsys.rgb_to_hsv(float(bgR[i])/255, float(bgG[i])/255, float(bgB[i])/255))
print "hsv", bgHSV[i]
hRange = []
sRange = []
vRange = []
for i in bgHSV:
hRange.append(i[0])
sRange.append(i[1])
vRange.append(i[2])
hMax = max(hRange)
hMin = min(hRange)
sMax = max(sRange)
sMin = min(sRange)
vMax = max(vRange)
vMin = min(vRange)
for i in range(0,im.width):
for j in range(0, im.height):
px = im.getpixel((i,j))
pxhsv = colorsys.rgb_to_hsv(float(px[0])/255, float(px[1])/255, float(px[2])/255)
if (hMin <= pxhsv[0] <= hMax) and (sMin <=pxhsv[1] <= sMax) and (vMin <=pxhsv[2] <= vMax):
im.putpixel((i,j),(0, 255, 0, 255))
##### background removal code END########
x = []
y = []
xy = []
xyz = []
# im = im.crop((int(im.width*0.333), int(im.height*0.333), int(im.width*0.6666), int(im.height*0.6666)))
im = im.crop((int(im.width*0.2), 0, int(im.width*0.8), im.height))
# im.show()
for i in range(0,im.width/res):
for j in range(0, im.height/res):
px = im.getpixel((i*res,j*res))
if px != (0, 255, 0): #if the pixel is of key color don't insert it in data
xyz.append([px[0],px[1],px[2]])
data = array(xyz)
# computing K-Means with K = 2 (2 clusters)
centroids,_ = kmeans(data,clusters)
# assign each sample to a cluster
idx,_ = vq(data,centroids)
for centroid in centroids:
print centroid
counts = [] # count number of pixel per cluster
for i in range(0,clusters):
counts.append(data[idx==i,1].size)
swatches =[]
for i in range(0, clusters):
cen = centroids[i]
swatches.append({'count': counts[i], 'color': (cen[0], cen[1], cen[2])})
# sorting the swatch according to the counts, the last item in the list is the color
sorted_swatches = sorted(swatches, key=lambda k: k['count'])
print swatches
print sorted_swatches
sw = Image.new('RGB', (50*len(swatches),50), (191,191,191))
dr = ImageDraw.Draw(sw)
itr = 0
colors = []
for centroid in centroids:
colors.append([centroid[0], centroid[1], centroid[2]])
itr+=1
for i in range(len(swatches)):
f = sorted_swatches[i]['color']
dr.rectangle(((i*50,0),(i*50+50,50)), fill=(f))
print 'len swatch', len(swatches)
dr.rectangle((((len(swatches)-1)*50,0),((len(swatches)-1)*50+10,10)), fill='Green', outline='white')
dr.rectangle((((len(swatches)-2)*50,0),((len(swatches)-2)*50+10,10)), fill='Red', outline='white')
##### Plotting the image using matplotlib #######
fig = plt.figure()
ax = fig.add_subplot(121, projection='3d')
for i in range(0,clusters):
r = float(colors[i][0])/255
g = float(colors[i][1])/255
b = float(colors[i][2])/255
ax.scatter(data[idx==i,0],data[idx==i,1], data[idx==i,2], c=array([[ r],[ g],[ b]]), marker='o')
for i in range(0, clusters):
r = float(colors[i][0])/255
g = float(colors[i][1])/255
b = float(colors[i][2])/255
ax.scatter(colors[i][0],colors[i][1],colors[i][2], c=array([[ r],[ g],[ b]]), marker='*', s = 150, linewidths=2)
ax.set_xlabel('Red')
ax.set_ylabel('Blue')
ax.set_zlabel('Green')
dx = fig.add_subplot(322)
dx.axis('off')
dx.imshow(array(orig))
cx = fig.add_subplot(324)
cx.axis('off')
cx.imshow(array(im))
bx = fig.add_subplot(326)
bx.axis('off')
bx.imshow(array(sw))
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment