Skip to content

Instantly share code, notes, and snippets.

@jstejada
Last active September 19, 2018 19:49
Show Gist options
  • Select an option

  • Save jstejada/c9bd25570a7f6e984891 to your computer and use it in GitHub Desktop.

Select an option

Save jstejada/c9bd25570a7f6e984891 to your computer and use it in GitHub Desktop.
Intento de k-means para segmentación de imágenes
'''
Created on Mar 17, 2013
@author: JuanTejada
'''
from math import sqrt
from operator import div
import Image
import random
import sys
MAX_ITER = 20000
MIN_DIFF = 1
class Point():
def __init__(self, coords = (0,0,0), count = 1, dim = 3, matcoords = (0,0)):
self.coords = coords
self.count = count
self.dim = dim
self.matcoords = matcoords
def __eq__(self, other):
return self.coords == other.coords
def __str__(self):
return str(self.coords)
def __repr__(self):
return str(self.coords)
def __hash__(self):
return hash(self.coords)
def main():
path = "../../input/imagenes/42.png"
k = 10
#path = input("Enter the absolute path for the image:")
#k = input("Enter k:")
img = Image.open(path)
#img.show()
img.thumbnail((200, 200))
mat = img.load()
points = getPoints(img.size, mat)
clusters = kmeans(points, k)
print "Final Centroids: "+ str(clusters.keys())
#colors = [(0,0,0),(255,255,255),(255,0,0),(0,255,0),(0,0,255),(127,127,127)]
i = 0
for cluster in clusters:
for point in clusters[cluster]:
mat[point.matcoords] = tuple(map(int,cluster))
i += 1
img.show()
def kmeans(points, k):
centroids = generateSeeds(k, points)
print "Seeds: "+ str(centroids)
old = []
clusters = {cent.coords:[] for cent in centroids}
ptdim = getPointDim(points)
diff = 0
count = 0
while True:
print "k: "+str(len(centroids))
for point in points:
clusters[minDistanceCentroid(point, centroids)].append(point)
old = centroids
centroids = calculateCentroids(clusters, ptdim)
diff = max(diff, max([distance(old[i].coords, centroids[i].coords) for i in range(len(centroids))]))
if sameCentroids(old,centroids) or diff < MIN_DIFF or count>MAX_ITER:
break
else:
clusters = {cent.coords:[] for cent in centroids}
count += 1
return clusters
def distance(p1,p2):
return sqrt(sum([((p1[i]-p2[i])**2) for i in range(len(p1))]))
def calculateCentroids(clusters, ptdim):
centroids = []
for cluster in clusters.values():
ptct = 0
acum = [0 for i in range(ptdim)]
for point in cluster:
ptct += point.count
for i in range(len(point.coords)):
acum[i] += point.coords[i]
centroids.append(Point(tuple(map(div, acum, [float(ptct)]*ptdim)), 1, ptdim))
return centroids
def minDistanceCentroid(point, centroids):
min = sys.maxint
cen = 0
for i in range(len(centroids)):
d = distance(point.coords, centroids[i].coords)
if d < min:
min = d
cen = i
return centroids[cen].coords
def generateSeeds(k, points):
s = set(random.sample(points, k))
while len(s)!=k:
s = set(random.sample(points, k))
return list(s)
def getPointDim(points):
return points[0].dim
def getPoints(size, imgMat):
points = []
x, y = size
#counts = {}
for i in range(x):
for j in range(y):
points.append(Point(imgMat[i,j], 1, len(imgMat[i,j]), (i,j)))
#for count, coords in img.getcolors(x * y):
#points.append(Point(coords, count, len(coords)))
return points
def sameCentroids(old, new):
for o in old:
if not o in new: return False
return True
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment