一、 先放几张效果图:
二 、代码部分:
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个小时的花里胡哨图。
如果有什么需要交流的欢迎留言。