2.6.1 特征空间可视化

2.6.1.1 特征可视化

读取图像,显示样本标记的标签:

[1]:
from skimage.io import imread, imsave
img = imread('Hyperspectral_Project/dc.tif')
img.shape
[1]:
(191, 1280, 307)
[2]:
import numpy as np
from skimage.exposure import rescale_intensity

#选取第60、27和17波段,组合成RGB图像
img_RGB = np.dstack([img[59, :, :], img[26, :, :], img[16, :, :]])

#对图像进行对比度拉伸,放缩到0-255的数值范围
p_10, p_90 = np.percentile(img_RGB, (10, 90))

img_rescale = rescale_intensity(img_RGB,
                                in_range=(p_10, p_90),
                                out_range=(0, 255))

img_rescale = img_rescale.astype('uint8')
imsave('hyperspectral_img_RGB.png', img_rescale)
[3]:
from skimage.io import imread, imsave
img = imread('Hyperspectral_Project/dc.tif')

import numpy as np
from skimage.exposure import rescale_intensity
#选取第60、27和17波段,组合成RGB图像
img_RGB = np.dstack([img[59, :, :], img[26, :, :], img[16, :, :]])
#对图像进行对比度拉伸,放缩到0-255的数值范围
p_10, p_90 = np.percentile(img_RGB, (10, 90))
img_rescale = rescale_intensity(img_RGB,
                                in_range=(p_10, p_90),
                                out_range=(0, 255))
