在遥感领域,许多图片的大小动辄上G。读取、显示这样的图片极为耗时,影响用户体验。金字塔技术在几乎不降低显示效果的前提下,大大降低了图片处理的耗时,改善了用户体验

目录

原理

操作方法

示例

解释

生成金字塔

读取金字塔

效果



原理

考虑一幅1024乘以1024的图片。假如每个像素占据1字节,则整个文件占据1MB(不算文件辅助信息之类的话)。假如显示这幅图片的窗口尺寸只有256*256,则我们完全可以抽样,每4行抽一行,每4列抽一列。抽取出来的字节数仅为原有字节数的1/16.假如读取的字节数变少了,耗时自然会降低。但是这要求我们在读取之前,就要把抽样完成,并且将抽样结果存放到一段连续的磁盘或内存里供使用(有人可能提出来,RasterIO函数具备抽样功能,可否每次读取时都利用RasterIO来抽样一次?不行,假如对若干段不连续的地址进行读取,RasterIO的耗时也会增加,不会比读取全部数据快多少。所以抽样结果一定要存入一段连续的内存或者磁盘里)。

操作方法

gdal提供了函数BuildOverviews()完成抽样并保存。

CPLErr BuildOverviews(const char *pszResampling, int nOverviews,
int *panOverviewList, int nListBands, int *panBandList,
GDALProgressFunc pfnProgress, void *pProgressData)

1)pszResampling可以是如下字符串的一个:

"NEAREST" 选取最近邻的原始像素值

"AVERAGE"取平均

"BILINEAR"双线性插值

"CUBIC"立方插值

"GAUSS"高斯插值

"LANZCOS"兰佐斯插值(高斯与兰佐斯都是数学-物理学家)

"AVERAGE_MAGPHASE"

"CUBICSPLINE"

"MODE"

"NONE"

2) 考虑到许多显示界面都具备缩放功能,一旦图像发生缩放,抽样的比率将发生变化,所以BuildOverviews()函数提供了nOverviews和panOverviewList。前者表示你可以做几次抽样;后者是一个数组,表示每次抽样的采样率是多少。

3) nListBands表示被采样的波段号。

4) 最后两个变量一般不用,写NULL即可

以下面的代码为例,nOverviews=3,panOverviewList={2,4,8},说明采样三次。第一次采样率为2,也就是每两行取一行,每2列取一列;第二次采样率为4,也就是每4行取一行,每4列取1列;...三次采样的结果都要保存下来。对于tif文件,抽样结果存入源文件;对于bmp文件,所有抽样结果存入一个统一的新文件,文件名是源文件名加后缀.ovr

采样率越高,抽样的结果占用字节数就越少。以原文件占1024kB为例,采样率为2,抽样结果占256kB;采样率4,则占据64kB;采样率为8,则占据16kB.采样率从高到低,占用空间越来越大,形成金字塔型,这也正是“影像金字塔”命名的由来。

示例

