Samar-blog

导航

1.聚类生成候选样本(无监督)

1.1对影像做超像素分割

(1)代码如下:

点击查看代码
import numpy as np
import scipy.io as sio
from sklearn import preprocessing
from skimage.segmentation import slic, mark_boundaries
import math
from operator import truediv
import matplotlib.pyplot as plt
from matplotlib import cm
import sys
import spectral.io.envi as envi
import os  # 确保 os 库在这里导入

# --- 辅助函数 ---

def SegmentsLabelProcess(labels):
    '''
    对labels做后处理,防止出现label不连续现象
    '''
    labels = np.array(labels, np.int64)
    H, W = labels.shape
    ls = list(set(np.reshape(labels, [-1]).tolist()))

    dic = {}
    for i in range(len(ls)):
        dic[ls[i]] = i

    new_labels = labels
    for i in range(H):
        for j in range(W):
            new_labels[i, j] = dic[new_labels[i, j]]
    return new_labels


# --- 核心 SLIC 和特征提取类 ---

class SLIC_Processor(object):
    """
    负责执行 SLIC 超像素分割、计算光谱均值 (X_super) 和构建邻接矩阵 (A)。
    """

    def __init__(self, HSI, n_segments, compactness=20, max_iter=20, sigma=0, min_size_factor=0.3, max_size_factor=2):
        self.n_segments = n_segments
        self.compactness = compactness
        # self.max_iter = max_iter
        self.sigma = sigma
        self.min_size_factor = min_size_factor
        self.max_size_factor = max_size_factor

        # 数据standardization标准化
        height, width, bands = HSI.shape
        data = np.reshape(HSI, [height * width, bands])
        minMax = preprocessing.StandardScaler()
        data = minMax.fit_transform(data)
        self.data = np.reshape(data, [height, width, bands])
        self.segments = None
        self.superpixel_count = 0
        self.S = None  # 超像素光谱均值矩阵 (X_super)
        self.Q = None  # 分配矩阵

    def get_Xsuper_Q_Segments(self):
        """
        执行 SLIC 分割,并计算每个超像素块内的光谱平均值(S,即 X_super),
        以及像素到超像素的分配矩阵 Q。

        Returns:
            Q (np.ndarray): 分配矩阵,尺寸 (H*W, N_superpixels)
            S (np.ndarray): 超像素光谱均值矩阵 (X_super),尺寸 (N_superpixels, Bands)
            Segments (np.ndarray): 超像素分割图,尺寸 (H, W)
        """
        img = self.data
        (h, w, d) = img.shape

        # --- 1. 执行 SLIC 分割 ---
        # convert2lab=False: 避免将高光谱数据转换为3通道的L*a*b色彩空间
        segments = slic(img, n_segments=self.n_segments, compactness=self.compactness,
                        convert2lab=False, sigma=self.sigma,  # <--- max_iter 已被移除
                        enforce_connectivity=True, min_size_factor=self.min_size_factor,
                        max_size_factor=self.max_size_factor, slic_zero=False)

        # 确保超像素 label 连续
        if segments.max() + 1 != len(set(np.reshape(segments, [-1]).tolist())):
            segments = SegmentsLabelProcess(segments)

        self.segments = segments
        superpixel_count = segments.max() + 1
        self.superpixel_count = superpixel_count
        print(f"--- SLIC 分割完成 ---")
        print(f"目标超像素数量: {self.n_segments}, 实际超像素数量: {superpixel_count}")

        # 可选:显示超像素分割边界
        # out = mark_boundaries(img[:,:,[0,1,2]], segments)
        # plt.figure(figsize=(8,8))
        # plt.imshow(out)
        # plt.title(f"Superpixel Segmentation (N={superpixel_count})")
        # plt.show()

        # --- 2. 计算光谱均值 (S = X_super) 和 分配矩阵 (Q) ---

        segments_flat = np.reshape(segments, [-1])
        # S (X_super): 尺寸 (N_superpixels, Bands)
        S = np.zeros([superpixel_count, d], dtype=np.float32)
        # Q: 尺寸 (H*W, N_superpixels)
        Q = np.zeros([w * h, superpixel_count], dtype=np.float32)
        x_flat = np.reshape(img, [-1, d])

        for i in range(superpixel_count):
            idx = np.where(segments_flat == i)[0]
            count = len(idx)
            pixels = x_flat[idx]

            # 计算超像素块内的光谱平均值
            superpixel = np.sum(pixels, axis=0) / count
            S[i] = superpixel

            # 填充分配矩阵 Q
            Q[idx, i] = 1

        self.S = S
        self.Q = Q

        return Q, S, self.segments

    def get_A(self, sigma: float = 10.0):
        """
        根据超像素分割图 Segments 和光谱均值 S (X_super) 构建邻接矩阵 A。
        矩阵 A 的元素表示相邻超像素之间的光谱相似度。

        Parameters:
            sigma (float): 高斯核带宽参数,用于计算相似度权重。

        Returns:
            A (np.ndarray): 超像素邻接矩阵,尺寸 (N_superpixels, N_superpixels)
        """
        if self.segments is None or self.S is None:
            raise ValueError("必须先调用 get_Xsuper_Q_Segments() 方法完成分割和特征提取。")

        A = np.zeros([self.superpixel_count, self.superpixel_count], dtype=np.float32)
        (h, w) = self.segments.shape

        # 通过滑动窗口检测邻接关系
        for i in range(h - 1):  # 迭代到 h-2 即可,避免越界
            for j in range(w - 1):  # 迭代到 w-2 即可
                sub = self.segments[i:i + 2, j:j + 2]
                sub_unique = np.unique(sub)

                # 如果窗口内包含多个超像素 ID,则说明它们相邻
                if len(sub_unique) > 1:
                    # 获取相邻的超像素 ID
                    idx1 = sub_unique[0]
                    idx2 = sub_unique[1]

                    # 仅计算一次,避免重复计算
                    if A[idx1, idx2] == 0:
                        pix1 = self.S[idx1]
                        pix2 = self.S[idx2]

                        # 计算光谱相似度作为权重 (欧式距离的指数衰减)
                        diss = np.exp(-np.sum(np.square(pix1 - pix2)) / sigma ** 2)

                        A[idx1, idx2] = A[idx2, idx1] = diss

        return A


# --- 主执行函数(包含测试数据)---

def run_superpixel_processing(hsi_data, target_n_segments=10000, sigma_weight=10.0):
    """
    执行完整的超像素分割、特征提取和图结构构建流程。

    Args:
        hsi_data (np.ndarray): 待处理的高光谱数据,形状 (H, W, B)。
        target_n_segments (int): 目标分割的超像素数量。
        sigma_weight (float): 构建邻接矩阵时的相似度权重参数。

    Returns:
        tuple: 包含 (Q, X_super, A, Segments) 的元组
               Q: 分配矩阵 (H*W, N)
               X_super: 超像素光谱均值矩阵 (N, B)
               A: 邻接矩阵 (N, N)
               Segments: 超像素分割图 (H, W)
    """
    print(f"输入数据形状 (H, W, B): {hsi_data.shape}")

    # 初始化并执行 SLIC
    slic_processor = SLIC_Processor(
        HSI=hsi_data,
        n_segments=target_n_segments,
        compactness=1,  # 低紧凑度,更倾向于光谱相似性
        sigma=1,  # 空间平滑参数
        min_size_factor=0.1,
        max_size_factor=2
    )

    # 1. 超像素分割和光谱均值提取 (X_super)
    Q, X_super, Segments = slic_processor.get_Xsuper_Q_Segments()

    # 2. 邻接矩阵构建 (A)
    A = slic_processor.get_A(sigma=sigma_weight)

    print("\n--- 结果形状摘要 ---")
    print(f"最终超像素数量 (N): {X_super.shape[0]}")
    print(f"X_super 形状 (N, B): {X_super.shape}")
    print(f"Q 形状 (H*W, N): {Q.shape}")
    print(f"A 形状 (N, N): {A.shape}")
    print(f"Segments 形状 (H, W): {Segments.shape}")

    return Q, X_super, A, Segments

    # ... (所有函数和类定义,包括 run_superpixel_processing 结束) ...

    # ----------------------------------------------------
    # 仅保留一个顶层 if __name__ == '__main__': 块
    # ----------------------------------------------------

if __name__ == '__main__':
        # 1. 确定目标超像素数量
        TARGET_N_SUPERPIXELS = 10000

        # 2. 导入 ENVI 读取库和OS库


        # !!! 替换成您自己的文件路径 !!!
        IMAGE_HDR_PATH = r"D:\RS_DYL\s3_RPC\ZY1E_AHSI_E89.52_N39.27_20231119_021937_L1A0000680549_H1B_f_rpcortho.hdr"

        # 设置输出目录
        OUTPUT_DIR = r"D:\RS_DYL\Output_GCN_Features"

        # --- 数据加载 ---
        try:
            img = envi.open(IMAGE_HDR_PATH, IMAGE_HDR_PATH.replace('.hdr', '.dat'))
            hsi_data = img.open_memmap(writable=False).copy()
            print(f"成功加载影像。尺寸: {hsi_data.shape}")

        except FileNotFoundError as e:
            print(f"错误:无法找到文件 {IMAGE_HDR_PATH} 或其对应的 DAT 文件。")
            print(f"请检查文件路径是否正确。详细错误: {e}")
            exit()  # 找不到文件则退出

        # 检查尺寸是否一致
        H, W, B = hsi_data.shape
        if B != 166:
            print(f"警告:影像波段数 B={B},与预期 166 不同。")

        # --- 执行处理流程 ---
        Q_out, Xsuper_out, A_out, Segments_out = run_superpixel_processing(
            hsi_data,
            target_n_segments=TARGET_N_SUPERPIXELS
        )

        print("\n--- 处理完成!---")
        print("超像素光谱均值矩阵 X_super 已存储在变量 Xsuper_out 中。")

        # --- 结果保存 ---

        # 确保输出目录存在
        if not os.path.exists(OUTPUT_DIR):
            os.makedirs(OUTPUT_DIR)

        # 1. 保存为 MATLAB .mat 文件
        sio.savemat(
            os.path.join(OUTPUT_DIR, 'Xsuper_features.mat'),
            {'Xsuper': Xsuper_out}
        )
        sio.savemat(
            os.path.join(OUTPUT_DIR, 'A_adjacency_matrix.mat'),
            {'A_matrix': A_out}
        )
        sio.savemat(
            os.path.join(OUTPUT_DIR, 'Segments.mat'),
            {'Segments': Segments_out}
        )

        # 2. 保存为 NumPy .npy 文件 (更快的加载速度)
        np.save(os.path.join(OUTPUT_DIR, 'Xsuper_features.npy'), Xsuper_out)
        np.save(os.path.join(OUTPUT_DIR, 'A_adjacency_matrix.npy'), A_out)
        np.save(os.path.join(OUTPUT_DIR, 'Segments.npy'), Segments_out)  # 关键添加
        np.save(os.path.join(OUTPUT_DIR, 'Q_matrix.npy'), Q_out)  # 可选

        print(f"\n结果已成功保存到目录: {OUTPUT_DIR}")
        print("保存文件:")
        print(" - Xsuper_features.mat/npy (超像素光谱均值)")
        print(" - A_adjacency_matrix.mat/npy (邻接矩阵)")
        print(" - Segments.mat/npy (超像素分割图) ✅")
        print(" - Q_matrix.npy (分配矩阵,可选)")

(2)实现成果如下:

点击查看代码
C:\Users\Administrator\.conda\envs\hyspipeline\python.exe D:\RS_DYL\python\chaoxiangsu.py 
成功加载影像。尺寸: (2504, 2461, 166)
输入数据形状 (H, W, B): (2504, 2461, 166)
--- SLIC 分割完成 ---
目标超像素数量: 10000, 实际超像素数量: 9870

--- 结果形状摘要 ---
最终超像素数量 (N): 9870
X_super 形状 (N, B): (9870, 166)
Q 形状 (H*W, N): (6162344, 9870)
A 形状 (N, N): (9870, 9870)
Segments 形状 (H, W): (2504, 2461)

--- 处理完成!---
超像素光谱均值矩阵 X_super 已存储在变量 Xsuper_out 中。

(3)即保存了四份文件:

Xsuper_features.mat / Xsuper_features.npy (超像素光谱均值)
A_adjacency_matrix.mat / A_adjacency_matrix.npy (邻接矩阵)
Segments.npy (超像素分割图)
Q_out (分配矩阵)

2.HySime端元数目估计和VCA端元初始化

(1)代码分三部分

①vd.py
点击查看代码
"""
HfcVd function
"""

from __future__ import division

import numpy as np
import scipy as sp
import scipy.stats as ss

def est_noise(y, noise_type='additive'):
    """
    This function infers the noise in a
    hyperspectral data set, by assuming that the
    reflectance at a given band is well modelled
    by a linear regression on the remaining bands.

    Parameters:
        y: `numpy array`
            a HSI cube ((m*n) x p)

       noise_type: `string [optional 'additive'|'poisson']`

    Returns: `tuple numpy array, numpy array`
        * the noise estimates for every pixel (N x p)
        * the noise correlation matrix estimates (p x p)

    Copyright:
        Jose Nascimento (zen@isel.pt) and Jose Bioucas-Dias (bioucas@lx.it.pt)
        For any comments contact the authors
    """
    def est_additive_noise(r):
        small = 1e-6
        L, N = r.shape
        w=np.zeros((L,N), dtype=np.double)
        RR=np.dot(r,r.T)
        RRi = np.linalg.pinv(RR+small*np.eye(L))
        RRi = np.matrix(RRi)
        for i in range(L):
            XX = RRi - (RRi[:,i]*RRi[i,:]) / RRi[i,i]
            RRa = RR[:,i]
            RRa[i] = 0
            beta = np.dot(XX, RRa)
            beta[0,i]=0;
            w[i,:] = r[i,:] - np.dot(beta,r)
        Rw = np.diag(np.diag(np.dot(w,w.T) / N))
        return w, Rw

    y = y.T
    L, N = y.shape
    #verb = 'poisson'
    if noise_type == 'poisson':
        sqy = np.sqrt(y * (y > 0))
        u, Ru = est_additive_noise(sqy)
        x = (sqy - u)**2
        w = np.sqrt(x)*u*2
        Rw = np.dot(w,w.T) / N
    # additive
    else:
        w, Rw = est_additive_noise(y)
    return w.T, Rw.T


def hysime(y, n, Rn):
    """
    Hyperspectral signal subspace estimation

    Parameters:
        y: `numpy array`
            hyperspectral data set (each row is a pixel)
            with ((m*n) x p), where p is the number of bands
            and (m*n) the number of pixels.

        n: `numpy array`
            ((m*n) x p) matrix with the noise in each pixel.

        Rn: `numpy array`
            noise correlation matrix (p x p)

    Returns: `tuple integer, numpy array`
        * kf signal subspace dimension
        * Ek matrix which columns are the eigenvectors that span
          the signal subspace.

    Copyright:
        Jose Nascimento (zen@isel.pt) & Jose Bioucas-Dias (bioucas@lx.it.pt)
        For any comments contact the authors
    """
    y=y.T
    n=n.T
    Rn=Rn.T
    L, N = y.shape
    Ln, Nn = n.shape
    d1, d2 = Rn.shape

    x = y - n;

    Ry = np.dot(y, y.T) / N
    Rx = np.dot(x, x.T) / N
    E, dx, V = np.linalg.svd(Rx)

    Rn = Rn+np.sum(np.diag(Rx))/L/10**5 * np.eye(L)
    Py = np.diag(np.dot(E.T, np.dot(Ry,E)))
    Pn = np.diag(np.dot(E.T, np.dot(Rn,E)))
    cost_F = -Py + 2 * Pn
    kf = np.sum(cost_F < 0)
    ind_asc = np.argsort(cost_F)
    Ek = E[:, ind_asc[0:kf]]
    return kf, Ek # Ek.T ?


