我目前正在使用K-means算法制作图像分割程序。
以下是我正在做的总结:
要确定质心,我将获取分配给质心的所有像素的平均位置。
我的问题是,当图片非常简单时,它的工作正常:
但是当我使用更复杂的图片时(这张照片根本不是“非常复杂”)
我不确定为什么这不能正常工作,我仔细检查了我的代码,并且在算法上看不出任何错误,问题不是来自算法选择我认为因为很多人通过互联网展示图片,用K表示良好的细分
如果您对如何改善我的结果有所了解......
如果你想自己测试它,这是我的代码。
我正在使用python 2.7
我的Algo.py:
from PIL import Image
from Pixel import Pixel
from Centroid import Centroid
import Tools
import random
class Algo:
def run(self, inputPath, outputPath, nbCluster, nbIteration):
size, pixelList = self.getImageData(inputPath)
centroidArray = self.initCentroid(size, pixelList, nbCluster)
for iteration in range(0, nbIteration):
print "Iteration : " + str(iteration)
self.clearCentroidsMembers(centroidArray)
self.assignCentroidToPixel(pixelList, centroidArray)
self.moveCentroid(centroidArray)
self.printResult(outputPath, size, centroidArray)
def clearCentroidsMembers(self, centroidArray):
for centroid in centroidArray:
centroid.members = []
def assignCentroidToPixel(self, pixelList, centroidArray):
for pixel in pixelList:
minDist = 100000;
closestCentroid = None
for centroid in centroidArray:
dist = Tools.getDistance(pixel.graphCoordinate, centroid.graphCoordinate)
if dist < minDist:
minDist = dist
closestCentroid = centroid
closestCentroid.members.append(pixel)
def moveCentroid(self, centroidArray):
for centroid in centroidArray:
newPos = Tools.getCenterOfMass(centroid.members)
if newPos == None:
newPos = centroid.graphCoordinate
centroid.graphCoordinate = newPos
def initCentroid(self, size, pixelList, nbCluster):
centroidArray = []
randomPixelPos = random.randint(0, len(pixelList) - 1)
graphCoordinate = pixelList[randomPixelPos].graphCoordinate
centroid = Centroid(graphCoordinate)
centroidArray.append(centroid)
for i in range(1, nbCluster):
maxDist = 0
graphCoordinate = None
for pixel in pixelList:
dist = 0
for centroid in centroidArray:
dist += Tools.getDistance(pixel.graphCoordinate, centroid.graphCoordinate)
dist = dist / len(centroidArray)
if dist > maxDist:
maxDist = dist
graphCoordinate = pixel.graphCoordinate
centroid = Centroid(graphCoordinate)
centroidArray.append(centroid)
return centroidArray
def printResult(self, path, size, centroidArray):
for centroid in centroidArray:
pixelList = []
for i in range(0, size[0] * size[1]):
pixelList.append((0, 0, 0))
for pixel in centroid.members:
pixelList[pixel.picturePosition] = pixel.graphCoordinate
resultImage = Image.new("RGB", size)
resultImage.putdata(pixelList)
resultImage.save(path + "out-" + str(centroidArray.index(centroid)) + ".jpg")
def getImageData(self, inputPath):
image = Image.open(inputPath)
image = image.convert("RGB")
size = image.size
pixelList = []
for y in range(0, size[1]):
for x in range(0, size[0]):
color = image.getpixel((x, y))
pixelPos = y * size[0] + x
pixel = Pixel(pixelPos, color)
pixelList.append(pixel)
return size, pixelList
我的Tools.py:
import math
def getDistance(pos1, pos2):
dist = math.sqrt( math.pow(pos2[0] - pos1[0], 2) + math.pow(pos2[1] - pos1[1], 2) + math.pow(pos2[2] - pos2[2], 2) )
return dist
def getCenterOfMass(pixelArray):
if len(pixelArray) == 0:
return None
center = [0, 0, 0]
for pixel in pixelArray:
center[0] += pixel.graphCoordinate[0]
center[1] += pixel.graphCoordinate[1]
center[2] += pixel.graphCoordinate[2]
center[0] /= len(pixelArray)
center[1] /= len(pixelArray)
center[2] /= len(pixelArray)
return (center[0], center[1], center[2])
这是Pixel.py:
class Pixel:
def __init__(self, position, coordinate):
self.graphCoordinate = coordinate
self.picturePosition = position
这是Centroid.py:
class Centroid:
def __init__(self, coordinate):
self.graphCoordinate = coordinate
self.members = []
最后是main.py
from Algo import Algo
algo = Algo();
algo.run("input/Stonehenge.jpg", "output/", 3, 100)