【GIS系列】多源异构原始影像解析:策略模式与规则引擎的应用

news2024/11/15 17:21:27

作者:后端小肥肠

🍇 我写过的文章中的相关代码放到了gitee,地址:xfc-fdw-cloud: 公共解决方案

🍊 有疑问可私信或评论区联系我。

🥑  创作不易未经允许严禁转载。

1. 前言

在遥感技术和地球观测领域,处理多源异构原始影像数据是一个关键挑战。随着卫星和传感器技术的进步,我们获得了前所未有的数据多样性。本文将介绍一个为这些数据量身定制的解析系统,该系统结合了策略模式和规则引擎,旨在提供一个灵活、高效且可扩展的数据处理平台,以应对不断增长的数据处理需求。

2. 项目背景

在遥感技术和地球观测领域,处理和分析多源异构原始影像数据已成为一项至关重要的任务。随着卫星技术的不断发展,来自不同传感器、不同平台的原始影像数据呈现出多样化和复杂化的特点。这些数据包括但不限于光学影像、雷达影像、高光谱影像等,每种类型都有其独特的数据结构和元数据信息。我之前博客针对不同各类原始影像数据格式和元数据信息进行过详细梳理:【GIS系列】卫星遥感影像简介及格式梳理-CSDN博客

有效地解析和管理这些多源异构的原始影像数据,对于地质调查、环境监测、城市规划、农业管理等多个领域都具有重要意义。然而,由于数据来源的多样性和复杂性,传统的数据处理方法往往难以满足需求。

本文将介绍一个专门针对多源异构原始影像数据设计的解析系统,探讨如何构建一个灵活、高效、可扩展的数据处理平台。本文仅对如何解析多源异构数据提供解决方案思路,不无偿提供源码。

3. 系统现状与挑战

目前,在处理多源异构原始影像数据时,我们面临以下挑战:

1. 数据格式多样性:不同卫星、不同传感器产生的原始影像数据格式各不相同,包括但不限于GeoTIFF、HDF、NITF等。

2. 元数据结构差异: 各类影像的元数据结构存在显著差异,如何统一解析和存储这些元数据是一大难题。

3. 数据量巨大:遥感影像数据通常体积庞大,如何高效处理和存储是一个挑战。

4. 实时性要求:某些应用场景(如灾害监测)需要近实时的数据处理能力。

5. 扩展性需求:随着新型传感器和卫星的不断发布,系统需要能够快速适应新的数据类型。

6. 质量控制: 原始影像数据可能存在噪声、畸变等问题,需要在解析过程中进行初步的质量评估。

为了应对这些挑战,我们设计了一个基于策略模式和规则引擎的多源异构原始影像数据解析系统。这个系统具有高度的灵活性和可扩展性,能够有效处理各种复杂的原始影像数据。

4. 核心技术实现

多源异构原始影像解析入库流程图如下:

上述流程图从前端、后端及数据库三个角度来呈现原始影像入库流程,首先由前端将文件路径传递给后台,后台基于规则引擎将影像映射到策略工厂,找到影像解析对应类,之后由解析类中的方法解析元数据,若解析成功则将元数据写入数据库同时写入成功日志流程结束,若解析失败则写入失败日志流程结束。 下文将介绍解析流程中涉及的核心技术栈。

4.1. 策略模式

策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以互相替换,让算法的变化独立于使用算法的客户。客户端代码通过持有一个策略接口的引用来使用特定的算法,在运行时可以动态地切换不同的算法。

4.1.1. 多源异构影像解析策略模式部分核心代码

在多源原始影像元数据解析中引入了策略模式,前端只需要输入文件路径,根据策略模式建立的路由后台即可动态解析不同类型影像并写入数据库。

策略模式的路由策略主要在策略工厂中定义路由Map,以Map键值对的形式实现:

private static  Map<String, Function<File,Boolean>> handleMap = null;
@PostConstruct
public void init(){
    handleMap=new HashMap<>();
    handleMap.put("GF1B_PMS", originalImageFile -> gf1BPMSHandleService.saveMetadata(originalImageFile));
    handleMap.put("GF1C_PMS", originalImageFile -> gf1CPMSHandleService.saveMetadata(originalImageFile));
    handleMap.put("GF1D_PMS", originalImageFile -> gf1DPMSHandleService.saveMetadata(originalImageFile));
    handleMap.put("GF1_PMS1", originalImageFile -> gf1PMS1HandleService.saveMetadata(originalImageFile));
    handleMap.put("GF1_PMS2", originalImageFile -> gf1PMS2HandleService.saveMetadata(originalImageFile));
    handleMap.put("GF6_PMS", originalImageFile -> gf6PMSHandleService.saveMetadata(originalImageFile));
    handleMap.put("GF6_WFV", originalImageFile -> gf6WFVHandleService.saveMetadata(originalImageFile));
    handleMap.put("GF2_PMS1", originalImageFile -> gf2PMS1HandleService.saveMetadata(originalImageFile));
    handleMap.put("GF2_PMS2", originalImageFile -> gf2PMS2HandleService.saveMetadata(originalImageFile));
    handleMap.put("BJ3B1_PMS", originalImageFile -> bj3B1PMSHandleService.saveMetadata(originalImageFile));
    handleMap.put("GF5_AHSI", originalImageFile -> gf5AHSIHandleService.saveMetadata(originalImageFile));
    handleMap.put("LT5_TM", originalImageFile -> lt5TMHandleService.saveMetadata(originalImageFile));
    handleMap.put("LT05_TM", originalImageFile -> lt05TMHandleService.saveMetadata(originalImageFile));
    handleMap.put("LC08_OLI", originalImageFile -> lc08OLIHandleService.saveMetadata(originalImageFile));
    handleMap.put("LC09_OLI", originalImageFile -> lc09OLIHandleService.saveMetadata(originalImageFile));
    handleMap.put("GF701_BWD", originalImageFile -> gf701BWDHandleService.saveMetadata(originalImageFile));
    handleMap.put("GF701_MUX", originalImageFile -> gf701MUXHandleService.saveMetadata(originalImageFile));
    handleMap.put("ZY1E_VNIC", originalImageFile-> zy1EVNICHandleService.saveMetadata(originalImageFile));
    handleMap.put("zy302a_mux", originalImageFile-> zy302MUXHandleService.saveMetadata(originalImageFile));
    handleMap.put("zy302a_nad", originalImageFile -> zy302NADHandleService.saveMetadata(originalImageFile));
    handleMap.put("HJ2B_CCD4", originalImageFile -> hj2BCCD4HandleService.saveMetadata(originalImageFile));
    handleMap.put("BJ3N1", originalImageFile -> bj3N1PMSHandleService.saveMetadata(originalImageFile));
    handleMap.put("TRIPLESAT_1_PMS",
            originalImageFile -> triplesat1PMSHandleService.saveMetadata(originalImageFile));
    handleMap.put("JL1GF02A_PMS2", originalImageFile -> jl1GF02APMS2HandleService.saveMetadata(originalImageFile));
    handleMap.put("JL1KF01C_PMSR1",
            originalImageFile -> jl1KF01CPMSR1HandleService.saveMetadata(originalImageFile));
    handleMap.put("DP01_PMS", originalImageFile -> dp01PMSHandleService.saveMetadata(originalImageFile));
    handleMap.put("CB04A_WPM", originalImageFile -> cb04AWPMHandleService.saveMetadata(originalImageFile));
    handleMap.put("S1A_SAR", originalImageFile -> s1ASARHandleService.saveMetadata(originalImageFile));
    handleMap.put("S2A_SAR", originalImageFile -> s2ASARHandleService.saveMetadata(originalImageFile));
    handleMap.put("S2B_SAR", originalImageFile -> s2BSARHandleService.saveMetadata(originalImageFile));
    handleMap.put("GF3_SYC",originalImageFile->gf3SARHandleService.saveMetadata(originalImageFile));
}

在handleMap中以影像文件名的部分为键值,真实解析方法为map值,以达到用文件名作为路由的目的。 

public void saveMetadata(String imageType, File originalImageFile){
    handleMap.get(imageType).apply(originalImageFile);
}

 直接引用策略工厂的saveMetadata方法即可实现根据文件路径解析不同类型影像。

4.1.2. 策略模式的意义

多源异构影像解析中,我们采用的Map映射的方式,用Map键代表不同路由策略,以上两种设计均使用了策略模式的思想,具体体现在以下几个方面:

  1. 独立的路由策略实现: 每个枚举值对应一种具体的任务路由策略,这样可以将不同的路由策略实现封装到不同的类中,实现了算法的独立性。
  2. 扩展性: 可以轻松地向系统中添加新的路由策略,只需添加对应的枚举值和相应的路由策略实现类。这样做符合开闭原则,使得系统更容易扩展。
  3. 动态切换策略: 策略模式使得在运行时可以动态地切换任务路由策略,而不需要修改调度系统的核心代码。这增加了系统的灵活性。
  4. 清晰的接口定义: 通过策略模式,可以为每种路由策略定义清晰的接口,包括了选择执行器的逻辑。这样,不同的路由策略实现可以按照相同的接口定义来实现。