# Comments on using complex number:
#
# Use only scipy and numpy functions for a correct use of complex number.
#
# scipy.sqrt() deal by the book with complex number,
# it's more tricky when using math and numpy modules.
#


def HfcVd(M, far='default'):
    """
    Computes the vitual dimensionality (VD) measure for an HSI
    image for specified false alarm rates.  When no false alarm rate(s) is
    specificied, the following vector is used: 1e-3, 1e-4, 1e-5.
    This metric is used to estimate the number of materials in an HSI scene.

    Parameters:
       M: `numpy array`
           HSI data as a 2D matrix (N x p).

       far: `list [default default]`
           False alarm rate(s).

    Returns: python list
           VD measure, number of materials estimate.

    References:
        C.-I. Chang and Q. Du, "Estimation of number of spectrally distinct
        signal sources in hyperspectral imagery," IEEE Transactions on
        Geoscience and Remote Sensing, vol. 43, no. 3, mar 2004.

        J. Wang and C.-I. Chang, "Applications of independent component
        analysis in endmember extraction and abundance quantification for
        hyperspectral imagery," IEEE Transactions on Geoscience and Remote
        Sensing, vol. 44, no. 9, pp. 2601-1616, sep 2006.
    """
    N, numBands = M.shape

    # calculate eigenvalues of covariance and correlation between bands
    lambda_cov = np.linalg.eig(np.cov(M.T))[0] # octave: cov(M')
    lambda_corr = np.linalg.eig(np.corrcoef(M.T))[0] # octave: corrcoef(M')
    # not realy needed:
    lambda_cov = np.sort(lambda_cov)[::-1]
    lambda_corr = np.sort(lambda_corr)[::-1]

    if far == 'default':
        far = [10**-3, 10**-4, 10**-5]
    else:
        far = [far]

    numEndmembers_list = []
    for y in range(len(far)):
        numEndmembers = 0
        pf = far[y]
        for x in range(numBands):
            sigmaSquared = (2.*lambda_cov[x]/N) + (2.*lambda_corr[x]/N) + (2./N)*lambda_cov[x]*lambda_corr[x]
            sigma = sp.sqrt(sigmaSquared)
            tau = -ss.norm.ppf(pf, 0, abs(sigma))
            if (lambda_corr[x]-lambda_cov[x]) > tau:
                numEndmembers += 1
        numEndmembers_list.append(numEndmembers)
    return numEndmembers_list

②vd_int.py
点击查看代码

"""
HySime class
HfcVd class
"""

import numpy as np
# from pysptools.material_count.inval import CountInputValidation1, CountInputValidation2

# from . import vd
import vd
# from .inval import *


class HySime(object):
    """ Hyperspectral signal subspace identification by minimum error. """

    def __init__(self):
        self.kf = None
        self.Ek = None

    # @CountInputValidation1('HySime')
    def count(self, M):
        """
        Hyperspectral signal subspace estimation.

        Parameters:
            M: `numpy array`
                Hyperspectral data set (each row is a pixel)
                with ((m*n) x p), where p is the number of bands
                and (m*n) the number of pixels.

        Returns: `tuple integer, numpy array`
            * kf signal subspace dimension
            * Ek matrix which columns are the eigenvectors that span
              the signal subspace.

        Reference:
            Bioucas-Dias, Jose M., Nascimento, Jose M. P., 'Hyperspectral Subspace Identification',
            IEEE TRANSACTIONS ON GEOSCIENCE AND REMOTE SENSING, VOL. 46, NO. 8, AUGUST 2008.

        Copyright:
            Jose Nascimento (zen@isel.pt) & Jose Bioucas-Dias (bioucas@lx.it.pt)
            For any comments contact the authors.
        """
        h, w, numBands = M.shape
        Mr = np.reshape(M, (w*h, numBands))
        w, Rw = vd.est_noise(Mr)
        self.kf, self.Ek = vd.hysime(Mr, w, Rw)
        return self.kf, self.Ek


class HfcVd(object):
    """
    Computes the vitual dimensionality (VD) measure for an HSI
    image for specified false alarm rates.
    """

    def __init__(self):
        self.vd = None

    # @CountInputValidation2('HfcVd')
    def count(self, M, far='default', noise_whitening=False):
        """
        Computes the vitual dimensionality (VD) measure for an HSI
        image for specified false alarm rates.  When no false alarm rate(s) is
        specificied, the following vector is used: 1e-3, 1e-4, 1e-5.
        This metric is used to estimate the number of materials in an HSI scene.

        Parameters:
           M: `numpy array`
               HSI data as a 2D matrix (N x p).

           far: `list [default default]`
               False alarm rate(s).

           noise_whitening: `boolean [default False]`
               If True noise whitening is applied before calling HfcVd,
               doing a NWHFC.

        Returns: python list
               VD measure, number of materials estimate.

        References:
            C.-I. Chang and Q. Du, "Estimation of number of spectrally distinct
            signal sources in hyperspectral imagery," IEEE Transactions on
            Geoscience and Remote Sensing, vol. 43, no. 3, mar 2004.

            J. Wang and C.-I. Chang, "Applications of independent component
            analysis in endmember extraction and abundance quantification for
            hyperspectral imagery," IEEE Transactions on Geoscience and Remote
            Sensing, vol. 44, no. 9, pp. 2601-1616, sep 2006.
        """
        import pysptools.noise as ns
        h, w, numBands = M.shape
        Mr = np.reshape(M, (w*h, numBands))
        if noise_whitening == True:
            Mr = ns.whiten(Mr)
        self.vd = vd.HfcVd(Mr, far)
        return self.vd
③main.py
点击查看代码
import numpy as np
import scipy.io as sio
from sklearn import preprocessing
from skimage.segmentation import slic, mark_boundaries
import math
from operator import truediv
import matplotlib.pyplot as plt
from matplotlib import cm
import sys
import spectral.io.envi as envi
import os
from pathlib import Path
import warnings

# 忽略特定警告,保持输出清晰
warnings.filterwarnings('ignore', category=RuntimeWarning)
np.set_printoptions(precision=4, suppress=True)


# --- 辅助函数 (保持不变) ---

def SegmentsLabelProcess(labels):
    '''
    对labels做后处理,防止出现label不连续现象
    '''
    labels = np.array(labels, np.int64)
    H, W = labels.shape
    ls = list(set(np.reshape(labels, [-1]).tolist()))

    dic = {}
    for i in range(len(ls)):
        dic[ls[i]] = i

    new_labels = labels
    for i in range(H):
        for j in range(W):
            new_labels[i, j] = dic[new_labels[i, j]]
    return new_labels


# --- 改进的纯 NumPy 实现的 VCA ---
def vca_numpy(M, P):
    """
    改进的纯 NumPy 实现的 Vertex Component Analysis (VCA)
    增加了数值稳定性处理和错误恢复机制

    参数:
    M: 输入数据矩阵 (bands, pixels)
    P: 要提取的端元数量

    返回:
    endmembers: 端元矩阵 (bands, P)
    indices: 端元在原始数据中的索引 (P,)
    """
    bands, pixels = M.shape

    # 1. 数据预处理:处理NaN、Inf和常数波段
    M = np.nan_to_num(M, nan=0.0, posinf=0.0, neginf=0.0)

    # 检查并移除常数波段(标准差接近0)
    std_bands = np.std(M, axis=1)
    valid_band_mask = std_bands > 1e-8
    if not np.all(valid_band_mask):
        print(f"⚠️ 检测到 {np.sum(~valid_band_mask)} 个常数波段,已移除")
        M = M[valid_band_mask, :]
        original_bands = bands
        bands = np.sum(valid_band_mask)
        # 如果移除太多波段,使用原始数据尝试继续
        if bands < max(3, P):
            print(f"⚠️ 有效波段数量 ({bands}) 小于需要的端元数 ({P}),使用原始数据尝试")
            M = M  # 尝试使用原始数据
            bands = original_bands

    # 2. 数据中心化
    mean_vec = np.mean(M, axis=1, keepdims=True)
    M_centered = M - mean_vec

    # 3. SVD 分解 - 添加尝试/恢复机制
    try:
        # 尝试标准 SVD
        U, S, Vh = np.linalg.svd(M_centered, full_matrices=False)
        V = Vh.T
    except np.linalg.LinAlgError as e:
        print(f"⚠️ 标准 SVD 失败: {e},尝试使用截断 SVD")
        try:
            # 使用随机化 SVD 作为后备
            from sklearn.utils.extmath import randomized_svd
            U, S, Vh = randomized_svd(M_centered, n_components=min(50, min(M_centered.shape)))
            V = Vh.T
        except ImportError:
            print("⚠️ 无法导入 sklearn,尝试使用特征值分解")
            # 使用特征值分解作为最后手段
            cov_matrix = M_centered @ M_centered.T
            eigenvalues, eigenvectors = np.linalg.eigh(cov_matrix)
            # 按特征值大小排序
            idx = np.argsort(eigenvalues)[::-1]
            U = eigenvectors[:, idx]
            S = np.sqrt(np.abs(eigenvalues[idx]))

    U = U[:, :P]  # 保留前 P 个奇异向量

    # 4. 初始化
    indices = np.zeros(P, dtype=int)
    A = np.zeros((bands, P))

    # 5. 第一个端元:最大投影
    if U.shape[1] > 0:  # 确保有足够的奇异向量
        SNR = np.linalg.norm(U, axis=0)
        max_idx = np.argmax(SNR)
        indices[0] = max_idx
        A[:, 0] = M[:, max_idx]
    else:
        # 如果 U 为空,随机选择一个点
        max_idx = np.random.randint(0, pixels)
        indices[0] = max_idx
        A[:, 0] = M[:, max_idx]

    # 6. 剩余端元
    for i in range(1, min(P, bands)):  # 确保不超过波段数
        # 计算残差
        U_i = U[:, :i]
        proj = U_i @ (U_i.T @ M)
        residual = M - proj

        # 选择最大残差
        norms = np.linalg.norm(residual, axis=0)
        max_idx = np.argmax(norms)
        indices[i] = max_idx
        A[:, i] = M[:, max_idx]

        # 更新子空间
        try:
            U = np.linalg.qr(np.column_stack((U_i, M[:, max_idx])), mode='reduced')[0]
        except np.linalg.LinAlgError:
            print(f"⚠️ QR 分解在第 {i} 次迭代失败,使用前一次的 U")
            # 如果 QR 失败,使用前一次的 U

    # 7. 如果 P 大于 bands,填充剩余端元
    if P > bands:
        print(f"⚠️ 要求的端元数量 P={P} 大于波段数 {bands},只提取了 {bands} 个有效端元")
        # 复制最后一个端元填充
        for i in range(bands, P):
            A[:, i] = A[:, bands - 1]
            indices[i] = indices[bands - 1]

    return A, indices


# --- 改进的 HySime 实现 (纯 Python) ---
def hysime(Y, noise_sigma=None):
    """
    改进的纯 Python HySime 实现
    增加了数值稳定性处理和边界条件检查

    参数:
    Y: 输入数据 (pixels, bands)
    noise_sigma: 噪声标准差 (可选)

    返回:
    p: 估计的端元数量
    """
    pixels, bands = Y.shape

    # 1. 数据预处理:处理NaN、Inf
    Y = np.nan_to_num(Y, nan=0.0, posinf=0.0, neginf=0.0)

    # 2. 检查并处理常数波段
    std_bands = np.std(Y, axis=0)
    mean_bands = np.mean(Y, axis=0)

    # 创建波段掩码,移除标准差接近0的波段
    valid_band_mask = std_bands > 1e-8
    constant_bands = np.sum(~valid_band_mask)

    if constant_bands > 0:
        print(f"⚠️ 检测到 {constant_bands} 个常数波段")
        # 保留有效波段
        if np.sum(valid_band_mask) >= 3:  # 至少保留3个波段
            Y = Y[:, valid_band_mask]
            bands = np.sum(valid_band_mask)
            print(f"  使用 {bands} 个有效波段进行 HySime 估计")
        else:
            print("  有效波段太少,使用所有波段尝试继续")

    # 3. 安全的数据标准化
    std_bands = np.std(Y, axis=0)
    # 替换接近0的标准差,避免除以0
    safe_std = np.where(std_bands < 1e-8, 1.0, std_bands)
    Y_standardized = (Y - np.mean(Y, axis=0)) / safe_std

    # 4. 计算协方差矩阵
    R = np.cov(Y_standardized, rowvar=False)

    # 5. 特征分解 - 添加错误处理
    try:
        eigenvalues, _ = np.linalg.eigh(R)
        eigenvalues = np.flip(eigenvalues)  # 从大到小排序
    except np.linalg.LinAlgError:
        print("⚠️ 特征分解失败,使用经验方法估计端元数量")
        # 使用经验方法:取数据维度的10%作为估计
        p = max(3, min(20, int(0.1 * min(pixels, bands))))
        return p, None

    # 6. 估计噪声方差
    if noise_sigma is None:
        # 更稳健的噪声估计:使用最小20%的特征值
        noise_idx = max(3, int(0.2 * bands))
        noise_eigenvalues = eigenvalues[-noise_idx:]
        # 确保没有负值
        noise_eigenvalues = np.abs(noise_eigenvalues)
        noise_sigma = np.mean(noise_eigenvalues)
        print(f"  估计的噪声方差: {noise_sigma:.4f}")

    # 7. 计算信号子空间维数
    signal_eigenvalues = eigenvalues[eigenvalues > noise_sigma]
    p = len(signal_eigenvalues)

    # 8. 设置合理的边界
    min_p = 3  # 最小端元数量
    max_p = min(30, bands - 1)  # 最大端元数量

    if p < min_p:
        print(f"⚠️ 估计的端元数量 {p} 小于最小值 {min_p},使用 {min_p}")
        p = min_p
    elif p > max_p:
        print(f"⚠️ 估计的端元数量 {p} 大于最大值 {max_p},使用 {max_p}")
        p = max_p

    print(f"  有效特征值: {len(signal_eigenvalues)} / {bands}")
    print(f"  前10个特征值: {eigenvalues[:10]}")
    print(f"  噪声阈值: {noise_sigma:.4f}")

    return p, None


# --- 核心 SLIC 和特征提取类 (保持不变) ---

class SLIC_Processor(object):
    """
    负责执行 SLIC 超像素分割、计算光谱均值 (X_super) 和构建邻接矩阵 (A)。
    """

    def __init__(self, HSI, n_segments, compactness=20, max_iter=20, sigma=0, min_size_factor=0.3, max_size_factor=2):
        self.n_segments = n_segments
        self.compactness = compactness
        self.sigma = sigma
        self.min_size_factor = min_size_factor
        self.max_size_factor = max_size_factor

        # 数据standardization标准化
        height, width, bands = HSI.shape
        data = np.reshape(HSI, [height * width, bands])
        minMax = preprocessing.StandardScaler()
        data = minMax.fit_transform(data)
        self.data = np.reshape(data, [height, width, bands])
        self.segments = None
        self.superpixel_count = 0
        self.S = None  # 超像素光谱均值矩阵 (X_super)
        self.Q = None  # 分配矩阵

    def get_Xsuper_Q_Segments(self):
        """
        执行 SLIC 分割,并计算每个超像素块内的光谱平均值(S,即 X_super),
        以及像素到超像素的分配矩阵 Q。
        """
        img = self.data
        (h, w, d) = img.shape

        # --- 1. 执行 SLIC 分割 ---
        segments = slic(img, n_segments=self.n_segments, compactness=self.compactness,
                        convert2lab=False, sigma=self.sigma,
                        enforce_connectivity=True, min_size_factor=self.min_size_factor,
                        max_size_factor=self.max_size_factor, slic_zero=False)

        # 确保超像素 label 连续
        if segments.max() + 1 != len(set(np.reshape(segments, [-1]).tolist())):
            segments = SegmentsLabelProcess(segments)

        self.segments = segments
        superpixel_count = segments.max() + 1
        self.superpixel_count = superpixel_count
        print(f"--- SLIC 分割完成 ---")
        print(f"目标超像素数量: {self.n_segments}, 实际超像素数量: {superpixel_count}")

        # --- 2. 计算光谱均值 (S = X_super) 和 分配矩阵 (Q) ---

        segments_flat = np.reshape(segments, [-1])
        S = np.zeros([superpixel_count, d], dtype=np.float32)
        Q = np.zeros([w * h, superpixel_count], dtype=np.float32)
        x_flat = np.reshape(img, [-1, d])

        for i in range(superpixel_count):
            idx = np.where(segments_flat == i)[0]
            count = len(idx)
            pixels = x_flat[idx]

            superpixel = np.sum(pixels, axis=0) / count
            S[i] = superpixel

            Q[idx, i] = 1

        self.S = S
        self.Q = Q

        return Q, S, self.segments

    def get_A(self, sigma: float = 10.0):
        """
        根据超像素分割图 Segments 和光谱均值 S (X_super) 构建邻接矩阵 A。
        """
        if self.segments is None or self.S is None:
            raise ValueError("必须先调用 get_Xsuper_Q_Segments() 方法完成分割和特征提取。")

        A = np.zeros([self.superpixel_count, self.superpixel_count], dtype=np.float32)
        (h, w) = self.segments.shape

        for i in range(h - 1):
            for j in range(w - 1):
                sub = self.segments[i:i + 2, j:j + 2]
                sub_unique = np.unique(sub)

                if len(sub_unique) > 1:
                    idx1 = sub_unique[0]
                    idx2 = sub_unique[1]

                    if A[idx1, idx2] == 0:
                        pix1 = self.S[idx1]
                        pix2 = self.S[idx2]

                        diss = np.exp(-np.sum(np.square(pix1 - pix2)) / sigma ** 2)

                        A[idx1, idx2] = A[idx2, idx1] = diss

        return A


