Last active
September 19, 2018 19:49
-
-
Save jstejada/c9bd25570a7f6e984891 to your computer and use it in GitHub Desktop.
Intento de k-means para segmentación de imágenes
This file contains hidden or 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
| ''' | |
| 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