img_rescale = img_rescale.astype('uint8')
[4]:
def get_label(file_path):
    with open(file_path, 'r') as label_file:
        label_data = label_file.readlines()[13:]
    label_list = []
    region_list = []
    for i in range(len(label_data) // 3):
        #解析文件,获得标注区域的标签、左上角像素坐标和右下角像素坐标
        label = label_data[i * 3].split('\t')[4]
        r_1, c_1 = label_data[i * 3 + 1][:-1].split('\t')[1:]
        r_2, c_2 = label_data[i * 3 + 2][:-1].split('\t')[1:]
        label_list.append(int(label) - 1)
        region_list.append((int(r_1) - 1, int(c_1) - 1, int(r_2), int(c_2)))
    return label_list, region_list
[5]:
from skimage import color
from skimage.io import imshow
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import patches
gray_img = color.rgb2gray(img_rescale)
gray_img = gray_img.reshape(img.shape[1], img.shape[2], 1)
gray_img = gray_img.repeat(3, axis=2)
file_path = 'Hyperspectral_Project/dctest.project'
label_list, region_list = get_label(file_path)
colors = sns.color_palette('bright')
for label, region in zip(label_list, region_list):
    gray_img[region[0]:region[2], region[1]:region[3]] = colors[label]
imshow(gray_img)
labels = ['Roofs', 'Street', 'Path', 'Grass', 'Trees', 'Water', 'Shadow']
legend_patches = []
for i in range(len(labels)):
    legend_patches.append(patches.Patch(color=colors[i], label=labels[i]))
plt.legend(handles=legend_patches,
           loc='lower left',
           fontsize=3,
           frameon=False,
           bbox_to_anchor=(1, -0.01))
plt.axis('off')
plt.savefig('hyperspectral_img_label.pdf', bbox_inches='tight', dpi=600)
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_7_0.png
[6]:
import requests
from bs4 import BeautifulSoup
import numpy as np
html_url = 'https://www.lars.purdue.edu/home/image_data/hydice_dc_wavelengths.html'
res = requests.get(html_url)
soup = BeautifulSoup(res.text, 'html.parser')
wavelength_list = []
for item in soup.find_all('br'):
    band_str = item.next_sibling.split()
    if band_str[-1] != 'x':
        wavelength_list.append(float(band_str[-2]))
wavelength_table = np.array(wavelength_list)

显示光谱曲线:

[88]:
y_label  = np.array(label_list)
y_region = np.array(region_list)

pixel_mean_value_list = []
pixel_std_value_list = []
label_index_list = []

X_list = []

for item in set(label_list):
    same_label_region = y_region[y_label==item]
    region_img_list = []
    for region in same_label_region:
        region_img = img[:,region[0]:region[2],region[1]:region[3]]
        region_img = region_img.transpose((1,2,0)).reshape(-1,img.shape[0])
        region_img_list.append(region_img)

    pixel_mean_value = np.concatenate(region_img_list,axis=0).mean(axis=0)
    pixel_mean_value_list.append(pixel_mean_value)

    pixel_std_value = np.concatenate(region_img_list,axis=0).std(axis=0)
    pixel_std_value_list.append(pixel_std_value)

    label_index_list.append(item)

    X_list.append(np.concatenate(region_img_list,axis=0))

%matplotlib inline
%config InlineBackend.figure_format = 'retina'
import matplotlib as mpl
mpl.style.use('ggplot')

#正常显示中文标签
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
#正常显示负号
plt.rcParams['axes.unicode_minus'] = False

for l, p_mean, p_std in zip(label_index_list, pixel_mean_value_list,pixel_std_value_list):
    plt.plot(wavelength_table, p_mean, label=labels[l])
    plt.fill_between(
    wavelength_table,
    p_mean + p_std,
    p_mean - p_std,
    alpha=0.15,)
plt.legend()
plt.xlabel('Wave length (nm)')
plt.savefig('class_mean_spectral_curve_fill.pdf', bbox_inches='tight')
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_10_0.png

特征组合显示:

[12]:
from skimage.io import imread

def load_hyperspectral_data(img_file_path,label_file_path):
    img = imread(img_file_path)
    label_list, region_list = get_label(label_file_path)

    y_regions  = np.array(label_list)
    X_regions = np.array(region_list)
    X_list = []
    y_list = []
    pixel_position_list = []

    for region_i, label_i in zip(region_list,label_list):

        for row in range(region_i[0],region_i[2]):
            for column in range(region_i[1],region_i[3]):
                X_list.append(img[:,row,column].reshape((img.shape[0],)))
                y_list.append(label_i)
                pixel_position_list.append([row,column])

    X = np.array(X_list)
    y = np.array(y_list)
    pixel_position = np.array(pixel_position_list)
    return X,y,pixel_position
[13]:
img_file_path = 'Hyperspectral_Project/dc.tif'
label_file_path = 'Hyperspectral_Project/dctest.project'
X,y,pixel_position = load_hyperspectral_data(img_file_path,label_file_path)
[45]:
#测试像素位置是否正确
img_and_label_test = np.zeros((1280, 307),dtype = np.uint8)
for p_i in pixel_position:
    img_and_label_test[p_i[0],p_i[1]] = 255
imshow(img_and_label_test)
[45]:
<matplotlib.image.AxesImage at 0x7fc819523d50>
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_14_1.png
[48]:
B = X[:,6:14].mean(axis = 1)
G = X[:,24:37].mean(axis = 1)
R = X[:,45:61].mean(axis = 1)
NIR = X[:,61:82].mean(axis = 1)
MIR = X[:,82:].mean(axis = 1)

[49]:
NDVI = (NIR-R)/(NIR+R)
MNDWI= (G-MIR)/(G+MIR)
NDBI = (MIR-NIR)/(MIR+NIR)

[75]:
input_x = np.concatenate(
    [NDVI.reshape((-1, 1)),
     MNDWI.reshape((-1, 1)),
     NDBI.reshape((-1, 1))],
    axis=1)
input_y = [labels[item] for item in y]
[76]:
input_x.shape
[76]:
(8079, 3)
[80]:
import pandas as pd
import seaborn as sns
input_pd = pd.DataFrame(input_x,columns=['NDVI','MNDWI','NDBI'])
input_pd['Categories']= input_y
[190]:
sns.pairplot(input_pd, hue='Categories', height=6,
             #plot_kws=dict(s=10),
             #diag_kws=dict(shade=True),
            )
plt.savefig('pairplot_spectral_index_small.pdf', bbox_inches='tight')
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_20_0.png

2.6.1.2 线性可分数据

[234]:
selected_categories = ['Trees', 'Water']
select_categories_visulization(selected_categories)
plt.savefig(
    f'linear_SVM_{selected_categories[0]}_{selected_categories[1]}.pdf',
    bbox_inches='tight')
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_22_0.png
[215]:
selected_categories = ['Street', 'Path']
select_categories_visulization(selected_categories)
plt.savefig(
    f'linear_SVM_{selected_categories[0]}_{selected_categories[1]}.pdf',
    bbox_inches='tight')
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_23_0.png

2.6.1.3 非线性可分数据

[563]:
from sklearn.neural_network import MLPClassifier

def select_mlp_categories_visulization(selected_categories):

    selected_data = input_pd[(input_pd['Categories'] == selected_categories[0]) |
                           (input_pd['Categories'] == selected_categories[1])]

    model = MLPClassifier(hidden_layer_sizes=(200,200,200),
                          alpha=1e-6,
                          tol=1e-7,
                          max_iter=2000,
                          random_state=7,
                         )



    features = selected_data.drop(['Categories','NDVI'],axis=1)
    target = selected_data['Categories']
    model.fit(features, target)


    sns.relplot(data=selected_data,
                y='NDBI',
                x='MNDWI',
                hue='Categories',s=10)
    plt.xlim(0.65,0.80)
    plt.ylim(-0.74,-0.66)
    ax = plt.gca()
    ax.set_aspect(1.5)

    plt.grid(b=False)

    plot_mlp_decision_function(model)
[554]:
selected_categories = ['Roofs', 'Path']
select_mlp_categories_visulization(selected_categories)

plt.savefig(
    f'mlp_{selected_categories[0]}_{selected_categories[1]}.pdf',
    bbox_inches='tight')
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_26_0.png
[ ]:
def visualize_classifier(model, X, y, ax=None, cmap='rainbow'):
    ax = ax or plt.gca()


    ax.axis('tight')
    ax.axis('off')
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()

    # fit the estimator
    model.fit(X, y)
    xx, yy = np.meshgrid(np.linspace(*xlim, num=200),
                         np.linspace(*ylim, num=200))
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)

    # Create a color plot with the results
    n_classes = len(np.unique(y))
    contours = ax.contourf(xx, yy, Z, alpha=0.3,
                           levels=np.arange(n_classes + 1) - 0.5,
                           cmap=cmap,
                           #clim=(y.min(), y.max()),
                           zorder=1)

    ax.set(xlim=xlim, ylim=ylim)