# --- 主执行函数(包含测试数据)---

def run_superpixel_processing(hsi_data, target_n_segments=10000, sigma_weight=10.0):
    """
    执行完整的超像素分割、特征提取和图结构构建流程。
    """
    print(f"输入数据形状 (H, W, B): {hsi_data.shape}")

    slic_processor = SLIC_Processor(
        HSI=hsi_data,
        n_segments=target_n_segments,
        compactness=1,
        sigma=1,
        min_size_factor=0.1,
        max_size_factor=2
    )

    Q, X_super, Segments = slic_processor.get_Xsuper_Q_Segments()
    A = slic_processor.get_A(sigma=sigma_weight)

    print("\n--- 结果形状摘要 ---")
    print(f"最终超像素数量 (N): {X_super.shape[0]}")
    print(f"X_super 形状 (N, B): {X_super.shape}")
    print(f"Q 形状 (H*W, N): {Q.shape}")
    print(f"A 形状 (N, N): {A.shape}")
    print(f"Segments 形状 (H, W): {Segments.shape}")

    return Q, X_super, A, Segments


# --- VCA 导入函数 (改进版) ---
def import_vca():
    """尝试导入 VCA 实现,优先使用 spectral,其次使用纯 NumPy 实现"""
    # 1. 尝试从 spectral 导入
    try:
        from spectral.algorithms.vca import vca
        print("✅ 使用 spectral 库的 VCA 实现")
        return vca
    except ImportError:
        pass

    # 2. 尝试从 spectral 主模块导入
    try:
        from spectral import vca
        print("✅ 使用 spectral 库的 VCA 实现 (备用路径)")
        return vca
    except ImportError:
        pass

    # 3. 使用纯 NumPy 实现
    print("🔧 使用改进的纯 NumPy 实现的 VCA (后备方案)")
    return vca_numpy


# --- 数据预处理函数 ---
def preprocess_for_vca(X_super):
    """
    为 VCA 准备数据,处理常见问题
    """
    # 1. 处理 NaN 和 Inf
    X_super = np.nan_to_num(X_super, nan=0.0, posinf=0.0, neginf=0.0)

    # 2. 检查数据范围
    min_val = np.min(X_super)
    max_val = np.max(X_super)
    mean_val = np.mean(X_super)
    std_val = np.std(X_super)

    print(f"  数据统计: min={min_val:.4f}, max={max_val:.4f}, mean={mean_val:.4f}, std={std_val:.4f}")

    # 3. 检查常数波段
    std_bands = np.std(X_super, axis=0)
    constant_bands = np.sum(std_bands < 1e-8)
    if constant_bands > 0:
        print(f"⚠️ 检测到 {constant_bands} 个常数波段")

    # 4. 数据标准化 (可选)
    # X_super = preprocessing.StandardScaler().fit_transform(X_super)

    return X_super


# --- 主程序 ---
if __name__ == '__main__':
    # 1. 确定目标超像素数量和路径
    TARGET_N_SUPERPIXELS = 10000
    IMAGE_HDR_PATH = r"D:\RS_DYL\s3_RPC\ZY1E_AHSI_E89.52_N39.27_20231119_021937_L1A0000680549_H1B_f_rpcortho.hdr"
    OUTPUT_DIR = Path(r"D:\RS_DYL\Output_GCN_Features")
    OUTPUT_DIR.mkdir(exist_ok=True)

    # 预期的保存文件路径
    XSUPER_NPY_PATH = OUTPUT_DIR / 'Xsuper_features.npy'
    A_NPY_PATH = OUTPUT_DIR / 'A_adjacency_matrix.npy'

    # =========================================================
    # --- 阶段 1: 数据加载或特征加载 ---
    # =========================================================

    if XSUPER_NPY_PATH.exists() and A_NPY_PATH.exists():
        print(f"✅ 检测到已保存的特征。从 {OUTPUT_DIR} 加载 X_super 和 A 矩阵。")
        Xsuper_out = np.load(XSUPER_NPY_PATH)
        A_out = np.load(A_NPY_PATH)

        # 仅为后续 HySime 步骤设置尺寸
        H, W, B = (0, 0, Xsuper_out.shape[1])  # H, W 不重要,但 B 必须设置
        N_super = Xsuper_out.shape[0]
        print(f"加载完成。X_super 形状: {Xsuper_out.shape}")

    else:
        print("❌ 未检测到已保存的超像素特征。开始执行 SLIC 分割和特征提取。")

        # --- 数据加载 ---
        try:
            img = envi.open(IMAGE_HDR_PATH, IMAGE_HDR_PATH.replace('.hdr', '.dat'))
            hsi_data = img.open_memmap(writable=False).copy()
            print(f"成功加载影像。尺寸: {hsi_data.shape}")

        except FileNotFoundError as e:
            print(f"错误:无法找到文件 {IMAGE_HDR_PATH} 或其对应的 DAT 文件。")
            print(f"请检查文件路径是否正确。详细错误: {e}")
            sys.exit(1)

        H, W, B = hsi_data.shape
        if B != 166:
            print(f"⚠️ 警告:影像波段数 B={B},与预期 166 不同。")

        # --- 执行超像素处理流程 ---
        Q_out, Xsuper_out, A_out, Segments_out = run_superpixel_processing(
            hsi_data,
            target_n_segments=TARGET_N_SUPERPIXELS
        )

        print("\n--- 超像素处理完成!---")

        # --- 结果保存 ---
        sio.savemat(OUTPUT_DIR / 'Xsuper_features.mat', {'Xsuper': Xsuper_out})
        sio.savemat(OUTPUT_DIR / 'A_adjacency_matrix.mat', {'A_matrix': A_out})
        np.save(XSUPER_NPY_PATH, Xsuper_out)
        np.save(A_NPY_PATH, A_out)
        print(f"超像素特征和邻接矩阵已保存到目录: {OUTPUT_DIR}")

        N_super = Xsuper_out.shape[0]

    # =========================================================
    # --- 阶段 2 & 3: HySime 估计端元数量 (P) 和 VCA 提取 ---
    # =========================================================

    X_super = Xsuper_out

    # 添加数据预处理
    print("\n--- 数据预处理 ---")
    X_super_processed = preprocess_for_vca(X_super)

    # 如果预处理后数据有变化,使用处理后的数据
    X_super = X_super_processed
    B = X_super.shape[1]  # 更新波段数

    # --- HySime 估计 P (使用改进的实现) ---
    print(f"\n--- 3.1. HySime 估计端元数量 ---")
    try:
        # 使用改进的 HySime 实现
        P_est, _ = hysime(X_super)
        P_est = int(P_est)
        print(f"✅ HySime 估计的端元数量 P: {P_est}")
    except Exception as e:
        print(f"⚠️ HySime 估计失败: {e}")
        # 使用基于数据维度的经验估计
        N_super = X_super.shape[0]
        B = X_super.shape[1]
        P_est = min(20, max(5, int(0.05 * min(N_super, B))))
        print(f"🔧 使用经验端元数量 P = {P_est} (基于数据维度)")

    # --- VCA 提取端元 ---
    print(f"\n--- 3.2. VCA 提取初始端元 ---")

    # 确保 P_est 在合理范围内
    min_p = 3
    max_p = min(30, B - 1)
    if P_est < min_p:
        print(f"⚠️ 估计的端元数量 {P_est} 小于最小值 {min_p},调整为 {min_p}")
        P_est = min_p
    elif P_est > max_p:
        print(f"⚠️ 估计的端元数量 {P_est} 大于最大值 {max_p},调整为 {max_p}")
        P_est = max_p

    # 导入 VCA 函数
    vca_func = import_vca()

    try:
        # 准备数据:VCA 期望输入是 (bands, pixels)
        data_for_vca = X_super.T  # 转置为 (bands, pixels)

        print(f"  VCA 输入数据形状: {data_for_vca.shape}")

        # 调用 VCA
        if vca_func == vca_numpy:
            endmembers_vca, indices = vca_numpy(data_for_vca, P_est)
        else:
            # 尝试使用 spectral 的 VCA
            endmembers_vca, indices = vca_func(data_for_vca, P_est)

        # 确保端元矩阵形状正确
        if endmembers_vca.shape[0] != B:
            if endmembers_vca.shape[1] == B:
                endmembers_vca = endmembers_vca.T
            else:
                # 尝试恢复
                actual_bands = endmembers_vca.shape[0]
                print(f"⚠️ 端元矩阵形状不匹配: 期望 {B} 波段,得到 {actual_bands} 波段")
                if actual_bands < B:
                    # 用零填充缺失波段
                    temp = np.zeros((B, P_est))
                    temp[:actual_bands, :] = endmembers_vca
                    endmembers_vca = temp
                else:
                    # 截断多余波段
                    endmembers_vca = endmembers_vca[:B, :]

        print(f"✅ VCA 成功提取 {P_est} 个初始端元。形状: {endmembers_vca.shape}")

        # --- 4. 保存 VCA 提取的端元 ---
        OUTPUT_FILE = OUTPUT_DIR / 'VCA_Endmembers.mat'
        sio.savemat(
            OUTPUT_FILE,
            {'Endmembers': endmembers_vca, 'P_est': P_est, 'Indices': indices}
        )
        print(f"VCA 端元和 P 值已保存到: {OUTPUT_FILE}")

    except Exception as e:
        print(f"❌ VCA 算法调用失败。错误: {e}")
        print("尝试使用改进的纯 NumPy 实现作为后备方案...")

        try:
            # 强制使用改进的纯 NumPy 实现
            endmembers_vca, indices = vca_numpy(X_super.T, P_est)

            # 确保形状正确
            if endmembers_vca.shape[0] != B:
                if endmembers_vca.shape[1] == B:
                    endmembers_vca = endmembers_vca.T

            # 保存结果
            OUTPUT_FILE = OUTPUT_DIR / 'VCA_Endmembers_backup.mat'
            sio.savemat(
                OUTPUT_FILE,
                {'Endmembers': endmembers_vca, 'P_est': P_est, 'Indices': indices}
            )
            print(f"✅ 使用改进的纯 NumPy 实现成功!结果已保存到: {OUTPUT_FILE}")

        except Exception as e2:
            print(f"❌ 改进的纯 NumPy 实现也失败: {e2}")
            print("📊 尝试提供数据诊断信息:")

            # 数据诊断
            print(f"  X_super 形状: {X_super.shape}")
            print(f"  X_super 数据类型: {X_super.dtype}")
            print(f"  X_super 的 min/max: {np.min(X_super):.4f}/{np.max(X_super):.4f}")
            print(f"  X_super 的 NaN 计数: {np.sum(np.isnan(X_super))}")
            print(f"  X_super 的 Inf 计数: {np.sum(np.isinf(X_super))}")

            # 波段标准差
            std_bands = np.std(X_super, axis=0)
            zero_std_count = np.sum(std_bands < 1e-8)
            print(f"  零标准差波段数量: {zero_std_count}")

            if zero_std_count > 0:
                print("💡 建议: 尝试移除零方差波段或使用数据预处理")

            # 尝试提取最小数量的端元
            min_p = min(3, B - 1)
            print(f"🔧 尝试使用最小端元数量 P={min_p} 重新运行...")

            try:
                endmembers_vca, indices = vca_numpy(X_super.T, min_p)
                OUTPUT_FILE = OUTPUT_DIR / 'VCA_Endmembers_emergency.mat'
                sio.savemat(
                    OUTPUT_FILE,
                    {'Endmembers': endmembers_vca, 'P_est': min_p, 'Indices': indices}
                )
                print(f"✅ 紧急模式成功!结果已保存到: {OUTPUT_FILE}")
            except Exception as e3:
                print(f"❌ 紧急模式也失败: {e3}")
                print("无法提取端元。请检查输入数据质量和预处理步骤。")
                sys.exit(1)

(2)运行成果

点击查看代码
C:\Users\Administrator\.conda\envs\hyspipeline\python.exe D:\RS_DYL\python\HySime\main.py 
✅ 检测到已保存的特征。从 D:\RS_DYL\Output_GCN_Features 加载 X_super 和 A 矩阵。
加载完成。X_super 形状: (9870, 166)

--- 数据预处理 ---
  数据统计: min=-2.5395, max=3.1195, mean=0.0100, std=0.9647
⚠️ 检测到 7 个常数波段

--- 3.1. HySime 估计端元数量 ---
⚠️ 检测到 7 个常数波段
  使用 159 个有效波段进行 HySime 估计
  估计的噪声方差: 0.0000
⚠️ 估计的端元数量 141 大于最大值 30,使用 30
  有效特征值: 141 / 159
  前10个特征值: [156.365    1.2957   0.8364   0.2354   0.2163   0.0292   0.0144   0.0084
   0.0055   0.0041]
  噪声阈值: 0.0000
✅ HySime 估计的端元数量 P: 30

--- 3.2. VCA 提取初始端元 ---
🔧 使用改进的纯 NumPy 实现的 VCA (后备方案)
  VCA 输入数据形状: (166, 9870)
⚠️ 检测到 7 个常数波段,已移除
⚠️ 端元矩阵形状不匹配: 期望 166 波段,得到 159 波段
✅ VCA 成功提取 30 个初始端元。形状: (166, 30)
VCA 端元和 P 值已保存到: D:\RS_DYL\Output_GCN_Features\VCA_Endmembers.mat

进程已结束,退出代码为 0

3.CyCUnet算法进行解混

(1)cycunet_png.py代码如下

点击查看代码
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.optim import lr_scheduler
import scipy.io as sio
import numpy as np
import os
import random
from pathlib import Path
import time
import matplotlib.pyplot as plt
from matplotlib import cm

# 设置和配置
seed = 1
random.seed(seed)
torch.manual_seed(seed)
np.random.seed(seed)
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"

# --- 2. 加载超像素数据 ---
OUTPUT_DIR = Path(r"D:\RS_DYL\Output_GCN_Features")
XSUPER_NPY_PATH = OUTPUT_DIR / 'Xsuper_features.npy'
VCA_MAT_PATH = OUTPUT_DIR / 'VCA_Endmembers.mat'

# 加载超像素数据
if not XSUPER_NPY_PATH.exists():
    raise FileNotFoundError("未找到超像素特征文件。请确保上一步已成功运行并保存。")

X_super_np = np.load(XSUPER_NPY_PATH).astype(np.float32)

