(五)图像的标准假彩色合成

环境:Windows10专业版 + IDEA2021.2.3 + jdk11.0.1 + GDAL(release-1928-x64-gdal-3-5-2-mapserver-8-0-0) + OpenCV-460.jar

系列文章:

(一)Python+GDAL实现BSQ,BIP,BIL格式的相互转换

(二)BSQ,BIL,BIP存储格式的相互转换算法

(三)单波段图像的伪彩色合成:密度分割(含介绍OpenCV中的Mat类)

(四)图像的%2线性拉伸

(五)图像的标准假彩色合成

(六)图像的直方图均衡化

(七)图像的均值滤波

(八)图像的中值滤波

(九)图像的高斯低通滤波

(十)图像的梯度倒数加权平滑

(十一)图像的罗伯特梯度锐化

(十二)图像的Sobel梯度锐化

(十三)图像的拉普拉斯梯度锐化

目录

一、标准假彩色合成简介

二、算法流程

三、代码实现

四、实验结果

1、原图像

2、假彩色合成结果

3、ENVI中标准假彩色的合成结果


一、标准假彩色合成简介

标准假彩色合成是一种遥感影像处理技术,用于增强图像的视觉效果和地物信息的提取

标准假彩色合成通常涉及以下几个关键步骤:

1、波段选择:从多光谱遥感图像中选择三个不同的波段。这些波段通常是根据能够最大化地物特征差异的原则来选择的。

2、颜色赋予:将选定的波段分别赋予红、绿、蓝三种颜色。由于这些波段的波长与对应的颜色波长不同,因此合成后的图像颜色并不是地物的真实颜色。

3、图像合成:利用加色法原理,将赋予颜色的波段合成一张彩色图像。这种方法可以使得某些地物特征在视觉上更加突出,便于分析和识别。

4、应用:标准假彩色合成广泛应用于植被信息提取、土地利用分类、环境监测等领域。例如,在ENVI软件中,可以通过加载CIR(Color Infrared)功能快速实现标准假彩色合成。

二、算法流程

1、利用GDAL读取landset图像波段4,波段3,波段2的像素并存放在数组中

2、一张16位的图像,图像的每个像素点的像素值都由16位的二进制数表示,每个像素点的颜色有 2^16 = 65536 种可能,也就是说,图像的颜色区间被划分成了 65536份;同理,8位图像,图像的颜色区间被划分成了2^8 = 256份。

因为TIFF图像的颜色存储位数为16位,需要进行线性拉伸转换为8位,将16位转换成8位,即为将区间 [0,65535] 映射到 [0,255] ,算出每个波段像素的最大值和最小值,进行线性拉伸,

​将最小值 pmin 映射到1,这样不会造成像素丢失,最后得到像素值范围在[1,255]的图像

3、将拉伸后的4,3,2波段的像素数组分别赋予R,G,B通道利用OpenCV合成图像并存储

三、代码实现

import org.gdal.gdal.Band;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;

import java.util.ArrayList;

/**
 * @Author: HNUST_jue_chen
 * @Date: 2022/10/28/ 11:01
 * @Attention: 转载, 引用请注明出处
 */

//假彩色合成
public class FalseColorSynthesis {
    //加载本地动态链接库
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    //获得波段4,3,2
    public ArrayList<int[][]> getBands(String path) {
        //支持所有驱动
        gdal.AllRegister();
        //以只读方式读取数据存入Dataset类型里
        Dataset dataset = gdal.Open(path, gdalconstConstants.GA_ReadOnly);
        //获得图像的大小
        int rows = dataset.getRasterYSize();
        int cols = dataset.getRasterXSize();
        int count = dataset.getRasterCount();
        System.out.println(rows);
        System.out.println(cols);
        System.out.println(count);

        //获得需要的三个波段
        Band band4 = dataset.GetRasterBand(4);
        Band band3 = dataset.GetRasterBand(3);
        Band band2 = dataset.GetRasterBand(2);

        //定义波段三个二维数组存放三个波段的像素
        int[][] band4_arr = new int[rows][cols];
        int[][] band3_arr = new int[rows][cols];
        int[][] band2_arr = new int[rows][cols];

        //将三个波段的像素的像素存放入二维数组
        for (int i = 0; i < rows; i++) {
            //一次读取一行像素值
            band4.ReadRaster(0, i, cols, 1, band4_arr[i]);
            band3.ReadRaster(0, i, cols, 1, band3_arr[i]);
            band2.ReadRaster(0, i, cols, 1, band2_arr[i]);
        }

        //将三个二维数组存放在集合中
        ArrayList<int[][]> band_arr = new ArrayList<>();
        band_arr.add(band4_arr);
        band_arr.add(band3_arr);
        band_arr.add(band2_arr);

        return band_arr;
    }

