如何使用 Python 在卫星图像上训练 SVM 分类器
How to train an SVM classifier on a satellite image using Python
我正在使用 scikit-learn
库对卫星图像执行监督 classification(支持向量机 classifier)。我的主要问题是如何训练我的 SVM classifier。我在 youtube 上观看了很多视频,并阅读了一些关于如何在 scikit-learn
中训练 SVM 模型的教程。我看过的所有教程都使用了著名的 Iris 数据集。为了在 scikit-learn
中执行监督 SVM class化,我们需要有标签。对于 Iris 数据集,我们有 Iris.target
,这是我们试图预测的标签('setosa'、'versicolor'、'virginica')。通过阅读 scikit-learn
文档,训练过程非常简单。
就我而言,我必须训练在市区上空捕获的 SAR 卫星图像,并且我需要 class 确定市区、道路、河流和植被(4 classes) .该图像有两个波段,但我没有每个波段的标签数据 class 我正在尝试预测,例如 Iris 数据。
所以,我的问题是,我是否必须手动创建向量数据(对于 4 classes)才能训练 SVM 模型?有没有比手动创建矢量数据更容易训练模型的方法?在这种情况下我们该怎么办?
老实说,我有点困惑。我将不胜感激任何帮助
我的解决方案:-
手动处理:-
如果你的数据集比较小,可以手动创建一个向量数据(自己创建的时候也靠谱)。否则,很难应用 SVM 对图像进行分类。
自动处理:-
第 1 步:-
您可以使用 "Unsupervised Image Clustering" 技术将图像分为这 4 个类别,然后在聚类完成后将图像标记为 1 到 4。 (例如 K-Means 聚类算法)
第 2 步:-
目前,您有一个标记图像的数据集。将它们拆分为训练测试数据。
第 3 步:-
现在应用 SVM 对您的测试图像进行分类并找出您的模型准确性。
这里有一个完整的示例,应该能让您走上正轨。为了简单起见,让我们假设您的目标是 class 将下面 three-band 图像上的像素分为三个不同的类别,即建筑物、植被和水。这些类别将分别以红色、绿色和蓝色显示。
我们首先读取图像并定义一些稍后将使用的变量。
import numpy as np
from skimage import io
img = io.imread('https://i.stack.imgur.com/TFOv7.png')
rows, cols, bands = img.shape
classes = {'building': 0, 'vegetation': 1, 'water': 2}
n_classes = len(classes)
palette = np.uint8([[255, 0, 0], [0, 255, 0], [0, 0, 255]])
无监督class化
如果您不想手动标记某些像素,那么您需要检测数据的底层结构,即您必须将图像像素分成 n_classes
个分区,例如通过 k-means clustering:
from sklearn.cluster import KMeans
X = img.reshape(rows*cols, bands)
kmeans = KMeans(n_clusters=n_classes, random_state=3).fit(X)
unsupervised = kmeans.labels_.reshape(rows, cols)
io.imshow(palette[unsupervised])
监督class化
或者,您可以将标签分配给已知 class 的一些像素(带标签的像素集通常称为 ground truth)。在这个玩具示例中,ground truth 由三个 20×20 像素的硬编码正方形区域组成,如下图所示:
supervised = n_classes*np.ones(shape=(rows, cols), dtype=np.int)
supervised[200:220, 150:170] = classes['building']
supervised[40:60, 40:60] = classes['vegetation']
supervised[100:120, 200:220] = classes['water']
地面实况(训练集)的像素用于拟合支持向量机。
y = supervised.ravel()
train = np.flatnonzero(supervised < n_classes)
test = np.flatnonzero(supervised == n_classes)
from sklearn.svm import SVC
clf = SVC(gamma='auto')
clf.fit(X[train], y[train])
y[test] = clf.predict(X[test])
supervised = y.reshape(rows, cols)
io.imshow(palette[supervised])
在训练阶段之后,classifier 将 class 标签分配给剩余的像素(测试集)。 class化结果如下所示:
最后的评论
结果似乎表明无监督 class 化比其有监督的对应物更准确。然而,有监督的 classification 通常优于无监督的 classification。重要的是要注意,在分析的示例中,通过调整 SVM classifier 的参数可以显着提高准确性。通过扩大和细化 ground truth 可以进一步改进,因为 train/test 比率非常小,红色和绿色块实际上包含不同 classes 的像素。最后,可以合理地预期利用更复杂的特征,例如根据强度水平计算的比率或指数(例如 NDVI)将提高性能。
我正在使用 scikit-learn
库对卫星图像执行监督 classification(支持向量机 classifier)。我的主要问题是如何训练我的 SVM classifier。我在 youtube 上观看了很多视频,并阅读了一些关于如何在 scikit-learn
中训练 SVM 模型的教程。我看过的所有教程都使用了著名的 Iris 数据集。为了在 scikit-learn
中执行监督 SVM class化,我们需要有标签。对于 Iris 数据集,我们有 Iris.target
,这是我们试图预测的标签('setosa'、'versicolor'、'virginica')。通过阅读 scikit-learn
文档,训练过程非常简单。
就我而言,我必须训练在市区上空捕获的 SAR 卫星图像,并且我需要 class 确定市区、道路、河流和植被(4 classes) .该图像有两个波段,但我没有每个波段的标签数据 class 我正在尝试预测,例如 Iris 数据。
所以,我的问题是,我是否必须手动创建向量数据(对于 4 classes)才能训练 SVM 模型?有没有比手动创建矢量数据更容易训练模型的方法?在这种情况下我们该怎么办?
老实说,我有点困惑。我将不胜感激任何帮助
我的解决方案:-
手动处理:-
如果你的数据集比较小,可以手动创建一个向量数据(自己创建的时候也靠谱)。否则,很难应用 SVM 对图像进行分类。
自动处理:-
第 1 步:-
您可以使用 "Unsupervised Image Clustering" 技术将图像分为这 4 个类别,然后在聚类完成后将图像标记为 1 到 4。 (例如 K-Means 聚类算法)
第 2 步:-
目前,您有一个标记图像的数据集。将它们拆分为训练测试数据。
第 3 步:-
现在应用 SVM 对您的测试图像进行分类并找出您的模型准确性。
这里有一个完整的示例,应该能让您走上正轨。为了简单起见,让我们假设您的目标是 class 将下面 three-band 图像上的像素分为三个不同的类别,即建筑物、植被和水。这些类别将分别以红色、绿色和蓝色显示。
我们首先读取图像并定义一些稍后将使用的变量。
import numpy as np
from skimage import io
img = io.imread('https://i.stack.imgur.com/TFOv7.png')
rows, cols, bands = img.shape
classes = {'building': 0, 'vegetation': 1, 'water': 2}
n_classes = len(classes)
palette = np.uint8([[255, 0, 0], [0, 255, 0], [0, 0, 255]])
无监督class化
如果您不想手动标记某些像素,那么您需要检测数据的底层结构,即您必须将图像像素分成 n_classes
个分区,例如通过 k-means clustering:
from sklearn.cluster import KMeans
X = img.reshape(rows*cols, bands)
kmeans = KMeans(n_clusters=n_classes, random_state=3).fit(X)
unsupervised = kmeans.labels_.reshape(rows, cols)
io.imshow(palette[unsupervised])
监督class化
或者,您可以将标签分配给已知 class 的一些像素(带标签的像素集通常称为 ground truth)。在这个玩具示例中,ground truth 由三个 20×20 像素的硬编码正方形区域组成,如下图所示:
supervised = n_classes*np.ones(shape=(rows, cols), dtype=np.int)
supervised[200:220, 150:170] = classes['building']
supervised[40:60, 40:60] = classes['vegetation']
supervised[100:120, 200:220] = classes['water']
地面实况(训练集)的像素用于拟合支持向量机。
y = supervised.ravel()
train = np.flatnonzero(supervised < n_classes)
test = np.flatnonzero(supervised == n_classes)
from sklearn.svm import SVC
clf = SVC(gamma='auto')
clf.fit(X[train], y[train])
y[test] = clf.predict(X[test])
supervised = y.reshape(rows, cols)
io.imshow(palette[supervised])
在训练阶段之后,classifier 将 class 标签分配给剩余的像素(测试集)。 class化结果如下所示:
最后的评论
结果似乎表明无监督 class 化比其有监督的对应物更准确。然而,有监督的 classification 通常优于无监督的 classification。重要的是要注意,在分析的示例中,通过调整 SVM classifier 的参数可以显着提高准确性。通过扩大和细化 ground truth 可以进一步改进,因为 train/test 比率非常小,红色和绿色块实际上包含不同 classes 的像素。最后,可以合理地预期利用更复杂的特征,例如根据强度水平计算的比率或指数(例如 NDVI)将提高性能。