环境:Windows10专业版 + IDEA2021.2.3 + jdk11.0.1 + GDAL(release-1928-x64-gdal-3-5-2-mapserver-8-0-0)
系列文章:
(一)Python+GDAL实现BSQ,BIP,BIL格式的相互转换
(二)BSQ,BIL,BIP存储格式的相互转换算法
(三)单波段图像的伪彩色合成:密度分割(含介绍OpenCV中的Mat类)
(四)图像的%2线性拉伸
(五)图像的标准假彩色合成
(六)图像的直方图均衡化
(七)图像的均值滤波
(八)图像的中值滤波
(九)图像的高斯低通滤波
(十)图像的梯度倒数加权平滑
(十一)图像的罗伯特梯度锐化
(十二)图像的Sobel梯度锐化
(十三)图像的拉普拉斯梯度锐化
目录
一、BSQ,BIP,BIL格式简介
(1)BSQ (band sequential)
(2)BIL(band interleaved by line format)
(3)BIP(band interleaved by pixel format)
二、代码实现
三、实验结果
图像的元数据
①读取为BSQ格式的存储格式
②BSQ转BIL
③BSQ转BIP
一、BSQ,BIP,BIL格式简介
(插图来源于@CSDN溯水xiangling)
(1)BSQ (band sequential)
像素按波段顺序存储,先保存第一个波段,保存完毕后再保存第二个波段,以此类推。
优点:①便于进行波段间的运算;②便于进行波段间的运算;
(2)BIL(band interleaved by line format)
像素按行存储,先保存第一个波段的第一行,再保存第二个波段的第一行,以此类推。
优点:①像素的空间位置在列的方向上是连续的,既可以形象地表达空间分布特征,又可以反映像素的光谱特征 ;②具有较快的读取速度
(3)BIP(band interleaved by pixel format)
按像元顺序存储,先保存第一个波段的第一个像元,再保存第二个波段的第一个像元,以此类推。
优点:①便于进行像元间的运算;②可以清晰地反映像元的光谱特征;
这三种格式各有优缺点,通常根据具体的应用场景和处理需求来选择合适的格式。例如,BSQ格式适合在读取特定波段时提高效率,因为同一波段的数据连续存储,而BIP和BIL则在需要同时访问多个波段的像素时更为高效。
在实际的数字图像处理中,可能需要将一种格式转换为另一种格式以便于分析或与其他软件兼容。转换这些格式可以通过编程语言结合GDAL库进行转换,或者使用MATLAB编写脚本来实现批量转换。也可以通过数据处理和格式转换的软件或工具。每种格式都有其特定的存储结构和应用场景,在进行格式转换时需要考虑数据的完整性和准确性。由于数据格式的转换可能涉及到大量的数据处理和计算,因此在进行转换时还需要考虑计算机的性能和存储空间等因素。
二、代码实现
import org.gdal.gdal.Band;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
/**
* @Author: jue_chen
* @Date: 2022/10/16/ 19:56
* @Attention: 转载, 引用请注明出处
*/
public class CalculateBands {
int iXSize; //图像的列数
int iYSize; //图像的行数
int bandsNum; //图像的波段数
int[][][] bandArr; //存储图像的所有灰度值,BSQ格式
//获取一副图像的波段信息
public void getBands(String srcPath) {
gdal.AllRegister(); //支持所有驱动
//以只读方式读取数据存入Dataset类型里
Dataset dataset = gdal.Open(srcPath, gdalconstConstants.GA_ReadOnly);
//判断文件是否读取成功
if (dataset == null) {
System.out.println("文件读取失败");
System.out.println(gdal.GetLastErrorMsg());
System.exit(1);
}
iXSize = dataset.getRasterXSize(); //获取图像列数
iYSize = dataset.getRasterYSize(); //获取图像行数
bandsNum = dataset.GetRasterCount(); //获取图像波段数
//定义波段类型的数组存放每一波段的信息
Band[] band = new Band[bandsNum];
for (int i = 0; i < bandsNum; i++) {
band[i] = dataset.GetRasterBand(i + 1); //图像波段的索引值从1开始,不是0
}
//三维数组存放具体波段的灰度值,第一维存放波段数,第二维存放波段的行数,第三维存放波段的列数,以BSQ格式存储
bandArr = new int[bandsNum][iYSize][iXSize];
for (int i = 0; i < bandsNum; i++) {
System.out.println("第" + (i + 1) + "波段");
for (int j = 0; j < bandArr[0].length; j++) {
band[i].ReadRaster(0, j, iXSize, 1, bandArr[i][j]); //一次读取一行灰度值数据
//读取结果输出测试
for (int k = 0; k < bandArr[0][0].length; k++) {
System.out.print(bandArr[i][j][k] + "\t");
}
System.out.println();
}
System.out.println();
}
System.out.println();
}
//打印图像所有波段的灰度值
public void printBandArr(int[][][] bandArr) {
for (int i = 0; i < bandArr.length; i++) {
for (int j = 0; j < bandArr[0].length; j++) {
for (int k = 0; k < bandArr[0][0].length; k++) {
System.out.print(bandArr[i][j][k] + "\t");
}
System.out.println();
}
System.out.println();
}
}
//获得BSQ格式的数组
public int[][][] getBSQ() {
return bandArr;
}
//BSQ转BIL
public int[][][] BSQtoBIL(int[][][] bandArrBSQ) {
//第一维存放波段的行数,第二维存放波段数,第三维存放波段的列数
int[][][] bandArrBIL = new int[bandArrBSQ[0].length][bandArrBSQ.length][bandArrBSQ[0][0].length];
for (int i = 0; i < bandArrBSQ[0].length; i++) { //BSQ的第二维大小
for (int j = 0; j < bandArrBSQ.length; j++) { //BSQ的第一维大小
for (int k = 0; k < bandArrBSQ[0][0].length; k++) { //BSQ的第三维大小
bandArrBIL[i][j][k] = bandArrBSQ[j][i][k];
}
}
}
return bandArrBIL;
}
//BSQ转BIP
public int[][][] BSQtoBIP(int[][][] bandArrBSQ) {
//第一维存放波段的行数,第二维存放波段的列数,第三维存放波段数
int[][][] bansArrBIP = new int[bandArrBSQ[0].length][bandArrBSQ[0][0].length][bandArrBSQ.length];
for (int i = 0; i < bandArrBSQ[0].length; i++) { //BSQ第二维大小
for (int j = 0; j < bandArrBSQ[0][0].length; j++) { //BSQ第三维大小
for (int k = 0; k < bandArrBSQ.length; k++) { //BSQ第一维大小
bansArrBIP[i][j][k] = bandArrBSQ[k][i][j];
}
}
}
return bansArrBIP;
}
//BIL转BSQ
public int[][][] BILtoBSQ(int[][][] bandArrBIL) {
//第一维存放波段数,第二维存放波段行数,第三维存放波段列数
int[][][] bandArrBSQ = new int[bandArrBIL[0].length][bandArrBIL.length][bandArrBIL[0][0].length];
for (int i = 0; i < bandArrBIL[0].length; i++) { //BIL第二维大小
for (int j = 0; j < bandArrBIL.length; j++) { //BIL第一维大小
for (int k = 0; k < bandArrBIL[0][0].length; k++) { //BIL第三维大小
bandArrBSQ[i][j][k] = bandArrBIL[j][i][k];
}
}
}
return bandArrBSQ;
}
//BIL转BIP
public int[][][] BILtoBIP(int[][][] bandArrBIL) {
//第一维存放波段的行数,第二维存放波段的列数,第三维存放波段数
int[][][] bandArrBIP = new int[bandArrBIL.length][bandArrBIL[0][0].length][bandArrBIL[0].length];
for (int i = 0; i < bandArrBIL.length; i++) { //BIL第一维大小
for (int j = 0; j < bandArrBIL[0][0].length; j++) { //BIL第三维大小
for (int k = 0; k < bandArrBIL[0].length; k++) { //BIL第二维大小
bandArrBIP[i][j][k] = bandArrBIL[i][k][j];
}
}
}
return bandArrBIP;
}
//BIP转BSQ
public int[][][] BIPtoBSQ(int[][][] bandArrBIP) {
//第一维存放波段数,第二维存放波段行数,第三维存放波段列数
int[][][] bandArrBSQ = new int[bandArrBIP[0][0].length][bandArrBIP.length][bandArrBIP[0].length];
for (int i = 0; i < bandArrBIP[0][0].length; i++) { //BIP第三维大小
for (int j = 0; j < bandArrBIP.length; j++) { //BIP第一维大小
for (int k = 0; k < bandArrBIP[0].length; k++) { //BIP第二维大小
bandArrBSQ[i][j][k] = bandArrBIP[j][k][i];
}
}
}
return bandArrBSQ;
}
//BIP转BIL
public int[][][] BIPtoBIL(int[][][] bandArrBIP) {
//第一维存放波段的行数,第二维存放波段数,第三维存放波段的列数
int[][][] bandArrBIL = new int[bandArrBIP.length][bandArrBIP[0][0].length][bandArrBIP[0].length];
for (int i = 0; i < bandArrBIP.length; i++) { //BIP第一维大小
for (int j = 0; j < bandArrBIP[0][0].length; j++) { //BIP第三维大小
for (int k = 0; k < bandArrBIP[0].length; k++) { //BIP第二维大小
bandArrBIL[i][j][k] = bandArrBIP[i][k][j];
}
}
}
return bandArrBIL;
}
public static void main(String[] args) throws Exception {
CalculateBands img = new CalculateBands();
img.getBands("D:\\Project\\IDEA_Project\\RS01\\src\\rs01\\img\\9.png"); //读入图像
int img_rows = img.iYSize; //图像灰度值的行数
int img_cols = img.iXSize; //图像灰度值的列数
int img_bandNum = img.bandsNum; //图像的波段数
System.out.println("读入图像每一波段的灰度值行数为:" + img_rows);
System.out.println("读入图像每一波段的灰度值列数为:" + img_cols);
System.out.println("读入图像的波段数为:" + img_bandNum);
System.out.println();
int[][][] img_bandArrBSQ = img.getBSQ(); //获取以BSQ格式的存储的数组
//BSQ转为BIL
int[][][] img_bandArrBIL = img.BSQtoBIL(img_bandArrBSQ);
System.out.println("BIL的存储格式");
img.printBandArr(img_bandArrBIL);
//BSQ转为BIP
int[][][] img_bandArrBIP = img.BSQtoBIP(img_bandArrBSQ);
System.out.println("BIP的存储格式");
img.printBandArr(img_bandArrBIP);
//BIL转为BSQ
int[][][] img_bandArrBSQ_1 = img.BILtoBSQ(img_bandArrBIL);
System.out.println("BSQ的存储格式");
img.printBandArr(img_bandArrBSQ_1);
//BIL转为BIP
int[][][] img_bandArrBIP_1 = img.BILtoBIP(img_bandArrBIL);
System.out.println("BIP的存储格式");
img.printBandArr(img_bandArrBIP_1);
//BIP转为BSQ
int[][][] imgBandArrBSQ_2 = img.BIPtoBSQ(img_bandArrBIP);
System.out.println("BSQ的存储格式");
img.printBandArr(imgBandArrBSQ_2);
//BIP转为BIL
int[][][] imgBandArrBIL_2 = img.BIPtoBIL(img_bandArrBIP);
System.out.println("BIL的存储格式");
img.printBandArr(imgBandArrBIL_2);
}
}
三、实验结果
仅展示BSQ转BIL,BIP的测试结果
图像的元数据