    //获得本图像像素的最大值和最小值
    public int[] getMinMaxPixel(int[][] arr) {
        //先将数组的第一个数赋予最大值和最小值
        int min = arr[0][0];
        int max = arr[0][0];
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[0].length; j++) {
                //更新最小值
                if (arr[i][j] < min) {
                    min = arr[i][j];
                }
                //更新最大值
                if (arr[i][j] > max) {
                    max = arr[i][j];
                }
            }
        }

        //将最大值和最小值存入数组
        int[] minMaxArr = new int[2];
        minMaxArr[0] = min;
        minMaxArr[1] = max;
        return minMaxArr;
    }

    //将16位像素转换为8位像素,线性拉伸[a,b]到[c,d]
    //a=min,b=max,c=1,d=255
    //新像素值=(d-c)/(max-min)*(原像素值-min)+1
    public int[][] linearTo8Bit(int[][] arr, int min, int max) {
        //定义线性拉伸后的数组
        int[][] arr_linear = new int[arr.length][arr[0].length];
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[0].length; j++) {
                arr_linear[i][j] = (int) ((double) (255 - 1) / (max - min) * (arr[i][j] - min) + 1);
            }
        }
        return arr_linear;
    }

    //将三个波段合成为假彩色图像
    public Mat falseColorSynthesis(ArrayList<int[][]> arrayList) {
        //获得三个波段的数组
        int[][] band4_arr = arrayList.get(0);
        int[][] band3_arr = arrayList.get(1);
        int[][] band2_arr = arrayList.get(2);

        //定义存储三个波段的三通道数组
        int[][] image_arr = new int[band4_arr.length][band4_arr[0].length * 3];

        //Mat类三通道的的顺序为B,G,R,在标准假彩色合成中应该分别赋予band2,band3,band4
        for (int i = 0; i < image_arr.length; i++) {
            //将波段2赋予蓝色通道
            for (int j = 0; j < band2_arr[0].length; j++) {
                image_arr[i][3 * j] = band2_arr[i][j];
            }
            //将波段3赋予绿色通道
            for (int j = 0; j < band3_arr[0].length; j++) {
                image_arr[i][3 * j + 1] = band3_arr[i][j];
            }
            //将波段4赋予红色通道
            for (int j = 0; j < band4_arr[0].length; j++) {
                image_arr[i][3 * j + 2] = band4_arr[i][j];
            }
        }

        //定义假彩色图像
        Mat mat = new Mat(band2_arr.length, band2_arr[0].length, CvType.CV_32SC3);
        //将像素放入图像
        for (int i = 0; i < image_arr.length; i++) {
            //一次放入一行三通道像素值
            mat.put(i, 0, image_arr[i]);
        }
        return mat;
    }

    public static void main(String[] args) {
        FalseColorSynthesis fsc = new FalseColorSynthesis();
        ArrayList<int[][]> band_arr = fsc.getBands("D:\\Project\\IDEA_Project\\RS01\\src\\rs01\\img\\13.tif");

        //得到波段4的最小最大像素值
        int[][] band4_arr = band_arr.get(0);
        int[] band4_minMax = fsc.getMinMaxPixel(band4_arr);
        int band4_min = band4_minMax[0];
        int band4_max = band4_minMax[1];

        //得到波段3的最小最大像素值
        int[][] band3_arr = band_arr.get(1);
        int[] band3_minMax = fsc.getMinMaxPixel(band3_arr);
        int band3_min = band3_minMax[0];
        int band3_max = band3_minMax[1];

        //得到波段2的最小最大像素值
        int[][] band2_arr = band_arr.get(2);
        int[] band2_minMax = fsc.getMinMaxPixel(band2_arr);
        int band2_min = band2_minMax[0];
        int band2_max = band2_minMax[1];

        //波段4线性拉伸
        int[][] band4_arrLinear = fsc.linearTo8Bit(band4_arr, band4_min, band4_max);
        //波段3线性拉伸
        int[][] band3_arrLinear = fsc.linearTo8Bit(band3_arr, band3_min, band3_max);
        //波段2线性拉伸
        int[][] band2_arrLinear = fsc.linearTo8Bit(band2_arr, band2_min, band2_max);

        //将线性拉伸后的数组存放在集合中
        ArrayList<int[][]> band_arrLinear = new ArrayList<>();
        band_arrLinear.add(band4_arrLinear);
        band_arrLinear.add(band3_arrLinear);
        band_arrLinear.add(band2_arrLinear);

        //合成假彩色图像
        Mat mat = fsc.falseColorSynthesis(band_arrLinear);
        //将假彩色图像写入文件
        Imgcodecs.imwrite("D:\\Project\\IDEA_Project\\RS01\\src\\rs01\\img\\13_fsc.png", mat);
    }
}