# 加载VCA端元
if VCA_MAT_PATH.exists():
    vca_data = sio.loadmat(VCA_MAT_PATH)
    E_VCA_np = vca_data['Endmembers'].astype(np.float32)  # 形状可能是 (Bands, P) 或 (P, Bands)
    print(f"✅ 使用VCA优化的端元,形状: {E_VCA_np.shape}")
else:
    # 如果没有VCA结果,使用随机初始化
    print("⚠️ 未找到VCA端元文件,将使用随机初始化端元")
    N_super, B = X_super_np.shape
    P = 10  # 默认端元数量
    E_VCA_np = np.random.rand(B, P).astype(np.float32)

# --- 3. 确定关键参数 ---
N_super, B = X_super_np.shape  # N_super: 超像素数量, B: 波段数

# 确认VCA端元形状:应该为 (Bands, P)
if E_VCA_np.shape[0] == B:
    P = E_VCA_np.shape[1]  # (B, P)
elif E_VCA_np.shape[1] == B:
    E_VCA_np = E_VCA_np.T  # 转置为 (B, P)
    P = E_VCA_np.shape[1]
else:
    # 无法匹配波段数,使用默认值
    print(f"⚠️ VCA端元波段数不匹配 (期望: {B}, 实际: {E_VCA_np.shape[0]} 或 {E_VCA_np.shape[1]})")
    P = min(10, B - 1)  # 默认端元数
    E_VCA_np = np.random.rand(B, P).astype(np.float32)
    print(f"  使用随机初始化端元,P={P}")

print(f"数据维度: 超像素数={N_super}, 波段数={B}, 端元数={P}")

# 训练参数
LR, EPOCH, batch_size = 8e-3, 70, 1
beta, delta, gamma = 0.5, 1e-2, 1e-7
sparse_decay, weight_decay_param = 0, 0  # 注意:sparse_decay=0 会导致返回 float 0.0

# --- 4. 数据预处理和维度适配 ---
# X_super_np 形状: (N_super, B)
# 转换为网络输入格式: (1, B, 1, N_super)
Y_tensor = torch.from_numpy(X_super_np.T).unsqueeze(0).unsqueeze(2).float().to(device)
print(f"网络输入形状: {Y_tensor.shape} (期望: [batch, bands, height, width] = [1, {B}, 1, {N_super}])")

# VCA 初始化端元 (Bands, P)
E_VCA_init = torch.from_numpy(E_VCA_np).float().to(device)


# --- 5. 定义损失函数和工具类 ---

def Nuclear_norm_adapted(inputs):
    """计算输入丰度矩阵的核范数"""
    # inputs 形状: (1, P, 1, N_super) -> 我们需要 (P, N_super)
    _, P_dim, _, N_dim = inputs.shape
    input_2d = torch.reshape(inputs.squeeze(0).squeeze(1), (P_dim, N_dim))

    # 计算核范数 (奇异值之和)
    try:
        s = torch.linalg.svdvals(input_2d)
        out = torch.sum(s)
    except:
        out = torch.linalg.norm(input_2d, ord='nuc')
    return out


class SparseKLloss(nn.Module):
    def __init__(self, device):
        super(SparseKLloss, self).__init__()
        self.device = device

    def __call__(self, input, decay=sparse_decay):
        if decay <= 0:
            # 返回零张量而不是 Python float
            return torch.tensor(0.0, device=self.device)
        loss = Nuclear_norm_adapted(input)
        return decay * loss


class SumToOneLoss(nn.Module):
    def __init__(self, device):
        super(SumToOneLoss, self).__init__()
        self.register_buffer('one', torch.tensor(1.0, dtype=torch.float, device=device))
        self.loss = nn.L1Loss(reduction='mean')
        self.device = device

    def __call__(self, input, gamma_reg=gamma):
        """
        input: 丰度估计,形状 (1, P, 1, N_super)
        确保每个像素位置 (1, N_super) 的所有端元丰度和为1
        """
        # 在 P 维度 (第1维) 求和
        input_sum = torch.sum(input, dim=1, keepdim=True)  # (1, 1, 1, N_super)
        target_tensor = self.one.expand_as(input_sum)
        loss = self.loss(input_sum, target_tensor)
        return gamma_reg * loss


class NonZeroClipper(object):
    """确保权重非负,防止数值不稳定"""

    def __call__(self, module):
        if hasattr(module, 'weight'):
            w = module.weight.data
            w.clamp_(min=1e-6)  # 确保大于0


# --- 6. CAE 模型定义 ---

class AutoEncoder(nn.Module):
    def __init__(self, input_bands, num_endmembers):
        """
        input_bands: 输入波段数 B
        num_endmembers: 端元数量 P
        """
        super(AutoEncoder, self).__init__()
        self.input_bands = input_bands
        self.num_endmembers = num_endmembers

        # 编码器:从光谱到丰度
        self.encoder = nn.Sequential(
            nn.Conv2d(input_bands, 128, kernel_size=(1, 1), stride=1, padding=0),
            nn.BatchNorm2d(128, momentum=0.9),
            nn.Dropout(0.5),
            nn.ReLU(),
            nn.Conv2d(128, 64, kernel_size=(1, 1), stride=1, padding=0),
            nn.BatchNorm2d(64, momentum=0.9),
            nn.ReLU(),
            nn.Conv2d(64, num_endmembers, kernel_size=(1, 1), stride=1, padding=0),
            nn.BatchNorm2d(num_endmembers, momentum=0.9),
        )

        # 解码器1:从丰度到重建光谱
        self.decoder1 = nn.Sequential(
            nn.Conv2d(num_endmembers, input_bands, kernel_size=1, stride=1, bias=False),
            nn.ReLU(),
        )

        # 解码器2:循环一致性
        self.decoder2 = nn.Sequential(
            nn.Conv2d(num_endmembers, input_bands, kernel_size=1, stride=1, bias=False),
            nn.ReLU(),
        )

    def forward(self, x):
        """
        x: 输入光谱,形状 (batch_size, B, 1, N_super)
        返回: 丰度估计1, 重建光谱1, 丰度估计2, 重建光谱2
        """
        # 第一阶段
        abu_est1 = self.encoder(x)  # (batch_size, P, 1, N_super)
        abu_est1 = torch.clamp(abu_est1, min=0, max=1)  # 非负约束

        re_result1 = self.decoder1(abu_est1)  # (batch_size, B, 1, N_super)

        # 第二阶段 (循环一致性)
        abu_est2 = self.encoder(re_result1)  # (batch_size, P, 1, N_super)
        abu_est2 = torch.clamp(abu_est2, min=0, max=1)

        re_result2 = self.decoder2(abu_est2)  # (batch_size, B, 1, N_super)

        return abu_est1, re_result1, abu_est2, re_result2


# --- 7. 模型初始化和训练设置 ---

def weights_init(m):
    """初始化网络权重"""
    if isinstance(m, nn.Conv2d):
        nn.init.kaiming_normal_(m.weight.data)
        if m.bias is not None:
            nn.init.constant_(m.bias.data, 0)


# 初始化模型
net = AutoEncoder(input_bands=B, num_endmembers=P).to(device)
net.apply(weights_init)

# 端元初始化
model_dict = net.state_dict()
# 端元 E 形状是 (Bands, P),Conv2d 权重形状是 (Out_channels, In_channels, H, W) = (B, P, 1, 1)
model_dict['decoder1.0.weight'] = E_VCA_init.unsqueeze(2).unsqueeze(3)  # (B, P) -> (B, P, 1, 1)
model_dict['decoder2.0.weight'] = E_VCA_init.unsqueeze(2).unsqueeze(3)  # 共享初始端元
net.load_state_dict(model_dict)

# 损失函数和优化器 - 注意传递 device 参数
criterionSumToOne = SumToOneLoss(device=device)
criterionSparse = SparseKLloss(device=device)
loss_func = nn.MSELoss(reduction='mean')
optimizer = torch.optim.Adam(net.parameters(), lr=LR, weight_decay=weight_decay_param)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=15, gamma=0.8)
apply_clamp_inst1 = NonZeroClipper()

# --- 8. 训练循环 (简化,不使用 DataLoader) ---

time_start = time.time()

for epoch in range(EPOCH):
    net.train()

    # 前向传播
    abu_est1, re_result1, abu_est2, re_result2 = net(Y_tensor)

    # 损失计算
    loss_sumtoone = criterionSumToOne(abu_est1) + criterionSumToOne(abu_est2)
    loss_sparse = criterionSparse(abu_est1) + criterionSparse(abu_est2)

    # 重构损失
    loss_re1 = loss_func(re_result1, Y_tensor)
    loss_re2 = loss_func(re_result2, Y_tensor)
    loss_re = beta * loss_re1 + (1 - beta) * loss_re2

    # 丰度一致性损失
    loss_abu = delta * loss_func(abu_est1, abu_est2)

    # 总损失
    total_loss = loss_re + loss_abu + loss_sumtoone + loss_sparse

    # 反向传播
    optimizer.zero_grad()
    total_loss.backward()
    nn.utils.clip_grad_norm_(net.parameters(), max_norm=10, norm_type=2)  # L2裁剪
    optimizer.step()

    # 约束:端元非负
    net.decoder1.apply(apply_clamp_inst1)
    net.decoder2.apply(apply_clamp_inst1)

    # 打印日志
    if epoch % 5 == 0 or epoch == EPOCH - 1:
        # 确保所有损失值都可以调用 .item()
        total_loss_val = total_loss.item() if hasattr(total_loss, 'item') else total_loss
        loss_re_val = loss_re.item() if hasattr(loss_re, 'item') else loss_re
        loss_abu_val = loss_abu.item() if hasattr(loss_abu, 'item') else loss_abu
        loss_sumtoone_val = loss_sumtoone.item() if hasattr(loss_sumtoone, 'item') else loss_sumtoone
        loss_sparse_val = loss_sparse.item() if hasattr(loss_sparse, 'item') else loss_sparse

        print(f'Epoch: {epoch:3d}/{EPOCH} | '
              f'Total Loss: {total_loss_val:.6f} | '
              f'Recon Loss: {loss_re_val:.6f} | '
              f'Abu Consist: {loss_abu_val:.6f} | '
              f'SumToOne: {loss_sumtoone_val:.6f} | '
              f'Sparse: {loss_sparse_val:.6f}')

    # 学习率调度 (在每个 epoch 后)
    scheduler.step()

# 训练完成
time_end = time.time()
training_time = time_end - time_start
print(f'✅ 训练完成!总耗时: {training_time:.2f} 秒')

# --- 9. 结果提取和保存 ---
net.eval()
with torch.no_grad():
    abu_est1, _, _, _ = net(Y_tensor)

    # 归一化:确保每个位置的丰度和为1
    abu_est1 = abu_est1 / (torch.sum(abu_est1, dim=1, keepdim=True) + 1e-8)

    # 提取丰度图: (1, P, 1, N_super) -> (N_super, P)
    abu_est_final = abu_est1.squeeze(0).squeeze(1).T.cpu().numpy()  # (N_super, P)

    # 提取学习到的端元: (B, P, 1, 1) -> (P, B)
    M_learned = net.decoder1[0].weight.data.squeeze().cpu().numpy().T  # (P, B)

print('**********************************')
print('解混完成.')
print(f'最终丰度图形状 (N_super, P): {abu_est_final.shape}')
print(f'学习到的端元形状 (P, B): {M_learned.shape}')
print(f'训练总耗时: {training_time:.2f} 秒')

# --- 10. 保存结果 ---
save_path = OUTPUT_DIR / 'CyCUnet_Superpixel_Result.mat'
sio.savemat(
    str(save_path),
    {
        'X_super': X_super_np,
        'Abundance_map': abu_est_final,
        'Endmembers_learned': M_learned,
        'P': P,
        'training_time': training_time,
        'B': B,
        'N_super': N_super
    }
)
print(f'✅ 结果已保存到: {save_path}')


def visualize_abundance_map(output_dir, n_super, p_endmembers):
    """
    加载解混结果和 Segments 矩阵,并重建和绘制丰度图。

    参数:
    output_dir: Path 对象,结果保存目录。
    n_super: int, 超像素数量 (N_super)。
    p_endmembers: int, 端元数量 (P)。
    """

    # 结果文件路径
    result_path = output_dir / 'CyCUnet_Superpixel_Result.mat'
    segments_npy_path = output_dir / 'Segments.npy'  # 假设 Segments 存为 numpy 文件
    segments_mat_path = output_dir / 'Segments.mat'  # 假设 Segments 存为 mat 文件

    # 1. 加载解混结果 (丰度图)
    try:
        results = sio.loadmat(str(result_path))
        abu_est_final = results['Abundance_map']  # 形状: (N_super, P)
    except FileNotFoundError:
        print(f"❌ 错误:未找到解混结果文件: {result_path}")
        return

    # 2. 尝试加载 Segments 矩阵
    segments = None
    if segments_npy_path.exists():
        segments = np.load(segments_npy_path)
        print(f"✅ 加载 Segments 矩阵: {segments_npy_path}")
    elif segments_mat_path.exists():
        # 假设 mat 文件中键名为 'Segments' 或 'Segments_out'
        mat_data = sio.loadmat(str(segments_mat_path))
        if 'Segments' in mat_data:
            segments = mat_data['Segments']
        elif 'Segments_out' in mat_data:
            segments = mat_data['Segments_out']
        else:
            print(f"⚠️ 警告:Segments 文件 {segments_mat_path} 中未找到 'Segments' 或 'Segments_out' 键。")
            return
        print(f"✅ 加载 Segments 矩阵: {segments_mat_path}")
    else:
        print("❌ 错误:未找到 Segments 矩阵文件 (Segments.npy 或 Segments.mat)。")
        print("请手动确保在第一步超像素处理时保存了 Segments 矩阵。")
        return

    H, W = segments.shape
    print(f"原始图像尺寸 H={H}, W={W}")

    # 3. 重建丰度图像 (H, W, P)
    Abu_image = np.zeros((H, W, p_endmembers), dtype=np.float32)

    # 遍历每个超像素
    for i in range(n_super):
        # 找到属于超像素 i 的所有像素的坐标
        pixel_indices = np.where(segments == i)

        # 将超像素 i 的丰度值赋给所有属于它的像素
        Abu_image[pixel_indices] = abu_est_final[i, :]

    # 4. 绘图
    plt.figure(figsize=(15, 6))
    plt.suptitle(f"CyCUnet Superpixel Abundance Maps ({H}x{W} Reconstructed)")

    # 最多绘制前 P 个丰度图
    plot_rows = 2
    plot_cols = int(np.ceil(p_endmembers / plot_rows))

    # 限制绘制的子图数量
    max_plots = min(p_endmembers, plot_rows * plot_cols)

    for i in range(max_plots):
        ax = plt.subplot(plot_rows, plot_cols, i + 1)

        # 绘制第 i 个端元的丰度图
        im = ax.imshow(Abu_image[:, :, i], cmap='jet', vmin=0, vmax=1)
        ax.set_title(f'Endmember {i + 1}')
        ax.axis('off')

        # 添加颜色条(只对第一个图添加,节省空间)
        if i == 0:
            cbar = plt.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
            cbar.set_label('Abundance Value')

    plt.tight_layout(rect=[0, 0.03, 1, 0.95])  # 调整布局以适应suptitle
    plt.show()


# --- 调用可视化函数 ---
# 确保在上面的代码中已经设置了 N_super, P
if 'N_super' in locals() and 'P' in locals() and 'OUTPUT_DIR' in locals():
    visualize_abundance_map(OUTPUT_DIR, N_super, P)
else:
    print("无法自动调用可视化函数,请确保 N_super 和 P 变量已定义。")

