变化检测的基础算法与实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Rulixiang/article/details/78712993

变化检测(Change Detection)是指通过观察在不同的时间来识别对象的状态或现象的差异的过程,其研究目标可以大致总结为1)变化识别,2)变化预测,3)变化定量4)变化预测。在遥感领域,变化检测的应用十分广泛,也比较成熟。一般情况下,遥感影像数据的变化检测的流程大致如下:
① 首先是数据的预处理,包括对于遥感影像数据的空间配准、辐射纠正等。
② 然后是利用变化检测算法对于变化信息进行提取,例如图像代数法、分类后比较、主成分分析、以及变化向量分析等方法。
③ 评价变化检测的结果。


这里写图片描述

这是一般情况下遥感影像的变化检测流程图,对于一些具体情况可能会有变化。在这个过成中最主要的步骤应该是变化检测,下面是一些基本的的变化检测算法。

影像相减法(Univariate image differencing):
这是相对比较简单的一种检测算法,主要是将两个空间配准过的影像逐像素、逐波段相减,产生差值图像来代表变化,数学表达式:

 Dxkij=xkij(t2)xkij(t1)+C

这里  xkij 指的是图像第i行和j列,第k个波段对应的像素值,  t1  t2 分别是第一次和第二次采集影像的时间,C是一个常数,以保证差值结果为正。此外,会对  Dxkij 做一个阈值检测,大于一定阈值的被认为是发生了变化的区域,否则就认为没有发生变化。
这种方法过程十分简单,在变化检测领域也十分广泛,并且在多种地理环境下验证了效果。但也存在一些问题,例如对于配准的错误和混合的像素点十分敏感等。

影像回归法(Image regression)
在变化检测的回归中,t1和t2时间的像素值被认为是一个线性的函数,所以我们可以用最小方差回归的方法来回归两个时刻的影像,然后求得实际像素值和根据回归函数的像素值的差,判断是否出现了变化。

 Dxkij=x̅kij(t2)xkij(t1)

其中  x̅kij(t2) 是根据回归函数得到的  t2 时刻的预测值,此外,还会对  Dxkij 做一个阈值检测,大于一定阈值的被认为是发生了变化的区域,否则就认为没有发生变化。这种方法也是比较简单。并且有工作表明回归的方法在检测城市区域覆盖、热带雨林覆盖等方面比直接相减的方法要好。

影像比值法(Image ratioing)
在比值法中,两个配准过的图像进行对应像素点值相除,得到一个比值

 Rxkij=xkij(t1)xkij(t2)

然后根据比值判断对应的影像区域是否发生了变化,如果R的值和1相差比较大,则认为对应的区域发生了变化,否则R的值等于1或者和1相差不远则认为没有发生变化。该方法的关键是在表示变化像素值中选择适当的阈值。这种做法的优点是减少了太阳角度,光影和地形的影响。缺点是结果是非正态分布的,这点并不是很好。

植被指数差值法(Vegetation index differencing)
这种方法的主要做法是分别求取植被覆盖指数,然后将后面的时相数据的植被指数减去前面时相数据的植被指数。最常用的植被指数求法包括以下几种(已知波段2和波段4的值与绿叶植物数量显著相关):
①比值植被指数法

 I=band4band2

②归一植被指数法
 I=band4band2band4+band2

③改变植被指数法
 I=band4band2band4+band2+0.5

这些都是应用十分广泛的植被比值求法。这种方法的缺点在于加强了随机噪声等对于结果的影响。

主成分分析法
主成分分析方法是一种经典的特征提取方法,通过寻找到方差最大的正交投影空间来消除特征之间的相关性。在遥感影像中,这种方法用来减少光谱的数目,提取原始影像中占方差较大的主成分。具体的应用分为以下几类:
①PCA差值:对两幅遥感影像进行PCA,然后对包含主成分的波段进行差值比较;
②差值PCA:将两幅遥感影像计算变化向量的差值影像,然后对差值影像求PCA;
③联合PCA:将影像的各个波段叠加组成联合数据,共同进行PCA
④PCA回归:选取两幅影像中对应的两个波段组成二维数组,然后进行PCA,未变化的信息会在第一主成分中出现,变化的会在第二主成分中突出出来。

利用PCA的变化检测方法能够减少波段之间数据的冗余,突出那些造成变化的主成分。缺点在于:PCA是独立于场景的,因此变化检测的结果会很难理解和标注出来。

分类后比较法(Post-classification comparison)
这是最明显的变化检测方法,需要对于产生的分类图像进行比较,通过对于不同时段影像分类结果的比较得出变化图(能够反应完整的变化情况)。此外,对分类结果的选择性分组允许我们观察任何可能感兴趣的变化子集,分类后比较方法的流程图:


这里写图片描述

这种方法最终结果取决于两次分类的精度,每次0.8精度的分类结果会导致总的结果精度只有0.8*0.8=0.64.同时也需要大量时间的数据来获得分类结果。

变化向量检测法
变化向量检测方法CVA计算每个像素点各个波段的差值,能够产生两个输出:(1)光谱变化向量描述从第一到第二日期变化的方向和大小;以及(2)通过在n维空间中确定变化向量的欧氏距离,计算出每个像素点的总的变化幅度。

Dij=xij(t2)xij(t1)=x1ij(t2)x1ij(t1)x2ij(t2)x2ij(t1)xnij(t2)xnij(t1)

如下图是CVA的示意图,图中的向量代表某一个像素点的变化,向量的方向代表变化的方向,向量的长度代表变化的幅度。


这里写图片描述