四、实验结果

1、原图像

TIFF格式的图像为16位深度的颜色,直接在Window里打开一张16位tif格式的图片是无法获得有效信息甚至无法打开,所以在ENVI中进行查看。

2、假彩色合成结果

3、ENVI中标准假彩色的合成结果

和ENVI中合成的假彩色图像非常接近

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【测试开发学习历程】第一个Python程序(下)

6 Python的标识符&#xff0c;命名规则与规范 标识符&#xff1a;python中的标识符是用于识别变量、函数、类、模块以及其他对象的名字叫标识符。 命名规则&#xff1a;所有需要自己命名的地方都必须要遵守以下规则 可以包含数字、字母、_&#xff0c;但是不能以数字开头&…

<c语言学习>数据文件操作

数据文件 按文件功能讲&#xff0c;计算机的文件分为程序文件和数据文件&#xff0c;数据文件操作以下简称文件操作。 程序文件&#xff1a; 包括源程序文件&#xff08;后缀为.c&#xff09;,目标文件&#xff08;windows环境后缀为.obj&#xff09;,可执行程序&#…

使用npm仓库的优先级以及.npmrc配置文件的使用

使用npm仓库的优先级以及.npmrc配置文件的使用 概念如何设置 registry&#xff08;包管理仓库&#xff09;1. 设置项目配置文件2. 设置用户配置文件3. 设置全局配置文件4. .npmrc文件可以配置的常见选项 概念 npm&#xff08;Node Package Manager&#xff09;是一个Node.js的…

2014年认证杯SPSSPRO杯数学建模B题(第一阶段)位图的处理算法全过程文档及程序

2014年认证杯SPSSPRO杯数学建模 B题 位图的处理算法 原题再现&#xff1a; 图形&#xff08;或图像&#xff09;在计算机里主要有两种存储和表示方法。矢量图是使用点、直线或多边形等基于数学方程的几何对象来描述图形&#xff0c;位图则使用像素来描述图像。一般来说&#…

既有理论深度又有技术细节——深度学习计算机视觉

推荐序 我曾经试图找到一本既有理论深度、知识广度&#xff0c;又有技术细节、数学原理的关于深度学习的书籍&#xff0c;供自己学习&#xff0c;也推荐给我的学生学习。虽浏览文献无数&#xff0c;但一直没有心仪的目标。两周前&#xff0c;刘升容女士将她的译作《深度学习计…

爬虫实践(1)

这一篇只提登录模拟&#xff0c;主要介绍chrome开发者窗口的使用&#xff0c;实际上相关接口调用都是用到cookie&#xff0c;需要再加一篇从token到cookie&#xff0c;以保证实践的完整性 以migu登录为例&#xff0c;分析其登录过程&#xff0c;之后可以使用任意语言模拟登录&…

蓝桥杯真题Day40 倒计时19天 纯练题!

蓝桥杯第十三届省赛真题-统计子矩阵 题目描述 给定一个 N M 的矩阵 A&#xff0c;请你统计有多少个子矩阵 (最小 1 1&#xff0c;最大 N M) 满足子矩阵中所有数的和不超过给定的整数 K? 输入格式 第一行包含三个整数 N, M 和 K. 之后 N 行每行包含 M 个整数&#xf…

Linux实现m4a格式转换为wav格式

需要在linux上安装ffmpeg 参考博客 Linux上安装ffmpeg修改环境变量【这一点很重要&#xff0c;自己因为没有添加环境变量&#xff0c;捣鼓了很长时间】 将ffmpeg的绝对路径添加到 PATH 环境变量中&#xff0c;以让系统能找到ffmpeg的安装路径。 # /home//project/ffmpeg-6.1-a…

数据库安全性

