图像聚类-基于遗传算法(K-means改进) python实现

一、 先放几张效果图:

二 、代码部分:

import cv2
import matplotlib.pyplot as plt
import numpy as np
import math
import random
import copy


# 原图像路径
imPath = 'D:\img.jpg'

# 读取图像
img = cv2.imread(imPath)
copyImg = cv2.imread(imPath)

shape = img.shape
imWidth = shape[0]
imHeight = shape[1]

imgCluster = [0]
imgCluster = np.tile(imgCluster,(imWidth,imHeight,1))

#设置相关参数
numOfClass = 5
roundOfLoop = 10
originChoose = 20
colorArray = [[255, 0, 0], [0,255,0], [0,0,255],[255,255,255],[0,0,0]]

#其它全局变量
centerOfPic = [[] for i in range(numOfClass)]
bestCenter = [[] for i in range(numOfClass)]  #记录最佳中心
bestDis = 0


#1. --初始化部分
def GetDis(point, center):
    dis = 0
    for i in range(3):
        dis+= (point[i]-center[i])**2
    return math.sqrt(dis)


def Origin(img, numOfClass):
    
    global bestCenter, bestDis
    global centerOfPic
    
    for m in range(originChoose):
        centerOfPic = [[] for i in range(numOfClass)]
        #P1 生成随机中心
        for i in range(numOfClass):
            x = random.randint(0,imWidth) - 1
            y = random.randint(0,imHeight)- 1
            tmp = [x,y]
            while(tmp in centerOfPic):
                x = random.randint(0,imWidth) - 1 
                y = random.randint(0,imHeight) - 1
                tmp = [x,y]
            centerOfPic[i].append(img[x][y][0])
            centerOfPic[i].append(img[x][y][1])
            centerOfPic[i].append(img[x][y][2])


        #P2 计算初始种群的适应程度
        tmpDis = 0
        for i in range(imWidth):
            for j in range(imHeight):
                disList = []
                for k in range(numOfClass): 
                    dis = GetDis(img[i][j], centerOfPic[k])
                    disList.append(dis)
                tmpDis += min(disList)
                
        
        if(m==0):
            bestDis = tmpDis
            bestCenter = copy.deepcopy(centerOfPic) #第二处
        if(tmpDis < bestDis):
            bestDis = tmpDis
            bestCenter = copy.deepcopy(centerOfPic) #第一处
        print(m, bestCenter, bestDis)
    centerOfPic = copy.deepcopy(bestCenter)
    #P3 生成初始种群
    for i in range(imWidth):
        for j in range(imHeight):
            disList = []
            for k in range(numOfClass): 
                dis = GetDis(img[i][j], centerOfPic[k])
                disList.append(dis)
            index = disList.index(min(disList))
            imgCluster[i][j] = index
            
Origin(img, numOfClass)
#--1. 初始化部分