[615]:
selected_categories = ['Shadow','Water']

from sklearn.tree import DecisionTreeClassifier



selected_data = input_pd[(input_pd['Categories'] == selected_categories[0]) |
                       (input_pd['Categories'] == selected_categories[1])]

model = DecisionTreeClassifier()



features = selected_data.drop(['Categories','NDBI'],axis=1)
target = selected_data['Categories']
model.fit(features, target)


sns.relplot(data=selected_data,
            x='NDVI',
            y='MNDWI',
            hue='Categories',s=10)

plt.grid(b=False)

plot_mlp_decision_function(model)

plt.savefig(
    f'DecisionTree_{selected_categories[0]}_{selected_categories[1]}.pdf',
    bbox_inches='tight')
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_28_0.png
[617]:
selected_categories = ['Roofs', 'Path']

selected_data = input_pd[(input_pd['Categories'] == selected_categories[0]) |
                       (input_pd['Categories'] == selected_categories[1])]
model = DecisionTreeClassifier()



features = selected_data.drop(['Categories','NDVI'],axis=1)
target = selected_data['Categories']
model.fit(features, target)


sns.relplot(data=selected_data,
            y='NDBI',
            x='MNDWI',
            hue='Categories',s=10)
plt.xlim(0.65,0.80)
plt.ylim(-0.74,-0.66)
ax = plt.gca()
ax.set_aspect(1.5)

plt.grid(b=False)

plot_mlp_decision_function(model)

plt.savefig(
    f'DecisionTree_{selected_categories[0]}_{selected_categories[1]}.pdf',
    bbox_inches='tight')
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_29_0.png
[618]:
from sklearn.naive_bayes import GaussianNB
clf = GaussianNB()

selected_categories = ['Roofs', 'Path']

selected_data = input_pd[(input_pd['Categories'] == selected_categories[0]) |
                       (input_pd['Categories'] == selected_categories[1])]
model = clf



features = selected_data.drop(['Categories','NDVI'],axis=1)
target = selected_data['Categories']
model.fit(features, target)


sns.relplot(data=selected_data,
            y='NDBI',
            x='MNDWI',
            hue='Categories',s=10)
plt.xlim(0.65,0.80)
plt.ylim(-0.74,-0.66)
ax = plt.gca()
ax.set_aspect(1.5)

plt.grid(b=False)

plot_mlp_decision_function(model)

plt.savefig(
    f'Gaussian_naive_bayes_{selected_categories[0]}_{selected_categories[1]}.pdf',
    bbox_inches='tight')
../../../_images/1stPart_Chapter2.PattenFeatureRecognition_PPT-code_visualize_hyperspectral_image_30_0.png