# --- 11. 可选:可视化丰度图 (如果需要) ---
# 注意:这需要 Segments 矩阵将超像素映射回原始空间
try:
    SEGMENTS_PATH = OUTPUT_DIR / 'Segments.npy'
    if SEGMENTS_PATH.exists():
        segments = np.load(SEGMENTS_PATH)
        H, W = segments.shape
        print(f'检测到 Segments 矩阵,形状: ({H}, {W})')

        # 重建空间丰度图
        abundance_maps = np.zeros((H, W, P))
        for i in range(N_super):
            abundance_maps[segments == i] = abu_est_final[i]

        print(f'成功重建空间丰度图,形状: ({H}, {W}, {P})')

        # 保存空间丰度图
        sio.savemat(OUTPUT_DIR / 'Spatial_Abundance_Maps.mat', {'Abundance_maps': abundance_maps})
        print(f'空间丰度图已保存到: {OUTPUT_DIR / "Spatial_Abundance_Maps.mat"}')

        # 简单可视化
        try:
            # 创建图像
            fig, axes = plt.subplots(1, min(5, P), figsize=(15, 3))
            if P == 1:
                axes = [axes]

            for i in range(min(5, P)):
                im = axes[i].imshow(abundance_maps[:, :, i], cmap='jet')
                axes[i].set_title(f'Endmember {i + 1}')
                axes[i].axis('off')
                fig.colorbar(im, ax=axes[i], fraction=0.046, pad=0.04)

            plt.tight_layout()
            plt.savefig(OUTPUT_DIR / 'Abundance_Maps_Visualization.png', dpi=300, bbox_inches='tight')
            print(f'丰度图可视化已保存到: {OUTPUT_DIR / "Abundance_Maps_Visualization.png"}')
            plt.close()

        except Exception as e:
            print(f"可视化时出错: {e}")
    else:
        print("提示: 未找到 Segments.npy,无法重建空间丰度图。如需可视化,请确保在超像素处理阶段保存了Segments矩阵。")
except Exception as e:
    print(f"处理空间丰度图时出错: {e}")

print("程序执行完毕!")

(2)实现成果

①运行五个小时卡住了:
点击查看代码
C:\Users\Administrator\.conda\envs\hyspipeline\python.exe D:\RS_DYL\python\cycunet_pny.py 
✅ 使用VCA优化的端元,形状: (166, 30)
数据维度: 超像素数=9870, 波段数=166, 端元数=30
网络输入形状: torch.Size([1, 166, 1, 9870]) (期望: [batch, bands, height, width] = [1, 166, 1, 9870])
Epoch:   0/70 | Total Loss: 13.739389 | Recon Loss: 13.736471 | Abu Consist: 0.002917 | SumToOne: 0.000002 | Sparse: 0.000000
Epoch:   5/70 | Total Loss: 16.892550 | Recon Loss: 16.890717 | Abu Consist: 0.001830 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  10/70 | Total Loss: 9.971375 | Recon Loss: 9.969975 | Abu Consist: 0.001399 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  15/70 | Total Loss: 5.826466 | Recon Loss: 5.825325 | Abu Consist: 0.001140 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  20/70 | Total Loss: 3.885312 | Recon Loss: 3.884359 | Abu Consist: 0.000953 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  25/70 | Total Loss: 2.589013 | Recon Loss: 2.588233 | Abu Consist: 0.000780 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  30/70 | Total Loss: 1.709771 | Recon Loss: 1.709160 | Abu Consist: 0.000610 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  35/70 | Total Loss: 1.333905 | Recon Loss: 1.333369 | Abu Consist: 0.000535 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  40/70 | Total Loss: 1.122289 | Recon Loss: 1.121799 | Abu Consist: 0.000489 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  45/70 | Total Loss: 0.986678 | Recon Loss: 0.986212 | Abu Consist: 0.000466 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  50/70 | Total Loss: 0.931914 | Recon Loss: 0.931465 | Abu Consist: 0.000449 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  55/70 | Total Loss: 0.885622 | Recon Loss: 0.885190 | Abu Consist: 0.000432 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  60/70 | Total Loss: 0.847609 | Recon Loss: 0.847189 | Abu Consist: 0.000420 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  65/70 | Total Loss: 0.829047 | Recon Loss: 0.828630 | Abu Consist: 0.000416 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  69/70 | Total Loss: 0.820989 | Recon Loss: 0.820572 | Abu Consist: 0.000417 | SumToOne: 0.000000 | Sparse: 0.000000
✅ 训练完成!总耗时: 3.97 秒
**********************************
解混完成.
最终丰度图形状 (N_super, P): (9870, 30)
学习到的端元形状 (P, B): (30, 166)
训练总耗时: 3.97 秒
✅ 结果已保存到: D:\RS_DYL\Output_GCN_Features\CyCUnet_Superpixel_Result.mat
✅ 加载 Segments 矩阵: D:\RS_DYL\Output_GCN_Features\Segments.npy
原始图像尺寸 H=2504, W=2461
②卡在这一步的输出,没有往后继续运行,所以询问了一下Gemini:
点击查看代码
阻塞原因:Matplotlib 阻塞进程
Matplotlib 的 plt.show() 默认会阻塞 (block) Python 进程,直到您手动关闭弹出的绘图窗口。由于您要求绘制 30 张子图,Matplotlib 需要时间来渲染这个大型图像。
您在命令行中看不到任何输出,是因为进程正在等待您关闭图形窗口。
所以:
1)法一:找到并关闭当前正在运行的程序弹出的绘图窗口。

2)法二:修改代码,将 plt.show() 替换为 plt.show(block=False) 和 plt.pause(1),或者如果您不需要在每次运行时都查看,就注释掉对 visualize_abundance_map 的调用。
③关掉弹窗,继续运行,运行成果如下:
点击查看代码
C:\Users\Administrator\.conda\envs\hyspipeline\python.exe D:\RS_DYL\python\cycunet_pny.py 
✅ 使用VCA优化的端元,形状: (166, 30)
数据维度: 超像素数=9870, 波段数=166, 端元数=30
网络输入形状: torch.Size([1, 166, 1, 9870]) (期望: [batch, bands, height, width] = [1, 166, 1, 9870])
Epoch:   0/70 | Total Loss: 13.739389 | Recon Loss: 13.736471 | Abu Consist: 0.002917 | SumToOne: 0.000002 | Sparse: 0.000000
Epoch:   5/70 | Total Loss: 16.892550 | Recon Loss: 16.890717 | Abu Consist: 0.001830 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  10/70 | Total Loss: 9.971375 | Recon Loss: 9.969975 | Abu Consist: 0.001399 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  15/70 | Total Loss: 5.826466 | Recon Loss: 5.825325 | Abu Consist: 0.001140 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  20/70 | Total Loss: 3.885312 | Recon Loss: 3.884359 | Abu Consist: 0.000953 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  25/70 | Total Loss: 2.589013 | Recon Loss: 2.588233 | Abu Consist: 0.000780 | SumToOne: 0.000001 | Sparse: 0.000000
Epoch:  30/70 | Total Loss: 1.709771 | Recon Loss: 1.709160 | Abu Consist: 0.000610 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  35/70 | Total Loss: 1.333905 | Recon Loss: 1.333369 | Abu Consist: 0.000535 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  40/70 | Total Loss: 1.122289 | Recon Loss: 1.121799 | Abu Consist: 0.000489 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  45/70 | Total Loss: 0.986678 | Recon Loss: 0.986212 | Abu Consist: 0.000466 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  50/70 | Total Loss: 0.931914 | Recon Loss: 0.931465 | Abu Consist: 0.000449 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  55/70 | Total Loss: 0.885622 | Recon Loss: 0.885190 | Abu Consist: 0.000432 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  60/70 | Total Loss: 0.847609 | Recon Loss: 0.847189 | Abu Consist: 0.000420 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  65/70 | Total Loss: 0.829047 | Recon Loss: 0.828630 | Abu Consist: 0.000416 | SumToOne: 0.000000 | Sparse: 0.000000
Epoch:  69/70 | Total Loss: 0.820989 | Recon Loss: 0.820572 | Abu Consist: 0.000417 | SumToOne: 0.000000 | Sparse: 0.000000
✅ 训练完成!总耗时: 3.97 秒
**********************************
解混完成.
最终丰度图形状 (N_super, P): (9870, 30)
学习到的端元形状 (P, B): (30, 166)
训练总耗时: 3.97 秒
✅ 结果已保存到: D:\RS_DYL\Output_GCN_Features\CyCUnet_Superpixel_Result.mat
✅ 加载 Segments 矩阵: D:\RS_DYL\Output_GCN_Features\Segments.npy
原始图像尺寸 H=2504, W=2461
检测到 Segments 矩阵,形状: (2504, 2461)
成功重建空间丰度图,形状: (2504, 2461, 30)
空间丰度图已保存到: D:\RS_DYL\Output_GCN_Features\Spatial_Abundance_Maps.mat
丰度图可视化已保存到: D:\RS_DYL\Output_GCN_Features\Abundance_Maps_Visualization.png
程序执行完毕!

进程已结束,退出代码为 0
④但是输出的丰度图只有5个端元的图:

将以下对应部分的代码替换成:

点击查看代码
# --- 11. 可选:可视化丰度图 (如果需要) ---
# 注意:这需要 Segments 矩阵将超像素映射回原始空间
try:
    SEGMENTS_PATH = OUTPUT_DIR / 'Segments.npy'
    if SEGMENTS_PATH.exists():
        segments = np.load(SEGMENTS_PATH)
        H, W = segments.shape
        print(f'✅ 加载 Segments 矩阵: {SEGMENTS_PATH}')
        print(f'原始图像尺寸 H={H}, W={W}')
        print(f'检测到 Segments 矩阵,形状: ({H}, {W})')
        
        # 重建空间丰度图
        abundance_maps = np.zeros((H, W, P))
        for i in range(N_super):
            abundance_maps[segments == i] = abu_est_final[i]
        
        print(f'成功重建空间丰度图,形状: ({H}, {W}, {P})')
        
        # 保存空间丰度图
        sio.savemat(OUTPUT_DIR / 'Spatial_Abundance_Maps.mat', {'Abundance_maps': abundance_maps})
        print(f'空间丰度图已保存到: {OUTPUT_DIR / "Spatial_Abundance_Maps.mat"}')
        
        # 简单可视化 (前5个端元)
        try:
            fig, axes = plt.subplots(1, min(5, P), figsize=(15, 3))
            if P == 1:
                axes = [axes]
                
            for i in range(min(5, P)):
                im = axes[i].imshow(abundance_maps[:, :, i], cmap='jet')
                axes[i].set_title(f'Endmember {i+1}')
                axes[i].axis('off')
                fig.colorbar(im, ax=axes[i], fraction=0.046, pad=0.04)
            
            plt.tight_layout()
            plt.savefig(OUTPUT_DIR / 'Abundance_Maps_Visualization.png', dpi=300, bbox_inches='tight')
            print(f'前5个端元丰度图可视化已保存到: {OUTPUT_DIR / "Abundance_Maps_Visualization.png"}')
            plt.close()
            
            # 完整可视化 (所有端元)
            cols = 5
            rows = (P + cols - 1) // cols
            
            fig, axes = plt.subplots(rows, cols, figsize=(20, 4 * rows))
            if P == 1:
                axes = np.array([[axes]])
            elif rows == 1:
                axes = axes.reshape(1, -1)
            else:
                axes = np.array(axes)  # 确保是numpy数组
                
            for i in range(P):
                row = i // cols
                col = i % cols
                im = axes[row, col].imshow(abundance_maps[:, :, i], cmap='jet')
                axes[row, col].set_title(f'Endmember {i+1}')
                axes[row, col].axis('off')
                fig.colorbar(im, ax=axes[row, col], fraction=0.046, pad=0.04)
            
            # 隐藏多余子图
            for i in range(P, rows * cols):
                row = i // cols
                col = i % cols
                axes[row, col].axis('off')
            
            plt.tight_layout()
            plt.savefig(OUTPUT_DIR / 'Abundance_Maps_Visualization_All.png', dpi=150, bbox_inches='tight')
            print(f'所有端元丰度图可视化已保存到: {OUTPUT_DIR / "Abundance_Maps_Visualization_All.png"}')
            plt.close()
            
        except Exception as e:
            print(f"可视化时出错: {e}")
    else:
        print("提示: 未找到 Segments.npy,无法重建空间丰度图。如需可视化,请确保在超像素处理阶段保存了Segments矩阵。")
except Exception as e:
    print(f"处理空间丰度图时出错: {e}")

4.谱角匹配(SAM)

基于谱角匹配(Spectral Angle Mapper, SAM) 的方法来进行 USGS 光谱库与 CyCUnet 学习得到的端元光谱之间的匹配

(1)代码CyCUnet_USGS.py:

点击查看代码
import numpy as np
import os
import matplotlib.pyplot as plt
import scipy.io as sio
from pathlib import Path
import re
from tqdm import tqdm

# 设置
OUTPUT_DIR = Path(r"D:\RS_DYL\Output_GCN_Features")
USGS_DIR = Path(r"D:\RS_DYL\ChapterM_Minerals")  # 修改为您的USGS光谱库路径

# 确保输出目录存在
OUTPUT_DIR.mkdir(exist_ok=True)


def load_cycunet_results():
    """加载CyCUnet解混结果"""
    result_file = OUTPUT_DIR / 'CyCUnet_Superpixel_Result.mat'
    if not result_file.exists():
        raise FileNotFoundError(f"未找到CyCUnet结果文件: {result_file}")

    data = sio.loadmat(result_file)
    M_learned = data['Endmembers_learned']  # (P, B)
    X_super = data['X_super']  # (N_super, B)
    abundance_map = data['Abundance_map']  # (N_super, P)

    P, B = M_learned.shape
    N_super = abundance_map.shape[0]

    print(f"✅ 加载CyCUnet结果:")
    print(f"  端元数量: {P}")
    print(f"  波段数量: {B}")
    print(f"  超像素数量: {N_super}")

    return M_learned, X_super, abundance_map, P, B, N_super


def parse_usgs_filename(filename):
    """从USGS文件名中提取矿物名称"""
    # 移除扩展名
    name = filename.stem
    # 分割并提取矿物名称(通常在第三个下划线之后)
    parts = name.split('_')
    if len(parts) >= 2:
        mineral_name = parts[1]  # Actinolite
        return mineral_name
    else:
        # 备用方法:使用正则表达式提取字母部分
        match = re.search(r'([A-Za-z]+)', name)
        if match:
            return match.group(1)
        else:
            return name


def load_usgs_spectra(usgs_dir):
    """加载USGS光谱库中的所有光谱"""
    usgs_files = list(usgs_dir.glob("*.txt"))
    if not usgs_files:
        raise FileNotFoundError(f"在目录 {usgs_dir} 中未找到USGS光谱文件")

    print(f"🔍 找到 {len(usgs_files)} 个USGS光谱文件")

    usgs_names = []
    usgs_specs = []

    for file_path in tqdm(usgs_files, desc="加载USGS光谱"):
        try:
            # 读取文件内容
            with open(file_path, 'r') as f:
                lines = f.readlines()

            # 跳过标题行(包含Record的行)
            reflectance_values = []
            for line in lines:
                line = line.strip()
                if line and not line.startswith('s07HYPRNRecord'):
                    try:
                        # 尝试转换为浮点数
                        value = float(line)
                        reflectance_values.append(value)
                    except ValueError:
                        # 跳过无法转换的行
                        continue

            if reflectance_values:
                # 确保光谱长度一致(这里假设所有光谱都有相同波段数)
                usgs_specs.append(np.array(reflectance_values, dtype=np.float32))
                mineral_name = parse_usgs_filename(file_path)
                usgs_names.append(mineral_name)
            else:
                print(f"⚠️ 跳过空文件: {file_path.name}")

        except Exception as e:
            print(f"❌ 读取文件 {file_path.name} 时出错: {e}")
            continue

    print(f"✅ 成功加载 {len(usgs_specs)} 个USGS光谱")
    return usgs_names, usgs_specs


