基于深度学习的遥感图像分类识别系统,使用PyTorch框架实现

 取5个场景

['海滩', '灌木丛', '沙漠', '森林', '草地']

划分数据集 train:val:test = 7:2:1

环境依赖

pytorch==1.1 or 1.0

tensorboard==1.8

tensorboardX

pillow

注意调低batch_size参数特别是像我这样的渣渣显卡

使用方法

只需要指明数据集路径参数即可,就可以得到最终模型以及log、tensorboard_log了

train:开始训练

python train_resnet.py 

数据集文件夹应为 之下的目录结构应如下:

your data_dir/
       |->train
       |->val
       |->test
       |->ClassnameID.txt

#运行生成result.txt

python infer.py

cpu跑的验证集:

correct:697/704=0.9901

trian_resnet.py
# -*- coding: utf-8 -*-

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader
import torch.optim as optim
from tensorboardX import SummaryWriter

import numpy as np
import time
import datetime
import argparse
import os
import os.path as osp
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
from rs_dataset import RSDataset
from get_logger import get_logger
from res_network import Resnet50
# gpu or not
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

def parse_args():
    parse = argparse.ArgumentParser()
    parse.add_argument('--epoch',type=int,default=10)       #迭代次数
    parse.add_argument('--schedule_step',type=int,default=2)

    parse.add_argument('--batch_size',type=int,default=64)           #根据自己的口袋,调大小   batch_size
    parse.add_argument('--test_batch_size',type=int,default=32)
    parse.add_argument('--num_workers', type=int, default=2)        #default = 8 线程数

    parse.add_argument('--eval_fre',type=int,default=2)
    parse.add_argument('--msg_fre',type=int,default=10)
    parse.add_argument('--save_fre',type=int,default=2)
    parse.add_argument('--name',type=str,default='res50_baseline', help='unique out file name of this task include log/model_out/tensorboard log')

    #local  :数据集路径
    parse.add_argument('--data_dir',type=str,default='D:/RSdata_dir/gra_data_dir/')            #/mnt/rssrai_cls/
    parse.add_argument('--log_dir',type=str, default='./logs')
    parse.add_argument('--tensorboard_dir',type=str,default='./tensorboard')
    parse.add_argument('--model_out_dir',type=str,default='./model_out')
    parse.add_argument('--model_out_name',type=str,default='final_model.pth')
    parse.add_argument('--seed',type=int,default=5,help='random seed')
    return parse.parse_args()

def evalute(net,val_loader,writer,epoch,logger):
    logger.info('------------after epo {}, eval...-----------'.format(epoch))
    total=0
    correct=0
    net.eval()
    with torch.no_grad():
        for img,lb in val_loader:
            img, lb = img.to(device), lb.to(device)
            outputs = net(img)
            outputs = F.softmax(outputs,dim=1)
            predicted = torch.max(outputs,dim=1)[1]
            total += lb.size()[0]

            correct += (predicted == lb).sum().cpu().item()
    logger.info('correct:{}/{}={:.4f}'.format(correct,total,correct*1./total,epoch))
    #tensorboard-acc
    writer.add_scalar('acc',correct*1./total,epoch)
    net.train()