下面的代码利用buildOverviews函数建立金字塔,然后按照不同分辨率来读取图片,并记录不同分辨率下读取的花费时间。关于如何记录读取时间,可以参看我的另外一篇博客《Visual Studio C++精确计时》

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "gdal_priv.h"
#include <QDebug>#pragma comment(lib, "winmm.lib")//不可少MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);ui->lineEdit->setText("C:\\code\\QT\\pyramid\\2-1.tif");ui->lineEdit_2->setText("C:\\code\\QT\\pyramid\\");QueryPerformanceFrequency(&m_nFreq);//获取频率QueryPerformanceCounter(&m_nBegin);//获取起始时间
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{QString qstrName = ui->lineEdit->text();GDALDataset * pSet = (GDALDataset *)GDALOpen(qstrName.toLatin1().data(), GA_Update);int       anOverviewList[3] = { 2, 4, 8};if(CE_None == pSet->BuildOverviews( "NEAREST", 3, anOverviewList, 0, NULL,NULL, NULL )){ui->label->setText("OK");}else{ui->label->setText("fail");}GDALClose(pSet);
}void MainWindow::on_pushButton_2_clicked()
{int iRatio = ui->spinBox->value();QString qstrName = ui->lineEdit->text();GDALDataset * pSet = (GDALDataset *)GDALOpen(qstrName.toLatin1().data(), GA_ReadOnly);GDALRasterBand *pBand =pSet->GetRasterBand(1);int iX = pSet->GetRasterXSize();int iY = pSet->GetRasterYSize();unsigned char * pData = new unsigned char[iX * iY];LARGE_INTEGER nTime1, nTime2;QueryPerformanceCounter(&nTime1);//获取时间pBand->RasterIO(GF_Read,0, 0, iX, iY, pData, iX/iRatio, iY/iRatio, GDT_Byte, 0, 0);QueryPerformanceCounter(&nTime2);int iInterval = (nTime2.QuadPart - nTime1.QuadPart) / (double)m_nFreq.QuadPart * 1000;ui->label_2->setText(QString("%1ms").arg(iInterval));GDALClose(pSet);//savestatic int iIndex = 0;QString qstrSavePath = ui->lineEdit_2->text();QString qstrSaveFile = QString("%1new%2.tif").arg(qstrSavePath).arg(iIndex++);GDALDriver * pDriver = GetGDALDriverManager()->GetDriverByName("GTiff");GDALDataset * pSetWrite = pDriver->Create(qstrSaveFile.toLatin1().data(),iX/iRatio, iY/iRatio,1,GDT_Byte,NULL);pBand =pSetWrite->GetRasterBand(1);pBand->RasterIO(GF_Write,0, 0, iX/iRatio, iY/iRatio, pData, iX/iRatio, iY/iRatio, GDT_Byte, 0, 0);GDALClose(pSetWrite);delete [] pData;
}

解释

生成金字塔

函数 on_pushButton_clicked()用于产生金字塔

语句

int       anOverviewList[3] = { 2, 4, 8};

意味着抽样三次,抽样率分别为2,4,8

读取金字塔

函数 on_pushButton_2_clicked()用于读取金字塔,然后把读取的结果保存成单独的文件

语句

pBand->RasterIO(GF_Read,0, 0, iX, iY, pData, iX/iRatio, iY/iRatio, GDT_Byte, 0, 0);

中各个参数意义如下:(按从左到右的次序)

GF_Read 表示读取

第一对 0,0表示读取的开始位置是原始图片(也就是抽样之前的图片)的左上角

iX,iY表示读取的范围:原始图片横向iX个像素,纵向iY个像素

pData表示读取后,像素存储的首地址

iRatio代表抽样率,iX/iRatio代表抽样后,抽样结果在X方向占多少像素,iY/iRatio代表抽样结果在Y方向占多少像素

GDT_Byte代表原始文件的像素占一个字节

RasterIO前后的两个QueryPerformanceCounter函数记下了读取前后的时间,两者相减便是RasterIO的耗时。这个耗时将显示在界面上。

效果

读取不抽样的图(微缩比例1)耗时48ms。结果文件new0.tif占据2967KB

读取抽样率为2(微缩比例2)的图耗时12ms。结果文件new1.tif占据742KB

读取抽样率为4的图耗时16ms。当图变小以后,读取耗时就存在随机性了,但是总的趋势不变。16ms也正常。结果文件new2.tif占据186KB

读取抽样率为8的图耗时0.结果文件new3.tif占据47KB

我们从图片的字节数也可以看出抽样确实减少了文件大小。从new0.tif到new3.tif