def calculate_sam(spec1, spec2):
    """计算两个光谱之间的谱角匹配(SAM)"""
    # 确保输入是1D数组
    spec1 = spec1.flatten()
    spec2 = spec2.flatten()

    # 归一化
    norm1 = np.linalg.norm(spec1)
    norm2 = np.linalg.norm(spec2)

    if norm1 == 0 or norm2 == 0:
        return np.pi / 2  # 90度,完全不匹配

    # 计算余弦相似度
    cos_theta = np.dot(spec1, spec2) / (norm1 * norm2)

    # 限制在[-1, 1]范围内,避免数值误差
    cos_theta = np.clip(cos_theta, -1.0, 1.0)

    # 计算角度(弧度)
    sam_angle = np.arccos(cos_theta)

    return sam_angle


def match_endmembers_to_usgs(M_learned, usgs_specs, usgs_names):
    """将学习到的端元与USGS光谱库匹配"""
    P, B = M_learned.shape
    num_usgs = len(usgs_specs)

    print(f"🔍 开始匹配 {P} 个端元与 {num_usgs} 个USGS光谱...")

    # 存储每个端元的最佳匹配
    best_matches = []
    best_sam_angles = []
    best_usgs_indices = []

    # 预处理USGS光谱(确保长度匹配)
    usgs_specs_processed = []
    for i, spec in enumerate(usgs_specs):
        if len(spec) == B:
            usgs_specs_processed.append(spec)
        elif len(spec) > B:
            # 如果USGS光谱更长,截断到B个波段
            usgs_specs_processed.append(spec[:B])
            print(f"⚠️ USGS光谱 {usgs_names[i]} 被截断从 {len(spec)} 到 {B} 波段")
        else:
            # 如果USGS光谱更短,用最后一个值填充
            padded_spec = np.pad(spec, (0, B - len(spec)), 'edge')
            usgs_specs_processed.append(padded_spec)
            print(f"⚠️ USGS光谱 {usgs_names[i]} 被填充从 {len(spec)} 到 {B} 波段")

    # 为每个端元找到最佳匹配
    for p in range(P):
        endmember = M_learned[p, :]  # (B,)
        best_sam = float('inf')
        best_usgs_idx = -1

        for i, usgs_spec in enumerate(usgs_specs_processed):
            sam_angle = calculate_sam(endmember, usgs_spec)
            if sam_angle < best_sam:
                best_sam = sam_angle
                best_usgs_idx = i

        best_matches.append(usgs_names[best_usgs_idx])
        best_sam_angles.append(best_sam)
        best_usgs_indices.append(best_usgs_idx)

        print(f"  端元 {p + 1:2d}: {usgs_names[best_usgs_idx]} (SAM: {best_sam:.4f} rad, {np.degrees(best_sam):.2f}°)")

    return best_matches, best_sam_angles, best_usgs_indices, usgs_specs_processed


def create_pseudolabels(abundance_map, endmember_labels):
    """基于丰度图创建伪标签"""
    N_super, P = abundance_map.shape

    # 对每个超像素,找到丰度最大的端元
    dominant_endmembers = np.argmax(abundance_map, axis=1)  # (N_super,)

    # 创建伪标签
    pseudolabels = []
    for i in range(N_super):
        dominant_em = dominant_endmembers[i]
        pseudolabels.append(endmember_labels[dominant_em])

    pseudolabels = np.array(pseudolabels)
    return pseudolabels, dominant_endmembers


def create_spatial_pseudolabels(pseudolabels, segments):
    """将超像素伪标签映射到空间域"""
    H, W = segments.shape
    N_super = len(pseudolabels)

    # 创建标签到整数的映射
    unique_labels = np.unique(pseudolabels)
    label_to_int = {label: idx for idx, label in enumerate(unique_labels)}

    # 创建空间伪标签图
    spatial_pseudolabels = np.zeros((H, W), dtype=np.int32)

    for i in range(N_super):
        label = pseudolabels[i]
        label_int = label_to_int[label]
        spatial_pseudolabels[segments == i] = label_int

    return spatial_pseudolabels, label_to_int, unique_labels


def plot_endmember_spectra(M_learned, usgs_specs_processed, best_usgs_indices, endmember_labels, output_dir):
    """绘制端元光谱和对应的USGS标准光谱"""
    P = M_learned.shape[0]

    # 创建子图
    cols = 5
    rows = (P + cols - 1) // cols

    fig, axes = plt.subplots(rows, cols, figsize=(20, 4 * rows))
    if P == 1:
        axes = np.array([[axes]])
    elif rows == 1:
        axes = axes.reshape(1, -1)
    else:
        axes = np.array(axes)

    # 生成波段索引(因为没有实际波长信息)
    B = M_learned.shape[1]
    wavelengths = np.arange(B)

    for p in range(P):
        row = p // cols
        col = p % cols

        # 绘制学习到的端元
        axes[row, col].plot(wavelengths, M_learned[p, :], 'b-', linewidth=2, label='Learned Endmember')

        # 绘制最佳匹配的USGS光谱
        usgs_idx = best_usgs_indices[p]
        axes[row, col].plot(wavelengths, usgs_specs_processed[usgs_idx], 'r--', linewidth=2, label='USGS Reference')

        axes[row, col].set_title(f'Endmember {p + 1}: {endmember_labels[p]}', fontsize=10)
        axes[row, col].set_xlabel('Band Index')
        axes[row, col].set_ylabel('Reflectance')
        axes[row, col].legend(fontsize=8)
        axes[row, col].grid(True, alpha=0.3)

    # 隐藏多余的子图
    for p in range(P, rows * cols):
        row = p // cols
        col = p % cols
        axes[row, col].axis('off')

    plt.tight_layout()
    plt.savefig(output_dir / 'Endmember_Spectral_Matching.png', dpi=300, bbox_inches='tight')
    plt.close()
    print(f"✅ 端元光谱匹配图已保存到: {output_dir / 'Endmember_Spectral_Matching.png'}")


def plot_spatial_pseudolabels(spatial_pseudolabels, label_to_int, unique_labels, output_dir):
    """绘制空间伪标签图"""
    plt.figure(figsize=(12, 10))

    # 使用不同的颜色映射
    im = plt.imshow(spatial_pseudolabels, cmap='tab20')
    plt.title('Spatial Pseudolabels (Mineral Classification)')
    plt.axis('off')

    # 创建颜色条
    cbar = plt.colorbar(im, shrink=0.8)
    cbar.set_ticks(range(len(unique_labels)))
    cbar.set_ticklabels(unique_labels, fontsize=8)

    plt.tight_layout()
    plt.savefig(output_dir / 'Spatial_Pseudolabels.png', dpi=300, bbox_inches='tight')
    plt.close()
    print(f"✅ 空间伪标签图已保存到: {output_dir / 'Spatial_Pseudolabels.png'}")


def save_results(M_learned, usgs_names, endmember_labels, best_sam_angles,
                 pseudolabels, spatial_pseudolabels, label_to_int, unique_labels,
                 best_usgs_indices, usgs_specs_processed, output_dir):
    """保存所有结果"""
    results = {
        'M_learned': M_learned,
        'USGS_names': usgs_names,
        'Endmember_labels': endmember_labels,
        'SAM_angles': best_sam_angles,
        'Pseudolabels': pseudolabels,
        'Spatial_pseudolabels': spatial_pseudolabels,
        'Label_to_int': label_to_int,
        'Unique_labels': unique_labels,
        'Best_USGS_indices': best_usgs_indices,
        'USGS_specs_processed': usgs_specs_processed
    }

    save_path = output_dir / 'USGS_Matching_Results.mat'
    sio.savemat(save_path, results)
    print(f"✅ 所有结果已保存到: {save_path}")


def main():
    """主函数"""
    print("🚀 开始USGS光谱库匹配与矿物分类...")

    # 1. 加载CyCUnet结果
    try:
        M_learned, X_super, abundance_map, P, B, N_super = load_cycunet_results()
    except Exception as e:
        print(f"❌ 加载CyCUnet结果失败: {e}")
        return

    # 2. 加载Segments矩阵(用于空间映射)
    try:
        segments_path = OUTPUT_DIR / 'Segments.npy'
        if segments_path.exists():
            segments = np.load(segments_path)
            H, W = segments.shape
            print(f"✅ 加载Segments矩阵: {segments.shape}")
        else:
            print("⚠️ 未找到Segments.npy,将无法生成空间伪标签图")
            segments = None
    except Exception as e:
        print(f"⚠️ 加载Segments矩阵失败: {e}")
        segments = None

    # 3. 加载USGS光谱库
    try:
        usgs_names, usgs_specs = load_usgs_spectra(USGS_DIR)
    except Exception as e:
        print(f"❌ 加载USGS光谱库失败: {e}")
        return

    # 4. 匹配端元与USGS光谱
    try:
        endmember_labels, best_sam_angles, best_usgs_indices, usgs_specs_processed = \
            match_endmembers_to_usgs(M_learned, usgs_specs, usgs_names)
    except Exception as e:
        print(f"❌ 端元匹配失败: {e}")
        return

    # 5. 创建伪标签
    try:
        pseudolabels, dominant_endmembers = create_pseudolabels(abundance_map, endmember_labels)
        print(f"✅ 创建了 {len(pseudolabels)} 个超像素伪标签")

        # 统计各类别数量
        unique, counts = np.unique(pseudolabels, return_counts=True)
        print("📊 伪标签统计:")
        for label, count in zip(unique, counts):
            print(f"  {label}: {count} 个超像素")
    except Exception as e:
        print(f"❌ 创建伪标签失败: {e}")
        return

    # 6. 创建空间伪标签(如果有segments)
    spatial_pseudolabels = None
    label_to_int = None
    unique_labels = None

    if segments is not None:
        try:
            spatial_pseudolabels, label_to_int, unique_labels = \
                create_spatial_pseudolabels(pseudolabels, segments)
            print(f"✅ 创建了空间伪标签图: {spatial_pseudolabels.shape}")
        except Exception as e:
            print(f"⚠️ 创建空间伪标签失败: {e}")
            spatial_pseudolabels = None

    # 7. 可视化结果
    try:
        plot_endmember_spectra(M_learned, usgs_specs_processed, best_usgs_indices,
                               endmember_labels, OUTPUT_DIR)

        if spatial_pseudolabels is not None:
            plot_spatial_pseudolabels(spatial_pseudolabels, label_to_int, unique_labels, OUTPUT_DIR)
    except Exception as e:
        print(f"⚠️ 可视化失败: {e}")

    # 8. 保存结果
    try:
        save_results(M_learned, usgs_names, endmember_labels, best_sam_angles,
                     pseudolabels, spatial_pseudolabels, label_to_int, unique_labels,
                     best_usgs_indices, usgs_specs_processed, OUTPUT_DIR)
    except Exception as e:
        print(f"❌ 保存结果失败: {e}")
        return

    print("🎉 USGS光谱库匹配与矿物分类完成!")
    print(f"   输出目录: {OUTPUT_DIR}")


if __name__ == "__main__":
    main()

(2)输出结果

点击查看代码
C:\Users\Administrator\.conda\envs\hyspipeline\python.exe D:\RS_DYL\python\CyCUnet_USGS.py 
🚀 开始USGS光谱库匹配与矿物分类...
✅ 加载CyCUnet结果:
  端元数量: 30
  波段数量: 166
  超像素数量: 9870