def main_worker(args,logger):
    try:
        writer = SummaryWriter(logdir=args.sub_tensorboard_dir)

        train_set = RSDataset(rootpth=args.data_dir,mode='train')
        train_loader = DataLoader(train_set,
                                  batch_size=args.batch_size,
                                  drop_last=True,
                                  shuffle=True,
                                  pin_memory=True,
                                  num_workers=args.num_workers)

        val_set = RSDataset(rootpth=args.data_dir,mode='val')
        val_loader = DataLoader(val_set,
                                batch_size=args.test_batch_size,
                                drop_last=True,
                                shuffle=True,
                                pin_memory=True,
                                num_workers=args.num_workers)

        net = Resnet50()
        net = net.train()
        input_ = torch.randn((1,3,224,224))
        #writer.add_graph(net,input_)

        #设置cuda
        #net = net.cuda()
        net = net.to(device)

        criterion = nn.CrossEntropyLoss().to(device)

        optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) #优化器

        scheduler = optim.lr_scheduler.StepLR(optimizer,step_size=args.schedule_step,gamma=0.3)

        loss_record = []

        iter = 0
        running_loss = []
        st = glob_st = time.time()
        total_iter = len(train_loader)*args.epoch
        for epoch in range(args.epoch):

            # 评估
            if epoch!=0 and epoch%args.eval_fre == 0:
            # if epoch%args.eval_fre == 0:
                evalute(net, val_loader, writer, epoch, logger)

            if epoch!=0 and epoch%args.save_fre == 0:
                model_out_name = osp.join(args.sub_model_out_dir,'out_{}.pth'.format(epoch))
                # 防止分布式训练保存失败
                state_dict = net.modules.state_dict() if hasattr(net, 'module') else net.state_dict()
                torch.save(state_dict,model_out_name)

            for img, lb in train_loader:
                iter += 1
                img = img.to(device)
                lb = lb.to(device)

                optimizer.zero_grad()

                outputs = net(img)
                loss = criterion(outputs,lb)

                loss.backward()
                optimizer.step()

                running_loss.append(loss.item())

                if iter%args.msg_fre ==0:
                    ed = time.time()
                    spend = ed-st
                    global_spend = ed-glob_st
                    st=ed

                    eta = int((total_iter-iter)*(global_spend/iter))
                    eta = str(datetime.timedelta(seconds=eta))
                    global_spend = str(datetime.timedelta(seconds=(int(global_spend))))

                    avg_loss = np.mean(running_loss)
                    loss_record.append(avg_loss)
                    running_loss = []

                    lr = optimizer.param_groups[0]['lr']

                    msg = '. '.join([
                        'epoch:{epoch}',
                        'iter/total_iter:{iter}/{total_iter}',
                        'lr:{lr:.5f}',
                        'loss:{loss:.4f}',
                        'spend/global_spend:{spend:.4f}/{global_spend}',
                        'eta:{eta}'
                    ]).format(
                        epoch=epoch,
                        iter=iter,
                        total_iter=total_iter,
                        lr=lr,
                        loss=avg_loss,
                        spend=spend,
                        global_spend=global_spend,
                        eta=eta
                    )
                    logger.info(msg)
                    writer.add_scalar('loss',avg_loss,iter)
                    writer.add_scalar('lr',lr,iter)

            scheduler.step()
        # 训练完最后评估一次
        evalute(net, val_loader, writer, args.epoch, logger)

        out_name = osp.join(args.sub_model_out_dir,args.model_out_name)
        torch.save(net.cpu().state_dict(),out_name)

        logger.info('-----------Done!!!----------')

    except:
        logger.exception('Exception logged')
    finally:
        writer.close()

if __name__ == '__main__':

    args = parse_args()
    #为CPU设置种子用于生成随机数,以使得结果是确定的
    torch.manual_seed(args.seed)
    torch.manual_seed(args.seed)

    # 唯一标识
    unique_name = time.strftime('%y-%m%d-%H%M%S_') + args.name
    args.unique_name = unique_name

    # 每次创建作业使用不同的tensorboard目录
    args.sub_tensorboard_dir = osp.join(args.tensorboard_dir, args.unique_name)
    # 保存模型的目录
    args.sub_model_out_dir = osp.join(args.model_out_dir, args.unique_name)

    # 创建所有用到的目录
    for sub_dir in [args.sub_tensorboard_dir,args.sub_model_out_dir,  args.log_dir]:
        if not osp.exists(sub_dir):
            os.makedirs(sub_dir)

    log_file_name = osp.join(args.log_dir,args.unique_name + '.log')
    logger = get_logger(log_file_name)

    for k, v in args.__dict__.items():
        logger.info(k)
        logger.info(v)

    main_worker(args,logger=logger)

界面gui.py

#!/bin/python

import wx
from PIL import Image
import numpy as np
import os
from tst import prediect


#文件-hello
def OnHello(event):
    wx.MessageBox("遥感图像识别")

#关于
def OnAbout(event):
    """Display an About Dialog"""
    wx.MessageBox("这是一个识别单张图像的界面-罗",
                  "关于 Hello World",
                  wx.OK | wx.ICON_INFORMATION)