#2.-- 迭代
for m in range(roundOfLoop):
    print("迭代至第{}次".format(m+1))
    
    
    #计算目前种群的适应程度(仅用于对比最佳中心) & 种群划分
    tmpDis = 0
    for i in range(imWidth):
        for j in range(imHeight):
            disList = []
            disList2 = []
            for k in range(numOfClass): 
                dis = GetDis(copyImg[i][j], centerOfPic[k])
                disList.append(dis)
                index = imgCluster[i][j][0]
                if(index != -1 ):   
                    dis2 = GetDis(img[i][j], centerOfPic[k])
                    disList2.append(dis2)
            tmpDis += min(disList)
            index = imgCluster[i][j][0]
            if(index != -1 ):   
                index = disList2.index(min(disList2))
                imgCluster[i][j] = index
          
    print(tmpDis, bestDis)
    if(tmpDis < bestDis):
        print('适应程度更新')
        bestDis = tmpDis
        bestCenter = copy.deepcopy(centerOfPic) #第一处
    
    
    
    #P1 生成新的中心
    sumOfCluster = [[0,0,0] for i in range(numOfClass)]
    numOfPoints = [1 for i in range(numOfClass)]
    
    for i in  range(imWidth):
        for j in range(imHeight):
            index = imgCluster[i][j][0]
            if(index != -1 ):         
                sumOfCluster[index][0] += img[i][j][0]
                sumOfCluster[index][1] += img[i][j][1]
                sumOfCluster[index][2] += img[i][j][2]
                numOfPoints[index] += 1
    
    centerOfPic = [[] for i in range(numOfClass)]
    for i in range(numOfClass):
        centerOfPic[i].append(int(sumOfCluster[i][0]/numOfPoints[i]))
        centerOfPic[i].append(int(sumOfCluster[i][1]/numOfPoints[i]))
        centerOfPic[i].append(int(sumOfCluster[i][2]/numOfPoints[i]))

    
    for i in range(imWidth):
        for j in range(imHeight):
            disList = []
            for k in range(numOfClass): 
                dis = GetDis(img[i][j], centerOfPic[k])
                disList.append(dis)
            index = disList.index(min(disList))
            imgCluster[i][j] = index
            
    
    #P2 选择
    
    sumOfDis = [0 for i in range(numOfClass)]
    for i in  range(imWidth):
        for j in range(imHeight):
            index = imgCluster[i][j][0]
            if(index != -1 ):         
                dis = GetDis(img[i][j], centerOfPic[index])
                if(dis==0):
                    dis=1
                sumOfDis[index] += dis
    
    sumOfCnt = []
    cnt = 1
    for i in  range(imWidth):
        for j in range(imHeight):
            index = imgCluster[i][j][0]
            if(index != -1 ):
                dis = GetDis(img[i][j], centerOfPic[index])
                sumOfCnt.append(dis/sumOfDis[index])
    
    t = max(sumOfCnt)
    if(t==0):
        t=1
    
    cnt = 1
    while(t<=0.1):
        t*=10
        cnt*=10
                  
    for i in  range(imWidth):
        for j in range(imHeight):
            index = imgCluster[i][j][0]
            if(index != -1 ):
                dis = GetDis(img[i][j], centerOfPic[index])
                disPro = dis/sumOfDis[index]
                disPro *= cnt
                ranNum = random.randint(0,100)
                ranNum /= 100
                #print(disPro,ranNum)
                if(disPro >= ranNum):
                    imgCluster[i][j][0] = -1
    
    
    #P3 交叉
    
    maxFitFunction = [0 for i in range(numOfClass)]
    averFitFunction = [0 for i in range(numOfClass)]
    numFitFunction = [1 for i in range(numOfClass)]
    
    for i in  range(imWidth):
        for j in range(imHeight):            
            index = imgCluster[i][j][0]
            if(index != -1 ):
                dis = GetDis(img[i][j], centerOfPic[index])
                maxFitFunction[index] = max(maxFitFunction[index],dis)
                averFitFunction[index] += dis
                numFitFunction[index] += 1
    
    for i in range(numOfClass):
        averFitFunction[i] /= numFitFunction[i]
    
    for i in  range(imWidth):
        for j in range(imHeight):
            index = imgCluster[i][j][0]
            if(index != -1 ):
                ranX = random.randint(0, imWidth) - 1
                ranY = random.randint(0, imHeight) - 1
                while(imgCluster[ranX][ranY][0] != index):
                    ranX = random.randint(0, imWidth) - 1
                    ranY = random.randint(0, imHeight) - 1
                
                anotherIndex = imgCluster[ranX][ranY][0]
                greaterFit = max(GetDis(img[i][j], centerOfPic[index]), GetDis(img[ranX][ranY], centerOfPic[anotherIndex]))
                if(greaterFit <= averFitFunction[index]):
                    uc = 1
                else:
                    uc = (maxFitFunction[index]-greaterFit)/(maxFitFunction[index]-averFitFunction[index])
                ran = random.randint(0,100)/100
                if(ran <= uc):
                    whichColor = random.randint(0, 2)
                    img[i][j][whichColor], img[ranX][ranY][whichColor] = img[ranX][ranY][whichColor], img[i][j][whichColor]
                    
    
    #P4 变异
    for i in  range(imWidth):
        for j in range(imHeight):
            index = imgCluster[i][j][0]
            if(index != -1 ):
                fit = GetDis(img[i][j], centerOfPic[index])
                
                if(fit <= averFitFunction[index]):
                    uc = 0.5
                else:
                    uc = 0.5*(maxFitFunction[index]-fit)/(maxFitFunction[index]-averFitFunction[index])
                ran = random.randint(0, 100000)/10
                if(ran <= uc):
                    whichColor = random.randint(0, 2)
                    #img[i][j][whichColor] = (img[i][j][whichColor] + random.randint(0,20))%255
                    img[i][j][whichColor] = 255 - img[i][j][whichColor]

#--2. 迭代




#3.--图像显示

for i in range(imWidth):
    for j in range(imHeight):
        disList = []
        for k in range(numOfClass): 
            dis = GetDis(copyImg[i][j], bestCenter[k])
            disList.append(dis)
        index = disList.index(min(disList))
        imgCluster[i][j] = index

for i in range(imWidth):
    for j in range(imHeight):
        index = imgCluster[i][j][0]
        img[i][j] = colorArray[index]
            
cv2.imshow('imshow',img)
cv2.imshow('im',copyImg)

cv2.waitKey(0)

cv2.destroyAllWindows()
            
#--3. 图像显示

print("All Done!")
print(id(centerOfPic), id(bestCenter))

三、应用:

本来说这个算法是用在遥感影像聚类上的,但好像效果并不怎么好,毕竟只是对灰度值进行聚类。

附赠一张跑了3个小时的花里胡哨图。

如果有什么需要交流的欢迎留言。

发布了34 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sinat_40471574/article/details/99465333