✅ 加载Segments矩阵: (2504, 2461)
加载USGS光谱:   0%|          | 0/1276 [00:00<?, ?it/s]🔍 找到 1276 个USGS光谱文件
加载USGS光谱: 100%|██████████| 1276/1276 [00:00<00:00, 5424.03it/s]
✅ 成功加载 1276 个USGS光谱
🔍 开始匹配 30 个端元与 1276 个USGS光谱...
⚠️ USGS光谱 Acmite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Actinolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Adularia 被截断从 242 到 166 波段
⚠️ USGS光谱 Adularia 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Albite 被截断从 242 到 166 波段
⚠️ USGS光谱 Allanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Allanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Allanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Allanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Allanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Allanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Allanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Allanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Almandine 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Alunite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ammonio-Illite-Smect 被截断从 242 到 166 波段
⚠️ USGS光谱 Ammonio-Illite-Smect 被截断从 242 到 166 波段
⚠️ USGS光谱 Ammonio-Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ammonio-Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ammonio-Smectite 被截断从 242 到 166 波段
⚠️ USGS光谱 Amphibole 被截断从 242 到 166 波段
⚠️ USGS光谱 Amphibole 被截断从 242 到 166 波段
⚠️ USGS光谱 Analcime 被截断从 242 到 166 波段
⚠️ USGS光谱 Analcime 被截断从 242 到 166 波段
⚠️ USGS光谱 Ancylite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andalusite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andalusite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andalusite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andesine 被截断从 242 到 166 波段
⚠️ USGS光谱 Andesine 被截断从 242 到 166 波段
⚠️ USGS光谱 Andesine 被截断从 242 到 166 波段
⚠️ USGS光谱 Andesine 被截断从 242 到 166 波段
⚠️ USGS光谱 Andesine 被截断从 242 到 166 波段
⚠️ USGS光谱 Andesine 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Andradite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anhydrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anhydrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Annite 被截断从 242 到 166 波段
⚠️ USGS光谱 Annite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anorthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anthophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anthophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anthophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anthophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anthophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Anthophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Antigorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Aragonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Arsenopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Arsenopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Arsenopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Arsenopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Arsenopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Arsenopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Augite 被截断从 242 到 166 波段
⚠️ USGS光谱 Augite 被截断从 242 到 166 波段
⚠️ USGS光谱 Augite 被截断从 242 到 166 波段
⚠️ USGS光谱 Augite 被截断从 242 到 166 波段
⚠️ USGS光谱 Augite 被截断从 242 到 166 波段
⚠️ USGS光谱 Axinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Axinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Axinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Axinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Axinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Axinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Axinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Azurite 被截断从 242 到 166 波段
⚠️ USGS光谱 Barite 被截断从 242 到 166 波段
⚠️ USGS光谱 Barite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bassanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bassanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bastnaesite 被截断从 242 到 166 波段
⚠️ USGS光谱 Beidellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Beidellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Beryl 被截断从 242 到 166 波段
⚠️ USGS光谱 Beryl 被截断从 242 到 166 波段
⚠️ USGS光谱 Beryl 被截断从 242 到 166 波段
⚠️ USGS光谱 Beryl 被截断从 242 到 166 波段
⚠️ USGS光谱 Beryl 被截断从 242 到 166 波段
⚠️ USGS光谱 Beryl 被截断从 242 到 166 波段
⚠️ USGS光谱 Beryl 被截断从 242 到 166 波段
⚠️ USGS光谱 Beryl 被截断从 242 到 166 波段
⚠️ USGS光谱 Beryl 被截断从 242 到 166 波段
⚠️ USGS光谱 Biotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Biotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Biotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Biotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bloedite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bloedite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bronzite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bronzite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bronzite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bronzite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bronzite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bronzite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brookite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brookite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brookite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brookite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brucite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brucite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brucite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brucite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brucite 被截断从 242 到 166 波段
⚠️ USGS光谱 Brucite 被截断从 242 到 166 波段
⚠️ USGS光谱 Buddingtonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Buddingtonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Butlerite 被截断从 242 到 166 波段
⚠️ USGS光谱 Butlerite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bytownite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bytownite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bytownite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bytownite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bytownite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bytownite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bytownite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bytownite 被截断从 242 到 166 波段
⚠️ USGS光谱 Bytownite 被截断从 242 到 166 波段
⚠️ USGS光谱 Calcite 被截断从 242 到 166 波段
⚠️ USGS光谱 Calcite 被截断从 242 到 166 波段
⚠️ USGS光谱 Calcite 被截断从 242 到 166 波段
⚠️ USGS光谱 Calcite 被截断从 242 到 166 波段
⚠️ USGS光谱 Calcite 被截断从 242 到 166 波段
⚠️ USGS光谱 Calcite 被截断从 242 到 166 波段
⚠️ USGS光谱 Calcite 被截断从 242 到 166 波段
⚠️ USGS光谱 Carbon 被截断从 242 到 166 波段
⚠️ USGS光谱 Carbon 被截断从 242 到 166 波段
⚠️ USGS光谱 Carnallite 被截断从 242 到 166 波段
⚠️ USGS光谱 Carnallite 被截断从 242 到 166 波段
⚠️ USGS光谱 Carnallite 被截断从 242 到 166 波段
⚠️ USGS光谱 Carnallite 被截断从 242 到 166 波段
⚠️ USGS光谱 Carnallite 被截断从 242 到 166 波段
⚠️ USGS光谱 Carnallite 被截断从 242 到 166 波段
⚠️ USGS光谱 Carnallite 被截断从 242 到 166 波段
⚠️ USGS光谱 Carnallite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cassiterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cassiterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cassiterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cassiterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cassiterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cassiterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Celestite 被截断从 242 到 166 波段
⚠️ USGS光谱 Celestite 被截断从 242 到 166 波段
⚠️ USGS光谱 Celestite 被截断从 242 到 166 波段
⚠️ USGS光谱 Celestite 被截断从 242 到 166 波段
⚠️ USGS光谱 Celestite 被截断从 242 到 166 波段
⚠️ USGS光谱 Celestite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcedony 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcedony 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcedony 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chalcopyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chert 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorapatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorapatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorapatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorapatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chromite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chromite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chromite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chromite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chromite 被截断从 242 到 166 波段
⚠️ USGS光谱 Chrysocolla 被截断从 242 到 166 波段
⚠️ USGS光谱 Chrysocolla 被截断从 242 到 166 波段
⚠️ USGS光谱 Chrysocolla 被截断从 242 到 166 波段
⚠️ USGS光谱 Chrysocolla 被截断从 242 到 166 波段
⚠️ USGS光谱 Chrysocolla 被截断从 242 到 166 波段
⚠️ USGS光谱 Chrysotile 被截断从 242 到 166 波段
⚠️ USGS光谱 Chrysotile 被截断从 242 到 166 波段
⚠️ USGS光谱 Chrysotile 被截断从 242 到 166 波段
⚠️ USGS光谱 Chrysotile 被截断从 242 到 166 波段
⚠️ USGS光谱 Cinnabar 被截断从 242 到 166 波段
⚠️ USGS光谱 Cinnabar 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinochlore 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinoptilolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinoptilolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinoptilolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Clinoptilolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Clintonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Colemanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Colemanite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cookeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cookeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cookeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cookeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cookeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cookeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cookeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Copiapite 被截断从 242 到 166 波段
⚠️ USGS光谱 Copiapite 被截断从 242 到 166 波段
⚠️ USGS光谱 Coquimbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Corrensite 被截断从 242 到 166 波段
⚠️ USGS光谱 Corrensite 被截断从 242 到 166 波段
⚠️ USGS光谱 Corundum 被截断从 242 到 166 波段
⚠️ USGS光谱 Corundum 被截断从 242 到 166 波段
⚠️ USGS光谱 Corundum 被截断从 242 到 166 波段
⚠️ USGS光谱 Corundum 被截断从 242 到 166 波段
⚠️ USGS光谱 Cronstedtite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cronstedtite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cummingtonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cummingtonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cummingtonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cummingtonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cummingtonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cummingtonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cummingtonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cuprite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cuprite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cuprite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cuprite 被截断从 242 到 166 波段
⚠️ USGS光谱 Cuprite 被截断从 242 到 166 波段
⚠️ USGS光谱 Datolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Datolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Datolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Datolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Datolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Datolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Diaspore 被截断从 242 到 166 波段
⚠️ USGS光谱 Diaspore 被截断从 242 到 166 波段
⚠️ USGS光谱 Diaspore 被截断从 242 到 166 波段
⚠️ USGS光谱 Diaspore 被截断从 242 到 166 波段
⚠️ USGS光谱 Diaspore 被截断从 242 到 166 波段
⚠️ USGS光谱 Diaspore 被截断从 242 到 166 波段
⚠️ USGS光谱 Diaspore 被截断从 242 到 166 波段
⚠️ USGS光谱 Dickite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dickite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dickite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dickite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dickite 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Diopside 被截断从 242 到 166 波段
⚠️ USGS光谱 Dipyre 被截断从 242 到 166 波段
⚠️ USGS光谱 Dolomite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dolomite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dolomite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dolomite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dolomite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dolomite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dolomite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dumortierite 被截断从 242 到 166 波段
⚠️ USGS光谱 Dumortierite 被截断从 242 到 166 波段
⚠️ USGS光谱 Elbaite 被截断从 242 到 166 波段
⚠️ USGS光谱 Elbaite 被截断从 242 到 166 波段
⚠️ USGS光谱 Elbaite 被截断从 242 到 166 波段
⚠️ USGS光谱 Elbaite 被截断从 242 到 166 波段
⚠️ USGS光谱 Elbaite 被截断从 242 到 166 波段
⚠️ USGS光谱 Endellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Endellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Enstatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Enstatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Epidote 被截断从 242 到 166 波段
⚠️ USGS光谱 Epidote 被截断从 242 到 166 波段
⚠️ USGS光谱 Epidote 被截断从 242 到 166 波段
⚠️ USGS光谱 Epidote 被截断从 242 到 166 波段
⚠️ USGS光谱 Epidote 被截断从 242 到 166 波段
⚠️ USGS光谱 Epidote 被截断从 242 到 166 波段
⚠️ USGS光谱 Epidote 被截断从 242 到 166 波段
⚠️ USGS光谱 Epidote 被截断从 242 到 166 波段
⚠️ USGS光谱 Epidote 被截断从 242 到 166 波段
⚠️ USGS光谱 Epsomite 被截断从 242 到 166 波段
⚠️ USGS光谱 Epsomite 被截断从 242 到 166 波段
⚠️ USGS光谱 Eugsterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Eugsterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Fassaite 被截断从 242 到 166 波段
⚠️ USGS光谱 Fassaite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ferrihydrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Fluorapatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Fluorapatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Fluorapatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Fluorapatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Fluorapatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Forsterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Galena 被截断从 242 到 166 波段
⚠️ USGS光谱 Galena 被截断从 242 到 166 波段
⚠️ USGS光谱 Galena 被截断从 242 到 166 波段
⚠️ USGS光谱 Galena 被截断从 242 到 166 波段
⚠️ USGS光谱 Galena 被截断从 242 到 166 波段
⚠️ USGS光谱 Galena 被截断从 242 到 166 波段
⚠️ USGS光谱 Galena 被截断从 242 到 166 波段
⚠️ USGS光谱 Galena 被截断从 242 到 166 波段
⚠️ USGS光谱 Gaylussite 被截断从 242 到 166 波段
⚠️ USGS光谱 Gaylussite 被截断从 242 到 166 波段
⚠️ USGS光谱 Gibbsite 被截断从 242 到 166 波段
⚠️ USGS光谱 Gibbsite 被截断从 242 到 166 波段
⚠️ USGS光谱 Gibbsite 被截断从 242 到 166 波段
⚠️ USGS光谱 Gibbsite 被截断从 242 到 166 波段
⚠️ USGS光谱 Gibbsite 被截断从 242 到 166 波段
⚠️ USGS光谱 Gibbsite 被截断从 242 到 166 波段
⚠️ USGS光谱 Gibbsite 被截断从 242 到 166 波段
⚠️ USGS光谱 Gibbsite 被截断从 242 到 166 波段
⚠️ USGS光谱 Glauconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Glauconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Glauconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Glauconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Glauconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Glauconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Glaucophane 被截断从 242 到 166 波段
⚠️ USGS光谱 Glaucophane 被截断从 242 到 166 波段
⚠️ USGS光谱 Glaucophane 被截断从 242 到 166 波段
⚠️ USGS光谱 Glaucophane 被截断从 242 到 166 波段
⚠️ USGS光谱 Glaucophane 被截断从 242 到 166 波段
⚠️ USGS光谱 Glaucophane 被截断从 242 到 166 波段
⚠️ USGS光谱 Glaucophane 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Goethite 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Grossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Gypsum 被截断从 242 到 166 波段
⚠️ USGS光谱 Gypsum 被截断从 242 到 166 波段
⚠️ USGS光谱 Gypsum 被截断从 242 到 166 波段
⚠️ USGS光谱 Gypsum 被截断从 242 到 166 波段
⚠️ USGS光谱 Gypsum 被截断从 242 到 166 波段
⚠️ USGS光谱 Gypsum 被截断从 242 到 166 波段
⚠️ USGS光谱 Gypsum 被截断从 242 到 166 波段
⚠️ USGS光谱 Gypsum 被截断从 242 到 166 波段
⚠️ USGS光谱 Halite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halloysite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halloysite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halloysite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halloysite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halloysite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halloysite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halloysite 被截断从 242 到 166 波段
⚠️ USGS光谱 Halloysite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hectorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hectorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hectorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hectorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hedenbergite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hedenbergite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hedenbergite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hedenbergite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hedenbergite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hedenbergite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hedenbergite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hedenbergite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Heulandite 被截断从 242 到 166 波段
⚠️ USGS光谱 Heulandite 被截断从 242 到 166 波段
⚠️ USGS光谱 Heulandite 被截断从 242 到 166 波段
⚠️ USGS光谱 Heulandite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Hornblende 被截断从 242 到 166 波段
⚠️ USGS光谱 Howlite 被截断从 242 到 166 波段
⚠️ USGS光谱 Howlite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hydrogrossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Hydrogrossular 被截断从 242 到 166 波段
⚠️ USGS光谱 Hydroxyl-Apatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hydroxyl-Apatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Hypersthene 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Illite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ilmenite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ilmenite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ilmenite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ilmenite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ilmenite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jadeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jadeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jadeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jadeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jadeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jadeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jadeite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Jarosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kainite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kainite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kaolinite 被截断从 242 到 166 波段
⚠️ USGS光谱 Karpatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Karpatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Karpatite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kieserite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kieserite 被截断从 242 到 166 波段
⚠️ USGS光谱 Kieserite 被截断从 242 到 166 波段
⚠️ USGS光谱 Knebelite 被截断从 242 到 166 波段
⚠️ USGS光谱 Knebelite 被截断从 242 到 166 波段
⚠️ USGS光谱 Knebelite 被截断从 242 到 166 波段
⚠️ USGS光谱 Knebelite 被截断从 242 到 166 波段
⚠️ USGS光谱 Knebelite 被截断从 242 到 166 波段
⚠️ USGS光谱 Knebelite 被截断从 242 到 166 波段
⚠️ USGS光谱 Knebelite 被截断从 242 到 166 波段
⚠️ USGS光谱 Labradorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Labradorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Labradorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Labradorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Labradorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Labradorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Laumontite 被截断从 242 到 166 波段
⚠️ USGS光谱 Laumontite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lazurite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lazurite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lazurite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lazurite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lazurite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lazurite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidocrocite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidocrocite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lepidolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Limonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Limonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lizardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lizardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lizardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lizardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lizardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lizardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Lizardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Maghemite 被截断从 242 到 166 波段
⚠️ USGS光谱 Maghemite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Magnetite 被截断从 242 到 166 波段
⚠️ USGS光谱 Malachite 被截断从 242 到 166 波段
⚠️ USGS光谱 Malachite 被截断从 242 到 166 波段
⚠️ USGS光谱 Malachite 被截断从 242 到 166 波段
⚠️ USGS光谱 Malachite 被截断从 242 到 166 波段
⚠️ USGS光谱 Malachite 被截断从 242 到 166 波段
⚠️ USGS光谱 Malachite 被截断从 242 到 166 波段
⚠️ USGS光谱 Margarite 被截断从 242 到 166 波段
⚠️ USGS光谱 Margarite 被截断从 242 到 166 波段
⚠️ USGS光谱 Marialite 被截断从 242 到 166 波段
⚠️ USGS光谱 Marialite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mascagnite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mascagnite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mascagnite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mascagnite 被截断从 242 到 166 波段
⚠️ USGS光谱 Meionite 被截断从 242 到 166 波段
⚠️ USGS光谱 Meionite 被截断从 242 到 166 波段
⚠️ USGS光谱 Meionite 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Microcline 被截断从 242 到 166 波段
⚠️ USGS光谱 Mirabilite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mirabilite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mizzonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mizzonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mizzonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monazite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monticellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monticellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monticellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monticellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monticellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Monticellite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Montmorillonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mordenite 被截断从 242 到 166 波段
⚠️ USGS光谱 Mordenite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Muscovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nacrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nanohematite 被截断从 242 到 166 波段
⚠️ USGS光谱 Natrolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Natrolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Natrolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Natrolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Natrolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Natrolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Natrolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Natrolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nepheline 被截断从 242 到 166 波段
⚠️ USGS光谱 Nepheline 被截断从 242 到 166 波段
⚠️ USGS光谱 Nepheline 被截断从 242 到 166 波段
⚠️ USGS光谱 Nephrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nephrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nephrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nephrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nephrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Niter 被截断从 242 到 166 波段
⚠️ USGS光谱 Niter 被截断从 242 到 166 波段
⚠️ USGS光谱 Nontronite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nontronite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nontronite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nontronite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nontronite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nontronite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nontronite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nontronite 被截断从 242 到 166 波段
⚠️ USGS光谱 Nontronite 被截断从 242 到 166 波段
⚠️ USGS光谱 Oligoclase 被截断从 242 到 166 波段
⚠️ USGS光谱 Oligoclase 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Olivine 被截断从 242 到 166 波段
⚠️ USGS光谱 Opal 被截断从 242 到 166 波段
⚠️ USGS光谱 Opal 被截断从 242 到 166 波段
⚠️ USGS光谱 Opal 被截断从 242 到 166 波段
⚠️ USGS光谱 Opal 被截断从 242 到 166 波段
⚠️ USGS光谱 Orthoclase 被截断从 242 到 166 波段
⚠️ USGS光谱 Orthoclase 被截断从 242 到 166 波段
⚠️ USGS光谱 Orthoclase 被截断从 242 到 166 波段
⚠️ USGS光谱 Palygorskite 被截断从 242 到 166 波段
⚠️ USGS光谱 Palygorskite 被截断从 242 到 166 波段
⚠️ USGS光谱 Paragonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Parisite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pectolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pectolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pectolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pectolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Perthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Perthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Perthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Perthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Perthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Perthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Perthite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Phlogopite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pigeonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pigeonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pigeonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pigeonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pigeonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pigeonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pinnoite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pinnoite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pitch 被截断从 242 到 166 波段
⚠️ USGS光谱 Polyhalite 被截断从 242 到 166 波段
⚠️ USGS光谱 Polyhalite 被截断从 242 到 166 波段
⚠️ USGS光谱 Portlandite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prehnite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prehnite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prehnite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prehnite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prochlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prochlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prochlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prochlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prochlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prochlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prochlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Prochlorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Psilomelane 被截断从 242 到 166 波段
⚠️ USGS光谱 Psilomelane 被截断从 242 到 166 波段
⚠️ USGS光谱 Psilomelane 被截断从 242 到 166 波段
⚠️ USGS光谱 Psilomelane 被截断从 242 到 166 波段
⚠️ USGS光谱 Psilomelane 被截断从 242 到 166 波段
⚠️ USGS光谱 Psilomelane 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrolusite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrolusite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrolusite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyromorphite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyroxene 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyroxene 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyroxene 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyroxene 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyroxene 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyroxene 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyroxmangite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyroxmangite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrrhotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrrhotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrrhotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrrhotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrrhotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Pyrrhotite 被截断从 242 到 166 波段
⚠️ USGS光谱 Quartz 被截断从 242 到 166 波段
⚠️ USGS光谱 Quartz 被截断从 242 到 166 波段
⚠️ USGS光谱 Quartz 被截断从 242 到 166 波段
⚠️ USGS光谱 Quartz 被截断从 242 到 166 波段
⚠️ USGS光谱 Quartz 被截断从 242 到 166 波段
⚠️ USGS光谱 Quartz 被截断从 242 到 166 波段
⚠️ USGS光谱 Quartz 被截断从 242 到 166 波段
⚠️ USGS光谱 Quartz 被截断从 242 到 166 波段
⚠️ USGS光谱 Rectorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rectorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rectorite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rhodochrosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rhodochrosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rhodochrosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rhodochrosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rhodochrosite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rhodonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rhodonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Richterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Richterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Richterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Richterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Richterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Richterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Richterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Richterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Richterite 被截断从 242 到 166 波段
⚠️ USGS光谱 Riebeckite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rivadavite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rivadavite 被截断从 242 到 166 波段
⚠️ USGS光谱 Roscoelite 被截断从 242 到 166 波段
⚠️ USGS光谱 Rutile 被截断从 242 到 166 波段
⚠️ USGS光谱 Rutile 被截断从 242 到 166 波段
⚠️ USGS光谱 Sanidine 被截断从 242 到 166 波段
⚠️ USGS光谱 Sanidine 被截断从 242 到 166 波段
⚠️ USGS光谱 Saponite 被截断从 242 到 166 波段
⚠️ USGS光谱 Saponite 被截断从 242 到 166 波段
⚠️ USGS光谱 Saponite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sauconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sauconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Schwertmannite 被截断从 242 到 166 波段
⚠️ USGS光谱 Scolecite 被截断从 242 到 166 波段
⚠️ USGS光谱 Scolecite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sepiolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sepiolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sepiolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sepiolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sepiolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sepiolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sepiolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sepiolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Serpentine 被截断从 242 到 166 波段
⚠️ USGS光谱 Siderite 被截断从 242 到 166 波段
⚠️ USGS光谱 Siderite 被截断从 242 到 166 波段
⚠️ USGS光谱 Siderite 被截断从 242 到 166 波段
⚠️ USGS光谱 Siderite 被截断从 242 到 166 波段
⚠️ USGS光谱 Siderite 被截断从 242 到 166 波段
⚠️ USGS光谱 Siderite 被截断从 242 到 166 波段
⚠️ USGS光谱 Siderite 被截断从 242 到 166 波段
⚠️ USGS光谱 Siderophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Siderophyllite 被截断从 242 到 166 波段
⚠️ USGS光谱 Smaragdite 被截断从 242 到 166 波段
⚠️ USGS光谱 Smaragdite 被截断从 242 到 166 波段
⚠️ USGS光谱 Smaragdite 被截断从 242 到 166 波段
⚠️ USGS光谱 Smaragdite 被截断从 242 到 166 波段
⚠️ USGS光谱 Smaragdite 被截断从 242 到 166 波段
⚠️ USGS光谱 Smaragdite 被截断从 242 到 166 波段
⚠️ USGS光谱 Smaragdite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sodium 被截断从 242 到 166 波段
⚠️ USGS光谱 Sodium 被截断从 242 到 166 波段
⚠️ USGS光谱 Spessartine 被截断从 242 到 166 波段
⚠️ USGS光谱 Spessartine 被截断从 242 到 166 波段
⚠️ USGS光谱 Spessartine 被截断从 242 到 166 波段
⚠️ USGS光谱 Spessartine 被截断从 242 到 166 波段
⚠️ USGS光谱 Spessartine 被截断从 242 到 166 波段
⚠️ USGS光谱 Spessartine 被截断从 242 到 166 波段
⚠️ USGS光谱 Spessartine 被截断从 242 到 166 波段
⚠️ USGS光谱 Spessartine 被截断从 242 到 166 波段
⚠️ USGS光谱 Sphalerite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sphalerite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sphalerite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sphalerite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sphalerite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sphalerite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sphalerite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sphene 被截断从 242 到 166 波段
⚠️ USGS光谱 Sphene 被截断从 242 到 166 波段
⚠️ USGS光谱 Spodumene 被截断从 242 到 166 波段
⚠️ USGS光谱 Spodumene 被截断从 242 到 166 波段
⚠️ USGS光谱 Spodumene 被截断从 242 到 166 波段
⚠️ USGS光谱 Spodumene 被截断从 242 到 166 波段
⚠️ USGS光谱 Spodumene 被截断从 242 到 166 波段
⚠️ USGS光谱 Spodumene 被截断从 242 到 166 波段
⚠️ USGS光谱 Staurolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Staurolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Staurolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Staurolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Staurolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Staurolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Stilbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Stilbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Stilbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Stilbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Stilbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Stilbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Stilbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Stilbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Stilbite 被截断从 242 到 166 波段
⚠️ USGS光谱 Strontianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Strontianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Strontianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Strontianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Strontianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Strontianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Sulfur 被截断从 242 到 166 波段
⚠️ USGS光谱 Sulfur 被截断从 242 到 166 波段
⚠️ USGS光谱 Syngenite 被截断从 242 到 166 波段
⚠️ USGS光谱 Syngenite 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Talc 被截断从 242 到 166 波段
⚠️ USGS光谱 Thenardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thenardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thenardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thenardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thenardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thenardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thenardite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thuringite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thuringite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thuringite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thuringite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thuringite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thuringite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thuringite 被截断从 242 到 166 波段
⚠️ USGS光谱 Thuringite 被截断从 242 到 166 波段
⚠️ USGS光谱 Tincalconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Tincalconite 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Topaz 被截断从 242 到 166 波段
⚠️ USGS光谱 Tourmaline 被截断从 242 到 166 波段
⚠️ USGS光谱 Tourmaline 被截断从 242 到 166 波段
⚠️ USGS光谱 Tremolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Tremolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Tremolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Tremolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Tremolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Tremolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Tremolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Tremolite 被截断从 242 到 166 波段
⚠️ USGS光谱 Trona 被截断从 242 到 166 波段
⚠️ USGS光谱 Trona 被截断从 242 到 166 波段
⚠️ USGS光谱 Ulexite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ulexite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ulexite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ulexite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ulexite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ulexite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ulexite 被截断从 242 到 166 波段
⚠️ USGS光谱 Ulexite 被截断从 242 到 166 波段
⚠️ USGS光谱 Uralite 被截断从 242 到 166 波段
⚠️ USGS光谱 Uralite 被截断从 242 到 166 波段
⚠️ USGS光谱 Uralite 被截断从 242 到 166 波段
⚠️ USGS光谱 Uralite 被截断从 242 到 166 波段
⚠️ USGS光谱 Uralite 被截断从 242 到 166 波段
⚠️ USGS光谱 Uralite 被截断从 242 到 166 波段
⚠️ USGS光谱 Uralite 被截断从 242 到 166 波段
⚠️ USGS光谱 Uvarovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Uvarovite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vermiculite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vermiculite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vermiculite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vermiculite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vermiculite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vesuvianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vesuvianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vesuvianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vesuvianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vesuvianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vesuvianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Vesuvianite 被截断从 242 到 166 波段
⚠️ USGS光谱 Witherite 被截断从 242 到 166 波段
⚠️ USGS光谱 Witherite 被截断从 242 到 166 波段
⚠️ USGS光谱 Witherite 被截断从 242 到 166 波段
⚠️ USGS光谱 Witherite 被截断从 242 到 166 波段
⚠️ USGS光谱 Witherite 被截断从 242 到 166 波段
⚠️ USGS光谱 Witherite 被截断从 242 到 166 波段
⚠️ USGS光谱 Wollastonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Wollastonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Wollastonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Wollastonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Wollastonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Wollastonite 被截断从 242 到 166 波段
⚠️ USGS光谱 Xenotime 被截断从 242 到 166 波段
⚠️ USGS光谱 Zircon 被截断从 242 到 166 波段
⚠️ USGS光谱 Zoisite 被截断从 242 到 166 波段
⚠️ USGS光谱 Zoisite 被截断从 242 到 166 波段
⚠️ USGS光谱 Zoisite 被截断从 242 到 166 波段
⚠️ USGS光谱 Zoisite 被截断从 242 到 166 波段
⚠️ USGS光谱 Zoisite 被截断从 242 到 166 波段
⚠️ USGS光谱 Zoisite 被截断从 242 到 166 波段
⚠️ USGS光谱 Zoisite 被截断从 242 到 166 波段
⚠️ USGS光谱 Zunyite 被截断从 242 到 166 波段
  端元  1: Niter (SAM: 0.0128 rad, 0.73°)
  端元  2: Diaspore (SAM: 0.2410 rad, 13.81°)
  端元  3: Olivine (SAM: 1.0393 rad, 59.55°)
  端元  4: Alunite (SAM: 0.5915 rad, 33.89°)
  端元  5: Olivine (SAM: 1.1869 rad, 68.00°)
  端元  6: Almandine (SAM: 0.8833 rad, 50.61°)
  端元  7: Chromite (SAM: 0.4702 rad, 26.94°)
  端元  8: Anthophyllite (SAM: 0.3046 rad, 17.45°)
  端元  9: Corundum (SAM: 0.3338 rad, 19.13°)
  端元 10: Olivine (SAM: 1.0432 rad, 59.77°)
  端元 11: Sodium (SAM: 0.1817 rad, 10.41°)
  端元 12: Corundum (SAM: 0.3532 rad, 20.24°)
  端元 13: Corundum (SAM: 0.3024 rad, 17.33°)
  端元 14: Ferrihydrite (SAM: 0.5166 rad, 29.60°)
  端元 15: Almandine (SAM: 0.5017 rad, 28.74°)
  端元 16: Olivine (SAM: 1.1054 rad, 63.34°)
  端元 17: Corundum (SAM: 0.2411 rad, 13.81°)
  端元 18: Serpentine (SAM: 0.6314 rad, 36.17°)
  端元 19: Chromite (SAM: 0.3200 rad, 18.33°)
  端元 20: Chromite (SAM: 0.2841 rad, 16.28°)
  端元 21: Diaspore (SAM: 0.2222 rad, 12.73°)
  端元 22: Olivine (SAM: 1.0817 rad, 61.98°)
  端元 23: Parisite (SAM: 1.2708 rad, 72.81°)
  端元 24: Corundum (SAM: 0.2667 rad, 15.28°)
  端元 25: Ulexite (SAM: 0.2118 rad, 12.13°)
  端元 26: Cassiterite (SAM: 0.2160 rad, 12.37°)
  端元 27: Serpentine (SAM: 0.3369 rad, 19.30°)
  端元 28: Chromite (SAM: 0.3751 rad, 21.49°)
  端元 29: Monticellite (SAM: 0.2952 rad, 16.92°)
  端元 30: Olivine (SAM: 1.0530 rad, 60.34°)
