K表示图像分割失败

时间:2016-01-14 20:35:00

标签: python algorithm python-2.7 k-means image-segmentation

我目前正在使用K-means算法制作图像分割程序。

以下是我正在做的总结:

  • 使用精简点差算法创建N个Centroids(得到更好的结果 比随机的)
  • 将每个像素分配到最近的质心
  • 将质心位置更改为“质心”
  • 重复2和3,直到没有任何改变

要确定质心,我将获取分配给质心的所有像素的平均位置。

我的问题是,当图片非常简单时,它的工作正常:

Working picture

但是当我使用更复杂的图片时(这张照片根本不是“非常复杂”)

Fail picture

我不确定为什么这不能正常工作,我仔细检查了我的代码,并且在算法上看不出任何错误,问题不是来自算法选择我认为因为很多人通过互联网展示图片,用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)

0 个答案:

没有答案