class HelloFrame(wx.Frame):

    def __init__(self,*args,**kw):
        super(HelloFrame,self).__init__(*args,**kw)

        pnl = wx.Panel(self)

        self.pnl = pnl

        st = wx.StaticText(pnl, label="选择一张图像进行识别", pos=(200, 0))
        font = st.GetFont()
        font.PointSize += 10
        font = font.Bold()
        st.SetFont(font)

        # 选择图像文件按钮
        btn = wx.Button(pnl, -1, "select",pos=(4,4))
        btn.SetBackgroundColour("#0a74f7")
        #事件
        btn.Bind(wx.EVT_BUTTON, self.OnSelect)


        self.makeMenuBar()

        self.CreateStatusBar()
        self.SetStatusText("欢迎来到图像识别系统")

    #菜单栏
    def makeMenuBar(self):
        fileMenu = wx.Menu()
        helloItem = fileMenu.Append(-1, "&Hello...\tCtrl-H",
                                    "Help string shown in status bar for this menu item")
        fileMenu.AppendSeparator()

        exitItem = fileMenu.Append(wx.ID_EXIT)
        helpMenu = wx.Menu()
        aboutItem = helpMenu.Append(wx.ID_ABOUT)

        menuBar = wx.MenuBar()
        menuBar.Append(fileMenu, "&File")
        menuBar.Append(helpMenu, "Help")

        self.SetMenuBar(menuBar)

        self.Bind(wx.EVT_MENU, OnHello, helloItem)
        self.Bind(wx.EVT_MENU, self.OnExit, exitItem)
        self.Bind(wx.EVT_MENU, OnAbout, aboutItem)
    #退出
    def OnExit(self, event):
        self.Close(True)

    #select按钮设置
    def OnSelect(self, event):
        wildcard = "image source(*.jpg)|*.jpg|" \
                   "Compile Python(*.pyc)|*.pyc|" \
                   "All file(*.*)|*.*"
        dialog = wx.FileDialog(None, "Choose a file", os.getcwd(),
                               "", wildcard, wx.ID_OPEN)
        if dialog.ShowModal() == wx.ID_OK:

            print(dialog.GetPath())
            img = Image.open(dialog.GetPath())
            imag = img.resize([128, 128])
            image = np.array(img)

            self.initimage(name= dialog.GetPath())

            #从tst.py获取 结果
            result = prediect(image)


            result_text = wx.StaticText(self.pnl, label='', pos=(600, 400), size=(150,50))
            result_text.SetLabel(result)

            font = result_text.GetFont()
            font.PointSize += 8
            result_text.SetFont(font)
            self.initimage(name= dialog.GetPath())

# 生成图片控件
    def initimage(self, name):
        imageShow = wx.Image(name, wx.BITMAP_TYPE_ANY)
        sb = wx.StaticBitmap(self.pnl, -1, imageShow.ConvertToBitmap(), pos=(0,30), size=(600,400))
        return sb


if __name__ == '__main__':

    app = wx.App()
    frm = HelloFrame(None, title='老罗的识别器', size=(1000,600))
    frm.Show()
    app.MainLoop()

影像分类


打开ENVI,选择主菜单->Classificatio->Unsupervised->IsoData或者K-mean。如选择IsoData,在选择文件时,可以设置空间或光谱裁剪区。如选择Can-tmr.ing,按默认设置,之后跳出参数设置,如ISODATA非监督分类结果。

 类别定义
在display中显示原始影像,在display->overlay->classification,选择ISODATA分类结果,如图所示,在Interactive Class Tool面板中,可以选择 各个分类结果显示。如图


Interactive Class Tool面板中,选择Option->Edit class colors/names。 通过目视或者其他方式识别分类结果,填写相应的类型名称和颜色。

如图

