专栏名称: 锐多宝
遥感技术教程、资讯与前沿论文
目录
相关文章推荐
拾榴询财  ·  有奖征集:回乡见闻 ·  2 天前  
格上财富  ·  2025年:平安生活指南25条 ·  3 天前  
格上财富  ·  芒格:巴菲特取得成功的六个要素 ·  4 天前  
中金固定收益研究  ·  【中金固收】春节读书心得与图书推荐 ·  3 天前  
51好读  ›  专栏  ›  锐多宝

BIL、BIP、BSQ都知道,二进制文件会读取吗

锐多宝  · 公众号  ·  · 2024-12-09 22:53

正文



介绍了遥感影像通用数据格式BIP、BIL、BSQ,并给出MATLAB、C++从原始二进制数据读取影像的代码~

🌿前言

遥感影像的 通用数据格式 有BIP、BIL、BSQ三种,通常在编程处理图像时都会使用GDAL、Arcpy、Rasterio等库来进行读取,如果因某些原因使用不了这些库,又该如何解决呢?

本文先简单介绍了BIP、BIL、BSQ三种通用格式的区别,随后分析了如何正确读取二进制存储遥感数据,最后给出了MATLAB和C++读取参考代码。

文末有获取项目所有文件的方式~

🍀BIP&BIL&BSQ

BIP

BIP(Band Interleaved by Pixel),可以理解为按照像素存储,先依次存储每个波段的第一个像素,再存储每个波段的第二个像素...

BIL

BIL(Band Interleaved by Line),可以理解为按照行进行存储,先依次存储每个波段的第一行,再存储每个波段的第二行...

BSQ

BSQ(Band Sequential),即按照顺序存储,依次存第一个波段所有像素,再存第二个波段所有像素...

一图理解

下图应该能够很好的反映出存储的方式(按照对应的数字顺一遍就很好理解)

了解更多可以参考此链接:https://blog.csdn.net/m0_46387817/article/details/108467947

🌸数据读取思路

重要两点

有关如何正确地读取影像数据,笔者认为有两点是至关重要的:

  1. 弄清所读楚遥感影像的存储是BIP还是BIL还是BSQ
  2. 知道所读影像的数据类型:float、double

如果数据格式不正确,就会导致数据读取的有问题,例如一个存储类型是8位的数据按照16位的数据类型读取,就会直接导致读取到的数组大小发生改变,这个错误还容易发现。

如果数据格式存储的8位无符号整型,恰好又按照8位的整型去读取,读出来的数组大小一致,但是值已经是错误的值了。

数据存储类型

读取步骤

  1. 将数据从二进制文件中按照存储类型读到一维数组

需要根据影像的元数据文件或者一些属性信息,了解影像单个像元存储的数据类型,再利用一些读取二进制文件的函数例如MATLAB中的fopen和fread函数、C++中的ifstream函数将数据正确地读到一维数组。

  1. 根据BIP、BIL、BSQ对一维数组进行解析

根据索引关系将一维数组解析为对应的波段数组。

索引关系

关于如何建立一维数组和波段数组(三维)的关系,即建立一个 的函数:

式中, 表示一维数组中的索引, 分别代表第 行、第 列、第 个波段, 是待求量。

笔者也是思考了很久,简单总结出如下两种思考方法(其实两种很类似,也挺绕的😴):

方法一

即固定任意两个变量的值为0,变化第三个变量的值,观察其规律,解求得到其对应的待求量。

方法二

先假设图像为一维(即单波段、一行值),得到一个规律;再逐渐增加维度,观察变换确立关系。

索引关系

BIP一维数组与波段数组索引关系
BIL一维数组与波段数组索引关系
BSQ一维数组与波段数组索引关系

🍗MATLAB代码

笔者根据自己理解,编写了parserData的MATLAB函数。并利用ENVI软件制作了BIL、BIP、BSQ格式的RGB图片文件,使用MATLAB读取数据文件经过解析后简单绘制可视化。

读取效果

BIP读取

读取BIP格式文件

BIL读取

读取BIL格式文件

BSQ读取

读取BSQ格式文件

parserData.m

function result = parseData(lineData, row, column, bandcount, type)
    % 解析一维数组到BIP、BIL、BSQ格式
    totalsize = length(lineData);
    result = zeros([row, column, bandcount]);

    % 解析BIP格式
    if upper(type) == "BIP"
        for i = 1:bandcount
            tmp = lineData(i:bandcount:totalsize);
            result(:, :, i) = reshape(tmp, column, row)';
        end
    % 解析BIL格式
    elseif upper(type) == "BIL"
        tmp = reshape(lineData, bandcount*column, row);
        for i = 1:bandcount
            result(:, :, i) = tmp(column*(i - 1)+1:column*i, :)';
        end
    % 解析BSQ格式
    elseif upper(type) == "BSQ"
        tmp = reshape(lineData, column, row*bandcount)';
        for i = 1:bandcount
            result(:, :, i) = tmp(row*(i - 1)+1:row*i, :);
        end
    end
end

demo.m

clear, clc, close all;
type = "BIP";
filepath = strcat("../"type"/tree"type);
filehead = strcat(filepath, ".hdr");

% 1.读取数据到一维数组
fileID = fopen(filepath, 'r');
if (fileID == -1)
    disp(strcat(filepath, "---OpenFailed"));
end
fileData = fread(fileID, "uint8");

types = ["BIP""BIL""BSQ"];

% 2.解析数据,并绘图
for i = 1:length(types)
    figure
    data = parseData(fileData, 465, 300, 3, types(i));
    imshow(uint8(data));
    resultName = strcat("../"type"/result", types(i), ".png");
    title(strcat(type"->", types(i)), 'FontSize', 14, 'FontName''Times New Roman')
    print(gcf, '-dpng','-r300', resultName);
end

🍟C++代码

C++主要是利用ifstream函数读取二进制文件,存储到vector数组,编写一个模板类Parser以便解析一维数组。

由于笔者能力有限,并未做C++的图行可视化,通过编写test函数生成简单一维数组调用类进行解析以测试类的可靠性,通过输出读取图像第一个像元值来与ENVI软件、取色值软件所探测得到的RGB做对比以测试读取的正确性。







请到「今天看啥」查看全文