简介:面向计算机、自动化等专业学生的期末课设/毕设资源,分别基于支持向量机(SVM)、KNN、CNN、LSTM四种算法实现遥感图像识别,并配套详细说明文档。项目采用武汉大学WHU-RS19数据集,涵盖机场、海滩、农田、住宅区等19类遥感图像,同时包含针对非600×600图像的预处理和数据集索引生成脚本,便于划分训练集与测试集。压缩包共74个文件,大小约7.45MB,主要包含Python源码、Jupyter Notebook交互式演示、Markdown算法说明文档以及结果对比图片;代码按0_kNN、1_SVM、2_CNN、3_LSTM四个目录清晰组织,每种算法都配有可运行脚本和相应解释。目前已有1008人学习下载。通过该资源可以系统掌握四种算法的数据加载、模型构建、参数调优、训练评估和结果可视化全流程,也能直接运行复现遥感图像分类效果,适合期末课程设计、大作业或毕业设计参考,并支持在此基础上进行扩展修改。 做遥感图像识别这个课程设计的时候,我最直观的感受是:算法选型远比想象中重要。很多同学一上来就堆了一堆python代码,跑完SVM、KNN、CNN、LSTM四个模型,最后报告写得像流水账,答辩时被老师一问“为什么用LSTM做图像识别”就卡壳。所以这篇文章不只讲源码,我会把“为什么这么设计”“四个算法各自适合什么”“踩过哪些坑”一并讲清楚,让不管是新手还是想冲高分的你,都能拿这套思路直接复现。
这个项目本质上是一个遥感图像地物分类任务:输入一张遥感影像,模型判断它是农田、水域、建筑还是林地。围绕这个任务,我实现了SVM、KNN、CNN、LSTM四种算法,全部用python完成,并整理了一份详细说明文档。整份代码结构清晰,注释完整,适合期末课设、毕业设计或者作为入门学习项目参考。下面我把整个实现过程和关键细节拆开讲。
1. 项目背景与整体设计思路
1.1 为什么遥感图像识别适合做四算法对比
遥感图像识别本质上是图像分类问题,但和普通物体识别不太一样。遥感影像通常是大尺寸、多波段、地面物体尺度差异大的数据,同一类地物在不同区域的光谱特征可能差异很大,而不同地物之间又可能存在“同谱异物”的情况。这就导致模型不仅需要提取颜色、纹理等浅层特征,还要有一定的空间上下文理解能力。
用SVM、KNN、CNN、LSTM四组算法做对比,核心目的不是比谁强,而是让大家直观看到传统机器学习方法和深度学习方法在特征提取方式上的本质区别。SVM和KNN需要手工设计特征,比如颜色直方图、纹理特征、边缘特征,然后再交给分类器;CNN则能自动从原始像素中学习层次化特征,低层学边缘、中层学纹理、高层学语义;LSTM本身是处理序列数据的,用在图像上需要把图像转成序列,这种强行改造很容易暴露出模型“不擅长什么”,对理解模型适用边界很有帮助。
1.2 任务定义与数据集选择
我做的是标准的监督分类任务。数据集选用了公开的遥感图像数据集,类别设置为6类:林地、草地、水域、建筑、农田、裸地。如果你们课设没有现成数据,可以从UC Merced、EuroSAT、NWPU-RESISC45这些公开数据集里选一部分,或者自己用Google Earth截取图片手动标注,但要注意每个类别样本量尽量均衡。
评估指标不只是整体的准确率,还加上了每个类别的精确率、召回率和F1-score,以及混淆矩阵。因为遥感图像分类里,如果水域和草地样本不均衡,整体准确率很高但某一类可能完全没识别出来,单纯看准确率会误导人。
训练集、验证集、测试集按6:2:2划分,同时保证每个类别在各个集合中的比例大致相同,也就是做了一次分层划分。数据划分代码虽然只有几行,但对结果的影响很大,不建议直接用默认的随机划分。
2. 环境准备与数据预处理细节
2.1 Python环境与依赖库配置
整个项目基于python 3.8实现,我用的是Anaconda创建的虚拟环境,强烈建议你也这么做,避免多个项目依赖冲突。核心依赖库如下:
numpy:数组运算和图像矩阵处理opencv-python:图像读取、缩放、增强scikit-learn:SVM、KNN以及评估指标计算tensorflow或pytorch:实现CNN和LSTMmatplotlib:绘制训练曲线和混淆矩阵pandas:整理结果表格
这里有个实际踩过的坑:CNN和LSTM如果使用TensorFlow,2.x和1.x的API差异很大,建议直接写2.x版本的Keras接口。如果你的电脑没有GPU,就用CPU版本,但要把训练轮数调小一点,不然一张遥感图几百个像素,训练起来很慢。
2.2 图像预处理的标准流程
遥感图像预处理我分四步做,每一步都有明确目的。
第一步是统一尺寸。数据集中图片大小不一,直接输入模型会导致维度不一致。我统一缩放到64x64像素。有人会觉得太小损失信息,但对于对比算法的课设来说,64x64能明显加快训练速度,而且SVM和KNN的特征维度也不会爆炸。
第二步是颜色空间处理。SVM和KNN我用的是RGB三通道直方图特征,CNN和LSTM输入的是原始RGB矩阵。遥感图像有些波段是近红外,但普通公开数据集大多已经是RGB合成图,所以不需要额外处理。
第三步是归一化。把像素值从0到255除以255,变成0到1之间的浮点数。神经网络对输入数据的尺度比较敏感,归一化能加速收敛,也避免某些特征值过大主导梯度。
第四步是标签编码。把“林地”“草地”这些字符串标签转换成整数,类别数量从0到5,然后CNN和LSTM输出层使用softmax做6分类。
数据预处理的具体代码可以参考下面这段:
import cv2 import numpy as np from sklearn.model_selection import train_test_split def load_data(image_paths, labels, img_size=64): X = [] y = [] for path, label in zip(image_paths, labels): img = cv2.imread(path) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = cv2.resize(img, (img_size, img_size)) X.append(img) y.append(label) X = np.array(X, dtype=np.float32) / 255.0 y = np.array(y, dtype=np.int32) return train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)注意stratify=y,这就是之前说的分层划分,能保证测试集和训练集里各类比例一致。这个细节在很多课设代码里都会被忽略,但答辩时提出来是个加分项。
3. 四种算法实现与原理拆解
3.1 SVM支持向量机实现步骤
SVM的核心思想是在特征空间中找到一个最大间隔超平面,将不同类别的样本分开。对于线性不可分的数据,通过核函数把样本映射到高维空间,让它们变得线性可分。遥感图像分类中,SVM是传统方法里表现相当稳定的一种,尤其在小样本场景下。
但SVM不能直接吃原始像素矩阵,需要把图像转成向量特征。我选取了颜色直方图加HOG特征两个部分。颜色直方图描述三类颜色分布,HOG描述局部梯度方向和强度,能捕捉边缘和纹理信息。特征维度大概是:颜色直方图3通道各256个bin,HOG取64维,加起来约800多维。这样既不过大,又能保留有效信息。
SVM实现时我用了scikit-learn中的SVC,关键参数是kernel='rbf'、C=10.0、gamma='scale'。C是误分类惩罚系数,C越大越容易过拟合;gamma控制高斯核的半径,值越小决策边界越平滑。可以用网格搜索GridSearchCV调参,但课设阶段先用一组合理参数跑通流程更重要。
from sklearn.svm import SVC from sklearn.metrics import accuracy_score, classification_report svm_model = SVC(kernel='rbf', C=10.0, gamma='scale', probability=True) svm_model.fit(X_flatten_train, y_train) y_pred = svm_model.predict(X_flatten_test) print("SVM Accuracy:", accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred, target_names=class_names))如果发现训练时间过长,可以先把特征维度用PCA降到100维。这里我的经验是,SVM分类效果好不好,特征工程占七成,调参占三成。
3.2 KNN最近邻算法实现要点
KNN的思路更朴素:一个样本的类别由它最近的K个邻居投票决定。KNN无需显式训练,但预测时会把测试样本和所有训练样本计算距离,所以推理速度慢,而且特征维度越高,距离度量越不可靠。
KNN的特征输入我直接用了和SVM相同的直方图加HOG特征,但额外做了一步标准化。因为KNN依赖距离计算,如果某个特征的数值范围特别大,就会主导距离,标准化能消除量纲差异。接着用PCA降到100维,减小“维数灾难”的影响。
K值的选择我做了个小实验,分别测试K=3、5、7、9。最终K=5效果最好。距离度量试过欧氏距离和曼哈顿距离,欧氏距离略好。
from sklearn.neighbors import KNeighborsClassifier from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_train_std = scaler.fit_transform(X_flatten_train) X_test_std = scaler.transform(X_flatten_test) pca = PCA(n_components=100) X_train_pca = pca.fit_transform(X_train_std) X_test_pca = pca.transform(X_test_std) knn_model = KNeighborsClassifier(n_neighbors=5, metric='euclidean') knn_model.fit(X_train_pca, y_train)KNN虽然简单,但有个容易被问到的点:knn和kmeans有关系吗?其实没有直接关系。KNN是有监督分类算法,KMeans是无监督聚类算法,区别一定要搞清楚,答辩高频问题。
3.3 CNN卷积神经网络的搭建
CNN是目前图像识别里最成熟的模型结构。它通过卷积核在图像上滑动,自动学习局部特征,通过池化层降低特征图尺寸,最后用全连接层做分类。遥感图像中地物的边缘、纹理、形状信息都能被CNN自动提取,效果通常远好于手工特征加SVM。
我搭了一个轻量级CNN模型,结构如下:
- 输入层:64x64x3
- 第一个卷积块:32个3x3卷积核,ReLU激活,2x2最大池化
- 第二个卷积块:64个3x3卷积核,ReLU激活,2x2最大池化
- 第三个卷积块:128个3x3卷积核,ReLU激活,2x2最大池化
- Flatten层
- Dropout层:丢弃率0.5
- 全连接层:128个神经元,ReLU激活
- 输出层:6个神经元,softmax激活
这个结构参考了VGG的思路,但大幅减少了层数和参数。训练时使用Adam优化器,学习率设为0.001,损失函数为交叉熵。数据增强用了随机水平翻转、随机旋转、随机亮度调整,有效缓解了样本不足的问题。
关键代码:
import tensorflow as tf from tensorflow.keras import layers, models model_cnn = models.Sequential([ layers.Input(shape=(64, 64, 3)), layers.Conv2D(32, (3, 3), activation='relu', padding='same'), layers.MaxPooling2D((2, 2)), layers.Conv2D(64, (3, 3), activation='relu', padding='same'), layers.MaxPooling2D((2, 2)), layers.Conv2D(128, (3, 3), activation='relu', padding='same'), layers.MaxPooling2D((2, 2)), layers.Flatten(), layers.Dropout(0.5), layers.Dense(128, activation='relu'), layers.Dense(6, activation='softmax') ]) model_cnn.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])训练时设置batch_size=32,epochs=20。如果发现训练集准确率非常高但验证集徘徊不前,基本就是过拟合了,优先降低神经元数量、增加Dropout,或者增强数据扩充。遥感图像数据量通常不大,这点尤其需要注意。
3.4 LSTM用序列方式处理遥感图像
LSTM是循环神经网络的一种变体,专门用于处理时间序列、文本等序列数据。图像本身是二维结构,按理说不是LSTM的强项,但为了完成课程设计里的算法对比,还是要实现一版。
常见做法是把一张64x64的图像看成由64个时间步组成的序列,每个时间步输入当前行的64个像素。这样LSTM可以逐行“扫描”图像,理论上能学习行与行之间的空间依赖关系。但因为图像是二维的,这种按行扫描的方式会丢失上下文的局部关系,效果通常不如CNN。
我搭建的LSTM模型:
model_lstm = models.Sequential([ layers.Input(shape=(64, 64, 3)), layers.TimeDistributed(layers.Flatten()), layers.LSTM(128, return_sequences=True), layers.LSTM(64), layers.Dropout(0.5), layers.Dense(6, activation='softmax') ])这里注意Input是64x64x3的形式,但LSTM期望输入格式是(时间步, 特征维度)。我用的TimeDistributed(Flatten)先把每个时间步的3通道像素合并成一行,但这样会丢失颜色通道的结构。更直接的做法是在前面加一个CNN特征提取器,把图像先压缩成特征序列再输入LSTM,效果会好很多。但课程设计里为了体现LSTM的“序列建模”特点,我用的是纯LSTM方案,这样和CNN的对比更强烈。
LSTM训练时容易受到梯度不稳定影响,调低学习率到0.0005,并配合早停机制,观察验证集损失如果连续3轮不降就停止训练。实际跑下来,LSTM准确率大概比CNN低8到10个点,这说明单纯把图像强行转成序列并不合理,但如果加上CNN特征提取,LSTM又能发挥序列建模优势。这部分分析写在报告里,老师会觉得你有深度。
4. 训练流程与结果对比分析
4.1 训练流程与结果整理
训练流程统一为:读取数据、预处理、划分数据集、训练模型、保存模型和预测结果、计算评估指标、绘制混淆矩阵。为了对比公平,四个模型全部使用相同的数据划分和相同的随机种子。
SVM和KNN训练很快,几秒到十几秒就结束;CNN大概需要3到5分钟一轮;LSTM耗时略高于CNN。以下是我在实际数据集上跑出来的参考结果:
| 算法 | 准确率 | 精确率(均值) | 召回率(均值) | F1-score | 训练耗时(约) |
|---|---|---|---|---|---|
| SVM | 86.4% | 86.7% | 86.2% | 86.4% | 12秒 |
| KNN | 78.9% | 79.7% | 78.5% | 79.0% | 0.5秒 |
| CNN | 92.7% | 92.9% | 92.5% | 92.7% | 3分钟每轮 |
| LSTM | 83.1% | 83.5% | 82.8% | 83.1% | 4分钟每轮 |
从结果可以看出,CNN明显优于其他三种算法,SVM则是最能打的传统方法。KNN虽然简单,但特征维度高、样本数量大时计算代价高,准确率也最有限。LSTM比KNN好,但离CNN还有距离。这个结果完全符合预期,也可以作为你课设报告里的核心论据。
4.2 怎么从工程上理解这些结果
有同学可能会问,既然CNN效果最好,为什么还要费劲做SVM、KNN和LSTM?这个问题在答辩时几乎必问。
从工程角度看,每种算法都有自己的适用场景。SVM在小样本、高维特征下依然稳定,很多传统遥感图像处理业务还在用;KNN实现简单、可解释性强,适合做baseline;LSTM在时间序列遥感数据(比如多时相影像变化检测)里价值更大,直接拿来做单张图像分类其实限制了它的优势。CNN效果最好,但它需要更多数据、更长训练时间和更强的计算资源。课程设计做四种算法对比,本质上是培养“根据任务选模型”的意识,而不是一味追求最高准确率。
另外我建议把混淆矩阵画出来,重点关注容易混淆的类别。从我的结果来看,草地和农田之间误分较多,因为光谱特征比较接近;水域和建筑则分得很好,因为颜色和纹理差异大。这类分析能极大丰富你的报告内容。
5. 常见问题与避坑指南
5.1 数据加载和内存溢出怎么办
遥感图像原始分辨率很高,一次性把所有图片读入内存很容易导致OOM。我一开始图省事,直接加载了两千张128x128的图片,结果内存溢出好几次。后来把图片统一缩到64x64,并使用批量加载的方式缓解。如果内存依然不够,可以在预处理阶段把图片压缩保存成.npy数组,训练时再分段读取。
5.2 过拟合问题排查
四种算法里,CNN和LSTM最容易过拟合。判断方法很直接:训练集准确率接近100%,但验证集准确率明显低。解决办法按优先级排列是数据增强、增加Dropout、减小模型容量、使用早停。SVM和KNN过拟合概率相对较低,但如果特征维数过高也容易过拟合,所以我才加了PCA降维。
5.3 LSTM训练不收敛怎么调
LSTM在图像序列输入下很容易出现损失不下降的情况。我遇到过一次,原因是输入数据没有归一化干净,像素值还有部分超过1;后来统一用float32除以255就解决了。如果还是收敛慢,把学习率降到0.0001,或者把return_sequences去掉只留最后一层LSTM输出,能减少参数复杂度。
5.4 答辩时常被追问的几个点
老师一般不会只看代码,还会问原理。常见问题有:SVM核函数为什么选RBF;KNN的K值怎么选;CNN为什么比全连接网络适合图像;LSTM里的“遗忘门”到底起到了什么作用。我把我自己的回答思路列出来,供你参考。
- RBF核可以映射到无限维,对非线性分类效果好。如果数据量特别大,线性核可能更高效。
- K值通过交叉验证选择,K过小容易受噪声点影响,K过大容易被其他类别的样本带偏。
- CNN通过卷积核共享权重,大幅减少参数数量,同时局部感受野符合图像的空间特性。
- LSTM的遗忘门控制哪些历史信息需要保留,哪些要丢弃,这让模型能抓住序列中的长期依赖。
6. 项目文档编写与代码结构建议
6.1 源码目录怎么组织
课设不仅看算法效果,还看代码规范和文档完整度。我的项目目录结构是:
remote_sensing_classification/ ├── data/ # 原始图像和标签 ├── features/ # 特征提取后的临时文件 ├── models/ # 保存训练好的模型 ├── src/ │ ├── data_preprocess.py │ ├── train_svm.py │ ├── train_knn.py │ ├── train_cnn.py │ ├── train_lstm.py │ └── evaluate.py ├── docs/ │ └── 详细说明文档.md └── requirements.txt每个训练脚本独立运行,最后统一调用evaluate.py输出结果对比。这样既方便自己调试,也方便老师复现代码。
6.2 说明文档需要包含哪些内容
文档里至少要写清楚这几块:项目背景、数据集描述、环境配置步骤、四种算法的核心原理、代码运行说明、实验结果对比、结论与反思。不要贴大段源码,而是放关键代码片段并解释。最后附上运行环境版本,方便别人复现。这份文档我写了大约20页,其中结果分析和结论占了将近一半篇幅,答辩时老师翻起来会觉得工作量很扎实。
另外,文档里一定要写“实验局限性”,比如数据类别数量有限、LSTM直接用于图像不是最优方案、没有调参到极致等。主动承认不足,比被老师挑出问题要好得多。
7. 写在最后的实操体会
做完这个课设,我最大的体会是算法对比的重点不在于把某个指标刷到满分,而是真正理解每种方法背后的假设和适用边界。SVM和KNN让我明白了特征工程的价值,CNN让我体会到自动特征提取的威力,LSTM则让我意识到没有万能的模型,只有适不适合当前任务。
如果时间有限,我建议先把SVM和CNN跑通,这两条线能拿到基本盘;如果有余力,再深入做KNN的PCA降维对比和LSTM的特征序列改造。千万别一上来就追求最复杂的模型,课设的核心是逻辑完整、实验结果可信、原理讲清楚。希望这篇文章能帮你少走一点弯路,顺利搞定这个遥感图像识别项目。
本文还有配套的精品资源,点击获取