✅ 创建了 9870 个超像素伪标签
📊 伪标签统计:
  Cassiterite: 1 个超像素
  Corundum: 1 个超像素
  Niter: 6735 个超像素
  Olivine: 3113 个超像素
  Parisite: 19 个超像素
  Ulexite: 1 个超像素
✅ 创建了空间伪标签图: (2504, 2461)
✅ 端元光谱匹配图已保存到: D:\RS_DYL\Output_GCN_Features\Endmember_Spectral_Matching.png
✅ 空间伪标签图已保存到: D:\RS_DYL\Output_GCN_Features\Spatial_Pseudolabels.png
✅ 所有结果已保存到: D:\RS_DYL\Output_GCN_Features\USGS_Matching_Results.mat
🎉 USGS光谱库匹配与矿物分类完成!
   输出目录: D:\RS_DYL\Output_GCN_Features

进程已结束,退出代码为 0

(3)分析输出结果:

①SAM比对的结果:
端元 (部分) 最佳匹配矿物 SAM 角 (度) 质量评估 物理推测意义
1 硝石 (硝石) 0.73° 优秀 非常干净、高质量的端元,可能是重要的蚀变产物或背景文物。
11 钠 (钠) 10.41° 很好 光谱形态良好,但可能存在轻微混合。
2、17、21 刚玉 12.73° ~ 13.81° 尚可 这些可能是具有实际蚀变意义的矿物,需要查看轮廓确认其特征峰。
3、5、10、16、22、30 橄榄石(橄榄石) 59° ~ 68° 极差 关键问题点!高 SAM 角表明:学习端元与标准橄榄石光谱形态差异巨大。
23 Parisite (氟碳尖矿) 72.81° 极差 同上。
②伪标签是这六个:

Cassiterite: 1 个超像素 - 锡石
Corundum: 1 个超像素 - 刚玉
Niter: 6735 个超像素 - 硝石
Olivine: 3113 个超像素 - 橄榄石
Parisite: 19 个超像素 - 氟碳钙铈矿
Ulexite: 1 个超像素 - 钠硼解石

③“端元识别”和“伪标签分类”这两个步骤之间的核心差异

1)伪标签是基于丰度图(统计学上的支配关系)生成的,而 SAM 匹配结果是基于光谱形态的相似度(光谱学上的纯净度)得出的。
2)分析

端元 最佳匹配矿物 SAM 角(度) 可信度 伪标签中的地位 最终处理建议
1 Niter (硝石) 0.73° 极高 支配 68% 区域 确认为 Niter。
11 Sodium (钠) 10.41° 未在支配列表 确认为 Sodium。 (可能是钠长石等钠质矿物)
21, 17, 2 Diaspore/Corundum 12.73°∼13.81° 中高 Corundum 支配 1 个像素 确认为 Diaspore/Corundum (需要查看光谱确认是否为目标蚀变矿物)。
25 Ulexite (钠硼解石) 12.13° 中高 支配 1 个像素 确认为 Ulexite。
26 Cassiterite (锡石) 12.37° 中高 支配 1 个像素 确认为 Cassiterite。
... 其他 ≤15∘ 的端元 ≤15∘ 中高 未在支配列表 保留并确认为对应矿物。
3, 5, 10, ... Olivine, Parisite ≥59∘ 极低 支配 32% 区域 排除,归类为背景/未知/噪声。

3)伪标签是解混过程的最终输出。
它的核心意义在于:在不知道图像中存在哪些纯净端元的前提下,通过数学手段找到它们,并量化它们在每个像素中的比例。

④伪标签的作用可以概括为以下三点:

1)作用一:将混合像元归属到最主要的组分 (分类)
目标: 在分类图中,一个像素必须被分配给一个类别。
如何实现: 伪标签通过 “最大丰度原则” 实现这一点。
例如:像素 A = 70% Niter (硝石) + 10% Corundum + 20% Olivine (噪声)。
如果直接 SAM 比对,该像素可能被拒绝。
但伪标签会说:“这个像素本质上是 Niter 类的”,然后将像素 A 归类为 Niter。
意义: 即使图像是高度混合的,伪标签也能提供一个简化的、可解释的空间分类图,这是遥感制图的基础。

2)作用二:发现图像中“隐性”的纯净组分(端元提取)
目标: 自动发现图像中最具代表性的光谱特征。
如何实现: HySime(或 VCA/N-FINDR 等解混算法)不依赖于 USGS 库,而是直接从您的 Hyperion 数据中寻找统计学上最独立、最“纯净”的 30 个特征(即端元)。
意义: 这是解混最核心的价值。它帮助您找到您的矿区独有的蚀变或背景特征,即使 USGS 库中没有它们的精确匹配,您也可以通过分析这些端元的光谱形态来推断其物理意义。

3)作用三:量化每种组分的比例(丰度图)
目标: 提供定量的矿物信息。
如何实现: 除了伪标签图(定性分类),解混的核心输出是 30 张丰度图。每张图都显示了对应端元在空间上从 0% 到 100% 的含量分布。
意义:
地质应用: 地质学家需要知道矿物含量的变化趋势,例如高岭石丰度高的区域可能指示强烈的酸性蚀变。这是 SAM Mapping 无法提供的。
您的例子: 丰度图告诉您,Niter 对应的端元特征在图像中普遍存在(高丰度),而 Cassiterite 对应的端元特征只在极少数超像素中接近 100%(即伪标签)。

即:

步骤 使用的方法 目的 您的应用
1. 纯净度分析 SAM 比对(30 个端元 vs USGS 库) 筛选出可信的物理端元(低 SAM 角)。 判断: Niter 可信,Olivine 不可信。
2. 空间分类 伪标签(最大丰度原则) 量化这些端元在空间上的支配力。 发现: Niter 支配 68%,Olivine 支配 32%。
3. 最终制图 组合分析 报告一张既有物理意义又符合空间分布的图。 输出: 剔除不可信的 Olivine 区域,保留 Niter 和所有低 SAM 角矿物的局部纯净区域。

posted on 2025-11-29 20:50  风居住的街道DYL  阅读(2)  评论(0)    收藏  举报