欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

K-means算法实现遥感影像变化检测

程序员文章站 2024-01-15 23:52:16
...

K-means算法实现遥感影像变化检测
刚刚开始学习编程及遥感图像处理,这是第一篇用python实现算法,是CSDN中一位大佬帮我写的,现在放在这里仅供学习
K-means算法实现遥感影像变化检测
K-means算法实现遥感影像变化检测
K-means算法实现遥感影像变化检测

# SAR Image change detection by k-means algorithm
#author:**
#date:2020-07-08

'''-------------调用库-----------------------------------------------------------------------------'''

import matplotlib.pyplot as plt                 
import matplotlib.image as mpimg                
import numpy as np                              
import pandas as pd                        
import math                                    

'''-----------定义两图片取对数函数----------------------------------------------------------------'''

def lograte(img1,img2):                         
    [rows, cols, chls] = img1.shape           #把图片像素的行数,列数,通道数返回给rows,cols,chls
    rate_img = np.zeros([rows, cols, chls])   #初始化矩阵
    log_img = np.zeros([rows, cols, chls])      
    for i in range(rows):                     #遍历每一个像素
        for j in range(cols):
            for k in range(chls):                                          
                rate_img[i, j, k] = np.true_divide(img1[i, j, k]+0.1, img2[i, j, k]+0.1)  #两图像做除后将数据追加到初始化矩阵中-------->>为何要作除
                log_img[i, j, k] = abs(math.log(rate_img[i, j, k])) #差异图取对数后将数据追加到初始化矩阵中------------->>为何取对数
    return log_img                           #得到取对数后的变化检测差异图(矩阵)


'''--------调用K-means算法对提取到的变化信息分类并显示图片-----------------------------------------'''
'''需要完成任务:
①初始聚类中心的选择(2个)
②点与聚类中心的距离计算,后按最小距离聚类
③更新点与聚类中心距离和最小点
'''
def kmeans(log_img):                      
    [rows, cols, chls] = log_img.shape                  #初始化矩阵
    log_img_one = log_img[:,:,0]                        #通道数置为0
    pre_img = log_img_one.reshape((rows * cols, 1))     #压缩维度,变为rows * cols行,1列
    k=2                                                 #聚类中心个数
    list_img = []                                       #初始聚类中心列表
    while len(list_img) < k:                            #只选两个点后跳出
    #while list_img.__len__() < k:                      #__len__()可以返回容器中元素的个数.len是获取集合长度的函数,它通过调用对象的__len__方法来工作
        n = np.random.randint(0,  pre_img.shape[0],  1) #以1为步长,随机选取0到行数间的数据 .shape[0]为图像高度(矩阵行数)[1]为宽度(列数)[2]为通道数
        if n not in list_img:
            list_img.append(n[0])                       #选取初始聚类中
    pre_point = pre_img[np.array(list_img)]             #初始图像的初始聚类中心点(矩阵形式)


#①定义一个空列表
#②while循环,当列表里的个数等于给定的聚类中心时停止
#③从0到行数值之间以1为步长,随机选数字
#④如果不再列表中则加入
#⑤找到初始聚类点,跳出循环
#⑥至此,完成了初始聚类中心的选择
    c=0                       #定义迭代次数
    while True:                                         #一直循环,知道遇到break跳出
        distance = [np.sum(np.sqrt((pre_img - i) ** 2)   , axis=1)   for i in pre_point]#计算每个点与两聚类中心的距离之和
        now_point = np.argmin(distance, axis=0)         #距离之和最小的点为聚类中心(返回索引)
        now_piont_distance = np.array(  list([np.average(pre_img[now_point == i], axis=0) for i in range(k)])  )    
        c+=0
        if np.sum(now_piont_distance - pre_point) < 1e-5 or c>50:
            break           
        else:
            pre_point = now_piont_distance
#①欧氏距离的计算
#②将距离最小点选出
#③计算新选点距离,方便与前聚类中心比较
#④若聚类中心不再变化或者迭代次数大于50次跳出
#⑤差异信息的分类完成
    labels=now_point
    res = labels.reshape((rows, cols))
    ima = np.zeros([rows, cols, chls])   #初始化聚类中心
    ima[:, :, 0] = res                          
    ima[:, :, 1] = res
    ima[:, :, 2] = res                   #恢复三通道
    plt.title("K-means-Change Detection Results")       
    plt.imshow(ima)                                                                            
    plt.axis('off')                             
    plt.show()                                 

if __name__ == '__main__':
    img1 = mpimg.imread('1999.04.bmp')          
    img2 = mpimg.imread('1999.05.bmp')          
    dim = lograte(img1,img2)                    
    dim = (dim*255).astype(np.double)              
    kmeans(dim)