利用gdal给影像添加金字塔相关推荐

  1. Qt、GDAL遥感影像显示

    影像显示原理 显示遥感影像在业界做得比较牛逼的有ENVI,Erdas,以及ArcGIS软件.其实我并不想列举ArcGIS软件,但是ArcGIS毕竟是行业的大佬,所以.. 遥感影像一般小到几百兆大到几个 ...

  2. python中利用GDAL对tif文件进行读写

    利用GDAL库对tif影像进行读取 示例代码默认波段为[B.G.R.NIR的顺序,且为四个波段] import gdal def readTif(fileName):dataset = gdal.Op ...

  3. GeoServer源码解析栅格数据Image Mosaic JDBC插件原理(一)GDAL生产影像切片

    1. 作者声明 GeoServer源码解析栅格数据Image Mosaic JDBC插件原理共分三篇幅 (一)GDAL生产影像切片 (二)GeoTools Image Mosaic JDBC插件源码解 ...

  4. 学习笔记——【python】GetGeoTransform()使用,gdal截取图像,使用GDAL进行影像投影坐标、地理坐标、图上坐标的转换

    1. GetGeoTransform()使用.gdal截取图像 GetGeoTransform() GeoTransform[0],左上角横坐标(应该是投影坐标) GeoTransform[2],行旋 ...

  5. Unreal Engin_画廊制作笔记 _011利用PS为场景添加滤镜效果

                                                    011 利用PS为场景添加滤镜效果 这节比较重要. 我们要利用PS制作一个类似镜头滤镜的效果. 第一步, ...

  6. android如何设置qq邮箱格式,如何利用安卓“电子邮件”客户端添加QQ邮箱

    如何利用安卓"电子邮件"客户端添加QQ邮箱 部分安卓系统都会预装谷歌"电子邮件"客户端,手机用户可以将"电子邮件"与用户的QQ邮箱账户进行绑 ...

  7. JAVA调用GDAL实现影像格式转换,以tif to jpg为例

    前言 本文简单实现java调用GDAL实现影像格式转换. package Marcus.com;import org.gdal.gdal.Dataset; import org.gdal.gdal.D ...

  8. 利用GDAL(python)读取Landsat8数据

    本人编写了一个利用GDAL读取Landsat8数据的代码,现在已经拥有了读取.真彩色.假彩色显示等功能.准备日后再进行扩展. 注意:路径是相对路径,使用需自行修改. 这个代码是将压缩包解压出来的数据的 ...

  9. 利用zabbix api批量添加数百台监控主机

    利用zabbix api批量添加监控主机 在公司规模很庞大的时候,每次都手动添加监控主机将会很麻烦,我们可以利用zabbix的api去批量添加监控主机 本次我们将实现用一台主机虚拟出100台主机,并通 ...

最新文章

  1. 自己动手写简单的web应用服务器(4)—利用socket实现文件的下载
  2. foxmail提示不知道这样的主机_不知道和婚礼策划师沟通时谈哪些?这样做让你高效备婚...
  3. MYSQL 深入浅出索引(下)
  4. 鸿蒙系统正式版官方下载,华为鸿蒙os2.0系统app正式版
  5. [NOI2014]动物园 【kmp】
  6. 跟沈剑学习如何带领技术团队作战
  7. Qt 给应用程序添加图标
  8. UITableView介绍 之 复杂cell的高度计算
  9. C语言函数一章教学,c语言案例教程:函数教学讲义.ppt
  10. 技术揭秘QQ空间”自动转发不良信息
  11. 希腊字母在数学或物理中代表的意思各是什么
  12. IP协议——IP地址的基础知识
  13. DFI工控机维修EC800 EC700-BT2工控机主板维修故障分析
  14. 差速小车的Cartographer建图
  15. 2020十大最佳大数据分析工具
  16. 敏捷 Scrum 大师班认证培训的终极方案 | The Ultimate Agile Scrum Master Certification Training
  17. 计算机组成原理源码,计算机组成原理源码两位乘课程设计报告.docx
  18. EDA软件—Cadence学习笔记分享(内含安装教程)
  19. c语言strrchr函数,strrchr_字符串 | Strings_C_参考手册_非常教程
  20. Win10,Win11系统安全中心提醒“找到可能不需要的应用”弹窗,如何关闭?

热门文章

  1. 洛谷P3354 [IOI2005]Riv 河流——“承诺”DP
  2. 关于sPLS analysis的一些学习
  3. 叼丝装备之服装必备----111111111111111111111111111111111
  4. 利用留数定理计算傅立叶变换积分
  5. 骑行318、 2016.7.26
  6. 开车的人和不开车的人思维有什么区别?
  7. (九)数字后端之静态时序分析STA
  8. flash的Socket连接,服务端用没有平台限制
  9. 图片突出显示(图片高亮显示)-jQuery实现-案例
  10. 苹果鼠标怎么充电_无线充电器怎么用?看一次就会了!-装修攻略