变化向量的大小表示地物的变化强度,方向反映了变化类型。变化向量检测的方法还可以和PCA算法相结合,这种结合之后的方法已经被相关研究证实可以有效的检测和分类不同地面覆盖的变化。总的来说,这种方法的优点是能够处理任何数量的光谱波段,并产生详细的变化检测信息。缺点在于很难检测土地覆盖的变化轨迹。

背景相减法(Background subtraction
在两幅遥感影像中,那些保持不变或者变化很小的区域可以认为是整个影像的背景区域,在变化检测中,我们并不需要关心背景区域,所以我们可以通过将遥感影像减去背影图片的做法来得到发生了变化的区域。
这种方法的优点在于实现简单,而缺点在于精度比较低。

除了上述的几种变化检测方法之外,其他还有很多变化检测算法,这里不再总结。此外这里实现了影像差值法、PCA差值和差值PCA三种方法。

============================================================

实验过程:

影像差值法
影像差值法就是将两个遥感影像对应波段和像素位置相减,然后判断是否发生了变化,这要通过设定一个阈值来判断。设定阈值的方法可以通过  Kmeans 或者大津阈值(  OTSU ),这里实验采用的是大津阈值的方式。大津阈值的过程如下:
对于一个差值影像和一个阈值  th ,我们将小于它的像素(视为没有发生变化)数目占整个影响的比例为  ω0 ,像素的均值为  μ0 ;大于它的像素(视为发生了变化)数目占整个影响的比例为  ω1 ,像素的均值为  μ1 。那么对于整个影像的均值  μ ,就有:

 μ=ω0μ0+ω1μ1

对于发生了变化和没发生变化的类别之间的方差,可以得到:
 σ2=ω0(μ0μ)2+ω1(μ1μ)2=ω0ω1(μ0μ1)2

简单来说就是通过遍历得到使得类别之间方差最大的阈值。大津阈值的实现代码:


def Find_Threshold(delta):#OTSU寻找阈值
    val=np.zeros([256])
    for th in range(256):
        loc1=delta>th
        loc2=delta<=th
        '''delta[loc1]=255
        delta[loc2]=0'''
        if delta[loc1].size==0:
            mu1=0
            omega1=0
        else:
            mu1=np.mean(delta[loc1])
            omega1=delta[loc1].size/delta.size

        if delta[loc2].size==0:
            mu2=0
            omega2=0
        else:
            mu2=np.mean(delta[loc2])
            omega2=delta[loc2].size/delta.size
        val[th]=omega1*omega2*np.power((mu1-mu2),2)

    #print("val=",val.shape)
    plt.figure()
    loc=np.where(val==np.max(val))
    #x=np.arange(0,256,1)
    #x=x.reshape([1,256])
    plt.plot(val)
    plt.ylabel("Var")
    plt.xlabel("Threshold")
    plt.grid("on")

    print("\nThe best OTSU Threshold: ",loc[0])
    return loc[0]

影像差值法的实现代码:

def CD_diff(img1,img2):#影像差值法

    delta=np.subtract(img2,img1)
    #delta=np.abs(delta)
    #delta.min()
    sh=delta.shape
    delta+=np.abs(delta.min())
    th=Find_Threshold(delta)
    #print(delta.min())
    if np.size(th)>1:
        th=th[0]
    for i1 in range(sh[0]):
        for i2 in range(sh[1]):
            if delta[i1][i2]>=th:
                delta[i1][i2]=0
            else:
                delta[i1][i2]=255
    return delta

差值PCA法,主要过程是对差值图像进行主成分分析,实现代码:

ii=Img_PCA(CD_diff(img1,img2))

PCA差值法,主要过程是先进性PCA主成分提取再差值,实现代码:

ii=CD_diff(Img_PCA(img1),Img_PCA(img2))

其中  Img_PCA 函数是对一个二维图像进行主成分提取的函数,实现代码:

def Img_PCA(delta):
    U,S,V=np.linalg.svd(delta)
    SS=np.zeros(U.shape)
    for i in range(S.shape[0]):
        SS[i][i]=S[i]

    def Pick_k(S):
        sval=np.sum(S)
        for i in range(S.shape[0]):
            if np.sum(S[:i])>=0.6*sval:
                break
        return i+1

    k=Pick_k(S)
    print("\nNumber of vectors to reserve: k= ",k)
    Uk=U[:,0:k]
    Sk=SS[0:k,0:k]
    Vk=V[0:k,:]
    im=np.dot(np.dot(Uk,Sk),Vk)
   # im=np.dot(im,delta)
    return im

在误差评价部分,用的指标是检测率法。检测率法的大致过程:假设  NCC 是检测出来的变化像素数,  NRC 是真实变化像素的数目,  NNC 是未变化像素被检测为变化像素的数目,  NRN 为真实未变化像素的数目,  NCN 是漏检的变化像素的数目。则评价指标:

 RD=NCCNRC,RO=1RD,RC=NNCNRN

 ROE=RO+RC2

 RD,RC,RO,ROE 分别是检测率,误检率,漏检率和总体误差。最终各个方法的结果和总体误差如下图:


这里写图片描述

  检测率 漏检率 误检率 总体误差
影像差值法 80.809% 19.191% 19.740% 19.465%
差值PCA法 81.206% 18.794% 19.219% 18.389%
PCA差值法 78.348% 21.652% 14.653% 18.19%

图(a), (b)分别是时相1和时相2的数据图,(c)是实际的变化图,(d),(e),(f)分别是影像差值法、差值PCA、PCA差值的检测效果图。就总体误差而言,可以看到PCA差值法的检测效果最好,而利用了PCA的检测都比直接差值的方法误差要小。

============================================================
总结
完整的代码实现和图像数据请参考我的github

猜你喜欢

转载自blog.csdn.net/Rulixiang/article/details/78712993