在高光谱图像中,VCA是一种常用的端元提取方法,算法来源:
“Vertex Component Analysis: A Fast Algorithm to Unmix Hyperspectral Data” submited to IEEE Trans. Geosci. Remote Sensing,2004
其python代码如下:
# -*- coding: utf-8 -*-
import sys
import scipy as sp
import scipy.linalg as splin
#############################################
# Internal functions
#############################################
def estimate_snr(Y,r_m,x):
[L, N] = Y.shape # L number of bands (channels), N number of pixels
[p, N] = x.shape # p number of endmembers (reduced dimension)
P_y = sp.sum(Y**2)/float(N)
P_x = sp.sum(x**2)/float(N) + sp.sum(r_m**2)
snr_est = 10*sp.log10( (P_x - p/L*P_y)/(P_y - P_x) )
return snr_est
def vca(Y,R,verbose = True,snr_input = 0):
# Vertex Component Analysis
#
# Ae, indice, Yp = vca(Y,R,verbose = True,snr_input = 0)
#
# ------- Input variables -------------
# Y - matrix with dimensions L(channels) x N(pixels)
# each pixel is a linear mixture of R endmembers
# signatures Y = M x s, where s = gamma x alfa
# gamma is a illumination perturbation factor and
# alfa are the abundance fractions of each endmember.
# R - positive integer number of endmembers in the scene
#
# ------- Output variables -----------
# Ae - estimated mixing matrix (endmembers signatures)
# indice - pixels that were chosen to be the most pure
# Yp - Data matrix Y projected.
#
# ------- Optional parameters---------
# snr_input - (float) signal to noise ratio (dB)
# v - [True | False]
# ------------------------------------
#
# Author: Adrien Lagrange ([email protected])
# This code is a translation of a matlab code provided by
# Jose Nascimento ([email protected]) and Jose Bioucas Dias ([email protected])
# available at http://www.lx.it.pt/~bioucas/code.htm under a non-specified Copyright (c)
# Translation of last version at 22-February-2018 (Matlab version 2.1 (7-May-2004))
#
# more details on:
# Jose M. P. Nascimento and Jose M. B. Dias
# "Vertex Component Analysis: A Fast Algorithm to Unmix Hyperspectral Data"
# submited to IEEE Trans. Geosci. Remote Sensing, vol. .., no. .., pp. .-., 2004
#
#
#############################################
# Initializations
#############################################
if len(Y.shape)!=2:
sys.exit('Input data must be of size L (number of bands i.e. channels) by N (number of pixels)')
[L, N]=Y.shape # L number of bands (channels), N number of pixels
R = int(R)
if (R<0 or R>L):
sys.exit('ENDMEMBER parameter must be integer between 1 and L')
#############################################
# SNR Estimates
#############################################
if snr_input==0:
y_m = sp.mean(Y,axis=1,keepdims=True)
Y_o = Y - y_m # data with zero-mean
Ud = splin.svd(sp.dot(Y_o,Y_o.T)/float(N))[0][:,:R] # computes the R-projection matrix
x_p = sp.dot(Ud.T, Y_o) # project the zero-mean data onto p-subspace
SNR = estimate_snr(Y,y_m,x_p);
if verbose:
print("SNR estimated = {}[dB]".format(SNR))
else:
SNR = snr_input
if verbose:
print("input SNR = {}[dB]\n".format(SNR))
SNR_th = 15 + 10*sp.log10(R)
#############################################
# Choosing Projective Projection or
# projection to p-1 subspace
#############################################
if SNR < SNR_th:
if verbose:
print("... Select proj. to R-1")
d = R-1
if snr_input==0: # it means that the projection is already computed
Ud = Ud[:,:d]
else:
y_m = sp.mean(Y,axis=1,keepdims=True)
Y_o = Y - y_m # data with zero-mean
Ud = splin.svd(sp.dot(Y_o,Y_o.T)/float(N))[0][:,:d] # computes the p-projection matrix
x_p = sp.dot(Ud.T,Y_o) # project thezeros mean data onto p-subspace
Yp = sp.dot(Ud,x_p[:d,:]) + y_m # again in dimension L
x = x_p[:d,:] # x_p = Ud.T * Y_o is on a R-dim subspace
c = sp.amax(sp.sum(x**2,axis=0))**0.5
y = sp.vstack(( x, c*sp.ones((1,N)) ))
else:
if verbose:
print("... Select the projective proj.")
d = R
Ud = splin.svd(sp.dot(Y,Y.T)/float(N))[0][:,:d] # computes the p-projection matrix
x_p = sp.dot(Ud.T,Y)
Yp = sp.dot(Ud,x_p[:d,:]) # again in dimension L (note that x_p has no null mean)
x = sp.dot(Ud.T,Y)
u = sp.mean(x,axis=1,keepdims=True) #equivalent to u = Ud.T * r_m
y = x / sp.dot(u.T,x)
#############################################
# VCA algorithm
#############################################
indice = sp.zeros((R),dtype=int)
A = sp.zeros((R,R))
A[-1,0] = 1
for i in range(R):
w = sp.random.rand(R,1);
f = w - sp.dot(A,sp.dot(splin.pinv(A),w))
f = f / splin.norm(f)
v = sp.dot(f.T,y)
indice[i] = sp.argmax(sp.absolute(v))
A[:,i] = y[:,indice[i]] # same as x(:,indice(i))
Ae = Yp[:,indice]
return Ae,indice,
其中,vca()参数共有四个,分别是Y、R、verbose以及snr_input,一般我们只输入Y和R:
提取后的返回值有两个:Ae、indice