背景&#xff1a;数据库的一大特性就是数据共享&#xff0c;这样我们就不能不考虑数据库的安全性问题。 1.数据库的不安全因素 1.1非授权用户对数据库的恶意存取和破坏 一些黑客&#xff08;Hacker&#xff09;和犯罪分子在用户存取数据库时猎取用户名和用户 口令&#xff0…

图像处理与视觉感知---期末复习重点(4)

文章目录 一、图像复原与图像增强1.1 概述1.2 异同点 二、图像复原/退化模型2.1 模型图简介2.2 线性复原法 三、彩色基础四、彩色模型五、彩色图像处理 一、图像复原与图像增强 1.1 概述 1. 图像增强技术一般要利用人的视觉系统特性&#xff0c;目的是取得较好的视觉效果&…

canvas跟随鼠标画有透明度的矩形边框

提示&#xff1a;canvas跟随鼠标画有透明度的矩形边框 文章目录 前言一、跟随鼠标画有透明度的矩形边框总结 前言 一、跟随鼠标画有透明度的矩形边框 test.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&…

Hana数据库 No columns were bound prior to calling SQLFetch or SQLFetchScroll

在php调用hana数据库的一个sql时报错了&#xff0c;查表结构的sql&#xff1a; select * from sys.table_columns where table_name VBAP SQLSTATE[SL009]: <<Unknown error>>: 0 [unixODBC][Driver Manager]No columns were bound prior to calling SQLFetch …

Kibana的安装(Linux版)

Kibana是一个针对Elasticsearch的开源分析及可视化平台&#xff0c;用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana&#xff0c;可以通过各种图表进行高级数据分析及展示。 Kibana让海量数据更容易理解。它操作简单&#xff0c;基于浏览器的用户界面可以快速创…

Eladmin-jpa基于SpringBoot和Vue的前后端分离后台管理系统​

在当今快速发展的软件开发领域&#xff0c;前后端分离的架构模式已经成为主流。这种架构模式不仅可以提高开发效率&#xff0c;还能使系统更加易于维护和扩展。Eladmin-jpa是一个基于Spring Boot 2.6.4、Spring Boot Jpa、JWT、Spring Security、Redis和Vue的前后端分离的后台管…

分布式系统面试全集通第一篇(dubbo+redis+zookeeper----分布式+CAP+BASE+分布式事务+分布式锁)

目录 分布式系统面试全集通第一篇什么是分布式?和微服务的区别什么是分布式分布式与微服务的区别 什么是CAP?为什么不能三者同时拥有分区容错性一致性可用性 Base理论了解吗基本可用软状态最终一致性 什么是分布式事务分布式事务有哪些常见的实现方案?2PC&#xff08;Two Ph…

docker安装elasticseachkibana

1.docker安装es 创建本机挂载目录&#xff0c;与容器上目录映射 /Users/wangpei/2024/mydata/elasticsearch conf下创建yml文件 echo "http.host : 0.0.0.0" >> /Users/wangpei/2024/mydata/elasticsearch/config/elasticsearch.yml 安装容器&#xff1a; d…

【Effective Web】html/css优化和技巧

html/css优化和技巧 html/css可以做到一些js的功能&#xff0c;减少js操作dom的高昂成本。 巧用伪类 显示勾选时文案 checkbo勾选时触发&#xff0c;实现checkbox的简单选中事件处理 <template><input type"checkbox" /><span class"checkb…

谷粒商城——缓存——SpringCache

1. 配置使用 首先需要导入相关的依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency> 随后在配置文件中进行配置&#xff1a; spring:cache:t…

纳斯达克大屏媒体尺寸与投放费用:一次投放需要多少钱?

纳斯达克大屏媒体尺寸与投放费用&#xff1a;一次投放需要多少钱&#xff1f; 1. 纳斯达克图片要求 1.1 像素要求 高度&#xff1a;2336 像素宽度&#xff1a;1832 像素 1.2 分辨率要求 像素比率&#xff1a;1.0 px 72 dpi 1.3 文件格式要求 静态图片格式&#xff1a;.…

java网络原理(四)----tcp特性

一.滑动窗口 滑动窗口&#xff1a;可以提高传输效率&#xff0c;准确的来说是让tcp在可靠传输的前提下&#xff0c;效率不要太拉胯。使用滑动窗口不能使tcp变的比UDP块&#xff0c;但能减少差距。 前面谈过tcp的传输数据的时&#xff0c;会把数据进行编号&#xff0c;每次传固…