在项目中,策略模式的运用使得任务的路由策略更加灵活和可扩展,使得系统能够适应不同的业务场景和调度需求。

4.2. 规则引擎

规则引擎是一种软件系统或组件,专门设计用于管理和执行事先定义的业务规则。这些规则通常以条件-动作的形式存在,即当某些条件得到满足时,触发相应的动作。规则引擎通过将业务规则从应用程序中分离出来,提供了更灵活、易于维护的业务逻辑管理方式。网上查询了很多规则引擎框架,最终选择了Easy Rules,原因就是Easy Rules基于java写的,而且 设计简单,仅依赖少量的核心类库,易于集成和使用。

4.2.1. 规则引擎部分核心代码

在上一节中介绍了策略模式的概念以及多源原始影像解析功能中策略模式的使用细节,在策略模式中基于路由解析了不同类型影像写入数据库中,但还缺少一个桥梁,规则引擎正是作为桥梁将文件名称与策略模式的路由做了相关映射,使得多源原始影像元数据解析功能能完整串接起来。

1. 定义规则

我们需要根据不同类别的影像定义不同的规则,下述代码为高分1,2,5,6类别影像的规则:

@Rule(priority = 2)
public class GFRule {

    @Condition
    public boolean isGFImage(@Fact("fileFact") FileFact fileFact) {
        return "GF".equalsIgnoreCase(fileFact.getSplit()[0].substring(0, 2));
    }

    @Action
    public void saveMetadata(@Fact("fileFact") FileFact fileFact) {
        String[] split = fileFact.getSplit();
        fileFact.saveMetadata(split[0] + "_" + split[1], new File(fileFact.getFilePath()));
    }
}

@Condition注解标记计算规则条件的方法,return "GF".equalsIgnoreCase(fileFact.getSplit()[0].substring(0, 2))代码为截取文件名如为GF则符合规则。

@Action注解标记要执行规则操作的方法,fileFact.saveMetadata(split[0] + "_" + split[1], new File(fileFact.getFilePath()))代码为执行相应解析影像方法。

2. 定义事实

@Data
@AllArgsConstructor
public class FileFact {
    // 文件路径
    private String filePath;
    private String[] split;
    private ImageFactory imageFactory;

    public FileFact(String filePath, ImageFactory imageFactory) {
        this.filePath = filePath;
        this.imageFactory = imageFactory;
        File file = new File(filePath);
        split = file.getName().split("_");
    }

    public void saveMetadata(String imageType, File originalImageFile ) {
        imageFactory.saveMetadata(imageType,originalImageFile);
    }
}

3. 定义规则引擎调用组件

@Service
@Import(LTRule.class)
public class RuleService {
  //注入影像解析策略工厂
    @Resource
    ImageFactory imageFactory;

    private DefaultRulesEngine rulesEngine = null;
    private Rules rules = null;

    @PostConstruct
    public void init() {
        // 创建规则引擎,设置引擎参数 告诉引擎规则被触发时跳过后面的规则
        RulesEngineParameters parameters = new RulesEngineParameters()
                .skipOnFirstAppliedRule(true);
        rulesEngine = new DefaultRulesEngine(parameters);
        // 注册规则
        rules = new Rules();
        rules.register(new ZYRule());
        rules.register(new GFRule());
        rules.register(new GF7Rule());
        rules.register(new GF3Rule());
        rules.register(new LTRule());
        rules.register(new LT05Rule());
        rules.register(new LCRule());
        rules.register(new BJ3B1Rule());
        rules.register(new BJ3N1Rule());
        rules.register(new TripleSat1Rule());
        rules.register(new JL1AndDP01Rule());
        rules.register(new HJ2BRule());
        rules.register(new SARule());
    }


    public void matchRule(String filePath) {
        // 创建事实对象
        Facts facts = new Facts();
        FileFact fileFact = new FileFact(filePath, imageFactory);
        facts.put("fileFact", fileFact);
        // 开始映射
        rulesEngine.fire(rules, facts);
    }

}

这段代码定义了一个名为 RuleService 的服务类,使用 Spring 框架的特性进行配置。它初始化一个规则引擎,注册了一系列特定的规则来处理不同类型的影像文件。当传入一个文件路径时,这个服务通过匹配的规则动态决定如何解析文件并处理相关的元数据,使得系统能够灵活地应对各种遥感影像数据的处理需求。 

 5. 延展应用

