diff --git a/src/hyperspectral/hyperspectral/unmixing/rspa.py b/src/hyperspectral/hyperspectral/unmixing/rspa.py index a33d31f..bf113ac 100644 --- a/src/hyperspectral/hyperspectral/unmixing/rspa.py +++ b/src/hyperspectral/hyperspectral/unmixing/rspa.py @@ -3,39 +3,43 @@ import numpy as np def compute_alpha(x, y, β): - u = x / np.linalg.norm(x, 2) - assert np.linalg.norm(x, 2) > np.linalg.norm(y, 2), "x must be larger in norm than y" - num = (β * np.linalg.norm(x, 2)**2 - np.linalg.norm(y, 2)**2) + nx, ny = np.linalg.norm(x, 2), np.linalg.norm(y, 2) + u = x / nx + #assert nx > ny, "x must be larger in norm than y" + num = (β * nx**2 - ny**2) denom = (β * np.dot(u, x)**2 - np.dot(u, y)**2) - #print('Numerator: {}\nDenominator: {}'.format(num, denom)) return 1 - math.sqrt(1 - num / denom) -def select_key(spectra, d, p, β): +def select_key(R, d, p, β): try: from tqdm.autonotebook import trange except: trange = range - m = spectra.shape[1] - R = spectra + m = R.shape[1] Y = R - Py = np.eye(m) k = [] k1 = [] e = [] for i in trange(d, leave=False): k.append(np.argmax(np.linalg.norm(Y, 2, axis=1))) - u = spectra[k[i]] / np.linalg.norm(spectra[k[i]], 2) - R = spectra - np.einsum('n,m->nm',np.matmul(spectra, u), u) - e.append(np.sum(np.linalg.norm(R, 2, axis=1)**p)) - k1.append(np.argmax(np.linalg.norm(R, 2, axis=1))) - x = Y[k[i]] - y = Y[k1[i]] - #x = np.matmul(Py, spectra[k[i]]) - #y = np.matmul(Py, spectra[k1[i]]) - α = compute_alpha(x, y, β) - Y = Y - α * np.einsum('n,m->nm', np.matmul(Y, u), u) - #Py = np.matmul(np.eye(m) - α * np.outer(u, u), Py) + u = R[k[i]] / np.linalg.norm(R[k[i]], 2) + Ri = R - np.outer(np.matmul(R, u), u) + e.append(np.sum(np.linalg.norm(Ri, 2, axis=1)**(p/2))) + if i < d - 1: + uyi = Y[k[i]] / np.linalg.norm(Y[k[i]], 2) + Yi = Y - np.outer(np.matmul(Y, uyi), uyi) + normY = np.linalg.norm(Yi, 2, axis=1) + k1.append(np.argmax(normY)) + if normY[k1[i]] < 1e-12: + break + else: + x = Y[k[i]] + u = x / np.linalg.norm(x, 2) + y = Y[k1[i]] + α = compute_alpha(x, y, β) + assert α > 0 and α < 1, "α out of range (0,1)" + Y = Y - α * np.outer(np.matmul(Y, u), u) return k[np.argmin(e)] def rspa(image, n, d, β=4.0, p=1, tol=1e-8):