示为最终结果。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: PyTorch是一个基于Python开发的机器学习框架,它拥有丰富的工具和功能,适用于各种任务,包括遥感图像地物分类。遥感图像地物分类是指通过对遥感图像进行分析和识别,将不同地物分类为不同的类别,如建筑、道路、植被等。 在PyTorch实现遥感图像地物分类可以遵循以下步骤: 1. 数据准备:首先,需要准备用于训练和评估的遥感图像数据集。可以从公开数据集中获取,或者根据实际需要收集和整理数据集。 2. 数据加载:使用PyTorch的数据加载器,将图像数据集加载到内存中,并对数据集进行预处理,如裁剪、缩放和标准化等。 3. 模型设计:选择适合遥感图像分类的模型架构,如卷积神经网络(CNN)。可以使用PyTorch提供的模型库,如ResNet、VGG等,也可以自定义模型。 4. 模型训练:将加载的图像数据集输入到模型中,通过定义损失函数和优化器,使用PyTorch提供的自动求导功能,进行模型训练。可以根据需要设置训练的迭代次数、学习率等超参数,并周期性地评估模型的性能。 5. 模型评估:训练完成后,使用测试集对模型进行评估,计算分类精度、查准率、查全率等指标,评估模型的性能。 6. 模型应用:经过训练和评估后,可以使用该模型对新的遥感图像进行分类预测。将新的图像输入到模型中,经过前向传播计算,得到图像的预测类别。 总而言之,通过PyTorch实现遥感图像地物分类可以借助其强大的机器学习功能和便捷的开发环境,快速高效地完成图像分类任务。同时,PyTorch还提供了丰富的工具和库,方便用户进行模型设计、训练和评估,并具有良好的可扩展性和灵活性,满足不同用户的需求。 ### 回答2: PyTorch是一个常用的深度学习框架,它提供了丰富的功能和工具,可以用于遥感图像地物分类任务的实现。在知乎上,关于PyTorch实现遥感图像地物分类的问题,可能会有一些相关的回答。 首先,我们需要准备好用于训练的遥感图像数据集。可以使用公开的遥感图像数据集,或者是自己收集的数据集。数据集应包含不同类别的地物图像样本,并且要进行适当的标注。 接下来,我们可以使用PyTorch的数据处理工具,如`torchvision`来加载和预处理图像数据。可以使用`torch.utils.data.Dataset`构建一个自定义的数据集类,根据需要对图像进行预处理操作,如缩放、裁剪、归一化等。 然后,我们可以使用PyTorch搭建一个卷积神经网络(CNN)模型,用于图像分类任务。可以根据具体的需求选择不同的网络结构,如ResNet、VGG等。可以使用`torch.nn`模块来构建自定义的网络模型,包括卷积层、池化层、全连接层等。 在模型搭建完成后,我们需要定义损失函数和优化器来进行训练。常用的损失函数有交叉熵损失函数(CrossEntropyLoss),可以通过`torch.nn.CrossEntropyLoss`来定义。优化器可以选择Adam、SGD等,可以使用`torch.optim`模块来构建。 接着,我们可以编写训练循环,使用训练数据来迭代训练模型。可以使用`torch.utils.data.DataLoader`来创建一个数据迭代器,方便获取批量的数据样本。然后,依次将数据输入到模型中,计算损失函数,并通过优化器来更新模型参数。 在训练过程中,可以使用一些技巧来提高模型性能,如数据增强、学习率调整等。可以通过`torchvision.transforms`来实现数据增强操作,如随机裁剪、随机旋转等。可以使用学习率调整器(Learning Rate Scheduler)来动态调整学习率,如StepLR、ReduceLROnPlateau等。 最后,在训练完成后,我们可以使用测试数据对模型进行评估。可以使用测试数据集来验证模型的泛化能力,并计算评估指标,如准确率、召回率等。 总之,使用PyTorch实现遥感图像地物分类是一个相对复杂的任务,但通过合理的数据处理、模型搭建和优化方法,可以有效实现。知乎上也有很多关于这一问题的讨论和分享,可以帮助我们更好地理解和实践相关内容。 ### 回答3: pytorch是一个常用的深度学习框架,可以用于遥感图像地物分类任务的实现。在pytorch中,可以利用卷积神经网络(CNN)进行图像分类任务。 首先,需要准备好遥感图像的数据集。数据集应包含标注好的遥感图像样本,以及每个样本对应的地物分类标签。接下来,可以利用pytorch的数据加载工具,如torchvision库中的datasets模块,将数据集按照一定的比例划分为训练集、验证集和测试集。 然后,可以利用pytorch的模型类来定义一个卷积神经网络模型。模型的结构可以根据具体任务进行设计,一般建议包含多个卷积层、池化层和全连接层。可以根据需要,使用不同的卷积核大小、步幅和激活函数等。 在模型定义好后,可以利用pytorch的优化器类定义一个优化器,如Adam优化器。优化器可以控制模型的权重更新方式,在训练过程中调整学习率和动量等超参数。 接下来,可以利用pytorch的训练循环来训练模型。训练循环包括多个迭代的训练阶段,每个阶段包括前向传播、计算损失、反向传播和模型权重更新等步骤。可以利用pytorch的损失函数类定义一个损失函数,如交叉熵损失函数。在训练过程中,通过最小化损失函数来优化模型的权重。 在训练结束后,可以利用验证集来评估模型的性能,并根据需要进行调参和优化。最后,可以利用测试集对训练好的模型进行评估,并根据评估结果进行后续的地物分类任务。 总之,pytorch可以提供一个灵活、高效的深度学习框架,用于实现遥感图像地物分类任务。通过合理设计模型结构、选择合适的优化器和损失函数,以及使用训练循环和数据加载工具等功能,可以实现高准确率的地物分类模型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值