虽然本文主要讨论了多源异构原始影像数据的解析,但这种基于策略模式和规则引擎的方法同样可以应用到其他相关领域:

1. 多源遥感数据融合:将不同类型的遥感数据(如光学和雷达数据)进行融合分析。

2. 历史影像数据处理: 处理和整合不同时期、不同来源的历史影像数据。

3. 实时遥感监测系统:构建能够实时接收和处理多源遥感数据的监测系统。

4. 卫星地面站数据管理: 管理和处理来自多个卫星地面站的数据流。

5. 遥感大数据分析平台:构建能够处理海量多源遥感数据的大数据分析平台。

这种方法为处理复杂的多源异构原始影像数据提供了一个灵活且可扩展的框架,也为其他类型的多源异构数据处理提供了有价值的参考。

 6. 结语

策略模式和规则引擎组合可以形成一套方法论用来解决多源异构数据解析的场景,此后有类似需求场景也可以使用这套方法论。若本文对你有启发和帮助,别忘记点点关注哦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2074062.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习周报(8.19-8.25

文章目录 摘要Abstract1.PyTorch环境的配置及安装使用PyCharm配置环境安装配置jupyter 2.两个Python常用函数3.DataSet4.TensorBoard的使用绘制一幅坐标图使用tendorboard对一幅图片进行操作 5.torchvison中的transforms总结 摘要 在之前学习了一些机器学习相关理论之后&#…

【限时免费发放】2000+热门Scratch作品源码

欢迎访问小虎鲸Scratch资源站&#xff01;在Scratch编程的学习过程中&#xff0c;优质的资源和灵感是至关重要的。因此&#xff0c;我们特别准备了这份【免费下载】的Scratch作品源码合集&#xff0c;包含超过2000个精选的Scratch项目源码&#xff0c;旨在为Scratch编程爱好者和…

Nginx+keepalived实现高可用

目录 一、准备工作 1、安装软件 二、配置master主服务器 1、修改nginx主配置文件 ​编辑 2、修改keepalived主配置文件 三、配置backup备服务器 四、配置节点服务器 1、配置第一个节点服务器 1.1、设置虚拟网卡 1.2、忽略ARP请求 1.3、安装并启动nginx软件 2、配置…

【STM32】SPI接口(非连续传输)

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 前言 SPI简介 IO口初始化 SPI配置 时钟使能 SPI初始化 SPI使能 数据接收与发送 硬件SPI代码 MySPI.h MySPI.c 前言 【通信协议】SPI总线-CSDN博客 本篇博客学习使用STM32的…

Expo 开发ReactNative 后切换 eas 账号

修改slug app.json中的sulg字段更新为新账号应用sulg 修改projectId app.json中的extra.eas.projectId字段更新为新账号应用projectId 退出账号&#xff1a; eas logout 重新登录&#xff1a; eas login

基于WEB的学生综合测评系统的设计与实现

第1章 绪 论 1.1 系统开发背景 随着计算机技术的不断发展,在现代化社会中,信息的处理越来越依赖计算机来完成。在没有测评系统之前&#xff0c;所有的信息记录都是由人工记录维护&#xff0c;不但不方便&#xff0c;还经常出错&#xff0c;有了测评系统就可以方便的对各种信息…

.net maui安卓开发中使用明文传输(一)

背景:最近在做一个pad上的项目,目的是执行每日点检功能(就是检查设备的各项保养指标);前期用HBuilder做了一个,但是现场的触摸屏选用的是TouchPie 安卓版本是6.0版本,上次开发的软件可以在安卓7.0上完美兼容,但由于触摸屏安卓版本太低不能兼容;询问厂商才知道这款触摸…

【Datawhale AI夏令营】从零上手CV竞赛Task1

【Datawhale AI夏令营】从零上手CV竞赛Task1 前言赛事官网学习任务TASK 1 前言 这个暑假我通过微信群关注到了【Datawhale AI夏令营】&#xff0c;并且记录我的代码学习以及调试的过程。 赛事官网 赛事官网&#xff1a;https://www.marsbigdata.com/competition/details?id…

RING总线(环形总线)Intel大小核的由来

想到Intel处理器&#xff0c;无一例外大家想到的就是现在的它具有大小核的结构&#xff0c;也就是性能核和效能核。这种结构的由来是由RING总线布局结构而诞生。ring总线&#xff08;环形总线&#xff09;&#xff0c;这个名字经常出现在讨论普通消费级处理器的时候&#xff0c…

算法【Java】—— 二分查找

二分查找算法分析 二分查找算法其实也是对撞指针的另一种用法&#xff0c;左右两个指针分别指向数据的左右端点&#xff0c;然后双指针向中间移动。 朴素二分查找 上面这道题是朴素的二分查找算法&#xff0c;由于数据是有序的&#xff0c;我们可以从中间值入手 如果中间值大…

国货之光|暴雨机推出面向大模型训练的AI服务器

当前&#xff0c;“百模大战”带来了算力需求的爆发&#xff0c;尤其是以ChatGPT为代表的多模态AI大模型&#xff0c;‌其参数规模和训练数据量均达到了前所未有的规模。‌GPT-3.5、‌GPT-4等模型的参数规模突破了万亿级别&#xff0c;‌训练数据量达到了TB级别&#xff0c;‌这…

AI多模态模型架构之模态生成器:Modality Generator

〔探索AI的无限可能&#xff0c;微信关注“AIGCmagic”公众号&#xff0c;让AIGC科技点亮生活〕 本文作者&#xff1a;AIGCmagic社区 刘一手 前言 AI多模态大模型发展至今&#xff0c;每年都有非常优秀的工作产出&#xff0c;按照当前模型设计思路&#xff0c;多模态大模型的…

Ai+若依(定时任务):【01篇】

若依为定时任务功能提供方便友好的web界面,实现动态管理任务。 案例 每间隔5秒,控制台输出系统时间。 实现步骤: ①创建任务类 在服务 ==》ruoyi-quartz==》task==》MyTask package com.ruoyi.quartz.task;import org.springframework.stereotype.Component;@Component…

程序员修炼之道 10:并发

不记录&#xff0c;等于没读。 这里是我阅读《程序员修炼之道》这本书的记录和思考。 并发和并行代码曾经是很新奇的玩意&#xff0c;但现在已经是标配。 并发 &#xff1a;Concurrency&#xff0c;指的是两个或更多个代码段在执行过程中表现得像是在同时运行一样。 并行 &am…

AD的3D模型格式是什么

AD通常指的是Altium Designer&#xff0c;这是一款用于电子设计自动化的软件&#xff0c;主要用于电路板的设计。在Altium Designer中&#xff0c;3D模型主要用于PCB&#xff08;印制电路板&#xff09;设计中的可视化&#xff0c;以便设计师能够在三维空间中查看组件和板的布局…

21:【stm32】定时器二:输入捕获

输出捕获 1、输出捕获的简介2、输入捕获原理2.1、输入滤波2.2、信号选择2.3、CCx事件和CCx中断 3、标准库编程 1、输出捕获的简介 定时器通过通道捕获输入电平的变化&#xff0c;而通道有CH1~CH4&#xff0c;这4个通道。 我们设定对通道CH3的输入电平进行捕获。假如CH3突然捕获…

Java排序算法详解

在Java编程中&#xff0c;排序算法是数据处理和算法设计中的基础且重要的部分。它们广泛应用于各种场景&#xff0c;如数据库管理、数据分析、图形界面排序等。掌握几种常见的排序算法对于提升程序效率和优化性能至关重要。本文将详细解析几种经典的Java排序算法&#xff0c;包…

OpenGL笔记二十之深度检测概念

OpenGL笔记二十之深度检测概念 —— 2024-08-25 晚上 bilibili赵新政老师的教程看后笔记 code review! 文章目录 OpenGL笔记二十之深度检测概念1.课程PPT截图2.运行3.代码 1.课程PPT截图 2.运行 3.代码 关键部分 main.cpp #include <iostream>#include "glfra…

【逐行注释】三维EKF的MATLAB代码|附下载链接

文章目录 程序概况源代码与注释运行结果代码块解析 程序概况 基于MATLAB的EKF&#xff08;扩展卡尔曼滤波&#xff09;代码解析。状态转移和观测都是非线性的&#xff0c;也就是说会涉及到雅克比矩阵的求解。我尽量将模型设计复杂一点&#xff0c;便于拿到手以后改成自己想要的…

C++类和对象(2)——拷贝构造函数

拷贝构造函数的语法 拷贝构造函数是构造函数的重载&#xff0c; 用于这种情况&#xff1a;用已经构造好的对象去给另一个对象初始化。 int main() {Date d1(2024, 8, 1);Date d2(d1);//用d1初始化d2return 0; } 我们以Date类为例子讲解一下。 class Date { public://全缺省…