☰
QGIS栅格金字塔优化:GDAL overview机制与参数调优
2026/11/6 8:12:40 网站建设 项目流程

一张三十多 GB 的正射影像拖进 QGIS,鼠标滚轮一转,画面先是白屏,然后一块一块地"糊"上来,缩到某一级就彻底卡住不动——这种场景做过遥感底图的人应该都不陌生。旁边有经验的人通常会甩过来一句"先建金字塔"。可真照着做,又会冒出新的疑问:金字塔到底建几级?算法选哪个?为什么建完之后影像边缘发黑、分类图斑糊成一团、文件体积还翻了一倍?更别说还有一大堆人根本不知道 QGIS 里的"金字塔"其实就是 GDAL 的 overview,QGIS 自己并不负责算,它只是调用、然后决定用不用。这篇东西就围绕QGIS 中的金字塔机制优化这个话题,把从"文件里到底存了什么"到"参数该怎么配"再到"建完反而更糟怎么排"这条链路拆开讲清楚。适合手头有大批量栅格数据、正在被加载速度和显示质量两头夹击的人看,也适合刚接手底图库、想把规范定下来的朋友。

1. QGIS 打开栅格时,底层到底发生了什么

1.1 一次滚轮缩放背后的分辨率博弈

很多人以为 QGIS 是"把整张图读进来再显示",这在几十 MB 的小图上勉强成立,但在大图上完全不是这么回事。QGIS 的栅格渲染走的是 GDAL 的 RasterIO 接口,核心参数是"我要一块多大范围的像素,输出到多大一块画布上"。假设当前地图画布的视口是 1600×900 像素,视口覆盖的地面范围是 10 km × 5.6 km,那么 QGIS 需要的就是一个 1600×900 的像素矩阵。GDAL 拿到这个请求后,会去算"原始分辨率和请求分辨率的比值",也就是降采样倍数。

这个比值决定了后面所有的行为。如果比值接近 1,GDAL 老老实实读原始分辨率的块;如果比值是 8,而文件里恰好有一层 8 倍降采样的 overview,GDAL 就直接读那一层,读的数据量只有原始数据的六十四分之一;如果文件里没有 overview,GDAL 就只能读原始分辨率的全部数据,然后在内存里现场做降采样。这就是为什么同一张大图,建不建金字塔的差距可能是零点几秒和几十秒的区别。

关键点在于:QGIS 不参与这个决策,它只是把"我要多大"告诉 GDAL,GDAL 的GDALRasterBand::GetOverview()负责挑最合适的那一层。所以讨论"QGIS 金字塔优化",本质上是在讨论"怎么让 GDAL 手里有合适的那一层"。

1.2 没有金字塔时,QGIS 的降采样是怎么"硬扛"的

没有 overview 的情况下,GDAL 的读取路径是这样的:按照请求范围,把原始分辨率的块全部读进缓存,然后逐像素做降采样。降采样算法在这里由 QGIS 的图层属性决定——符号化选项卡里的"重采样"设置,放大时一个算法、缩小时另一个算法,可选最近邻、双线性、立方。

问题在于这个降采样是"流式"做的,QGIS 为了不让界面卡死,会把整个读取拆成若干个小任务丢到后台线程池里跑,你能看到画面从中间或者从左上角开始一块块填充。这个过程有几个隐性代价:第一,磁盘 IO 量是原始数据量级别,网络盘或者机械盘上会非常明显;第二,CPU 要参与重采样计算,多波段浮点数据尤其吃 CPU;第三,缓存压力大,一块 20000×20000 的影像全分辨率读进来,就算按块读,缓存也会被迅速挤爆,导致反复回读。

我见过最典型的案例是一张约 40 GB 的多光谱影像,在千兆网络盘上,全图视图加载要将近一分钟,而且每次缩放都重新来一遍。加了金字塔之后,全图视图降到两三秒。这个差距不是 QGIS 的锅,也不是机器不行,纯粹是"该有的数据没提前算好"。

1.3 金字塔在文件里究竟长什么样

这里要破除一个误解:金字塔不是一个单独的文件,也不是一张缩略图,它是同一个栅格数据集内部(或旁边)的一组"低分辨率副本",每一层都是完整覆盖全域的。以 GeoTIFF 为例,一层 overview 就是一组额外的 IFD(图像文件目录),描述了"这张图按 2 倍、4 倍、8 倍……降采样后的样子",每层都有完整的栅格数据块。

存放方式有三种,实际工作中要分清:

  • 内部金字塔:直接写进 TIFF 的 SubIFD 或者追加 IFD 里,文件还是那一个 .tif,不产生额外文件。GeoTIFF 支持得最好,也是最推荐的方式。
  • 外部金字塔:生成一个同名的.ovr文件,原文件不动。好处是不破坏原始数据、可以随时删掉重来;坏处是多一个文件,分发的时候容易漏掉,一漏就等于没建。
  • Erdas Imagine 格式的.aux:老路子了,现在基本不用,除非要跟老系统对接。

另外还有一种情况:如果栅格是 COG(Cloud Optimized GeoTIFF),overview 是内嵌的、按块组织的,本身就是为"快速随机访问"设计的。这类文件拿到 QGIS 里通常开箱即用,不需要再手工建金字塔——但前提是制作的时候确实把 overview 打进去了,而不是改个扩展名了事。

2. 动手之前先定三件事:层数、算法、放哪儿

2.1 层数不是越多越好,按你的最小显示比例尺反推

金字塔层级一般按 2 的幂次走:2、4、8、16、32、64、128……很多人图省事,直接写2 4 8 16 32 64 128 256,觉得"多建几层总没坏处"。实际上坏处很明确:每一层都要占存储(总增量大约是原始数据的 1/3,因为 1/4 + 1/16 + 1/64 … 收敛到 1/3),层数越多构建越慢,而且真正用到的往往只有最上面两三层。

正确的做法是反推。假设你的影像原始分辨率是 0.2 米,而你最常看的是 1:50000 的图,屏幕上一个像素大约对应地面 12 米(按 96 dpi 粗算,1:50000 下 1 像素约 13 米,量级差不多),那降采样倍数是 12 / 0.2 = 60,取 2 的幂次就是 64。也就是说,建到 64 就够用了,再往下建纯属浪费。如果还要做全省范围的概览,那就把最小比例尺也考虑进来,通常建到 128 或 256。

我一般的习惯是:先问清楚这套数据"最小会缩到多小看",再决定最高层级。给个粗略的对照表:

数据原始分辨率常用最小显示比例尺屏幕像素对应地面建议最高降采样层级
0.2 m 正射影像1:10000约 2.6 m16
0.2 m 正射影像1:50000约 13 m64
0.5 m 影像1:25000约 6.6 m16
5 m DEM全省概览数百米64 至 128
0.1 m 扫描地形图1:2000约 0.5 m8

这张表不是标准答案,各地屏幕 DPI、地图比例尺习惯不一样,得自己按实际算一遍。但它能说明一个道理:金字塔层数和"看得多细"没关系,只和"缩得多小"有关系。

2.2 降采样算法选错,数据就被毁了

这是最容易出事的一环。GDAL 的gdaladdo -r支持一批算法,常用的有nearest、average、bilinear、cubic、cubicspline、gauss、lanczos、mode、rms。名字看着都懂,实际差别很大:

  • nearest(最近邻):直接抽样,不做加权。速度最快,但会把连续数据打成马赛克。分类栅格、土地利用图、掩膜图用它,别的不要碰。
  • average(平均):取窗口内所有有效像素的均值。连续数据的主力,DEM、温度场、NDVI 都用它。但注意它对 NoData 的处理,后面会专门讲。
  • bilinear / cubic / cubicspline:插值法,视觉上更平滑。适合展示型影像,但对异常值敏感,边上容易出现振铃。
  • gauss:高斯加权,本质是一种带权平均。对影像比较友好,主观上比 average 柔和一点。
  • lanczos:锐度保留最好,代价是可能产生过冲(亮边暗边),在反差大的边缘上会看到"光晕"。
  • mode(众数):取窗口内出现次数最多的值。分类栅格用它比 nearest 更稳,因为它是"投票"而不是"抽样",能减少碎斑。
  • rms:均方根。这个用得少,主要针对特定的信号类数据。
  • average_magphase:专门给复数数据(干涉相位一类)用的,普通栅格用不上。

实际工作中的对应关系我整理成下面这样,基本可以照着抄:

数据类型推荐算法不推荐的算法原因
光学正射影像(8bit/16bit)average 或 gaussnearest抽样会产生明显锯齿和噪点
分类栅格(土地利用、掩膜)mode 或 nearestaverage、bilinear平均会产生不存在的类别值
DEM / 高程average 或 cubicnearest抽样的地形会失真,出现台阶
浮点指数(NDVI 等)averagenearest抽样对异常值太敏感
扫描地形图(二值/索引色)nearestaverage平均会让线条变灰、色表错乱

有一点要提醒:算法只影响 overview 层,不影响原始数据。所以万一选错,删掉.ovr或者重写内部 overview 就能救回来,不用重新处理源文件。这也是我倾向于先做外部.ovr试用、确认效果后再固化到内部的原因之一。

2.3 内部、外部、COG,三种存法各有各的适用场景

内部金字塔最省心,分发的时候只要传一个文件。但它有两个前提:文件格式得支持(GeoTIFF 没问题,JPEG、PNG 这种就不行),且写入的时候得对整个文件做修改——对于放在只读介质上的数据、或者有严格版本管理的原始数据,这就很不方便。

外部.ovr的好处是"旁挂",源文件一个字都不动。适合那些要长期归档、不允许改动的原始成果。缺点是分发时要多带一个文件,很多时候.ovr被漏掉,接收方打开一看还是卡,还以为是 QGIS 的问题。所以如果走外部方案,我一般会在同目录放一个说明文件,或者在命名上做点文章让人一眼能看出来。

COG 是另一个思路:它把 overview 内嵌、按 512×512 或 256×256 的块重排,天然适合"只读一小块"的访问模式。近两年新建的影像库我基本都直接做成 COG,QGIS 打开就是流畅的,不用再手工建。代价是制作过程要做一次完整重写,对超大文件耗时较长,需要预留磁盘空间。

3. QGIS 里建金字塔的两条路,以及建完怎么验证

3.1 图形界面:属性面板里的那个"金字塔"页签

QGIS 3.x 的栅格图层属性对话框里有一个"金字塔"页签,点进去能看到当前数据集已有的 overview 列表——层级、尺寸、压缩方式都会列出来。如果列表是空的,说明这文件没建过金字塔,页签里也提供了构建入口,可以选外部还是内部、选压缩方式、选算法。

用界面的好处是门槛低,不用记命令。坏处也很明显:批量处理的时候一层层点太慢,而且参数暴露得不全,比如 NoData 的处理、块大小的控制,界面里给不了那么细。所以我的习惯是:单个文件、临时验证用界面;成批的数据一律走命令行或者处理算法。

顺带提一句,QGIS 的处理工具箱里有一个"构建金字塔(Build overviews)"算法,可以批量跑,参数比属性面板全一些,适合几十上百个文件一起处理。它能接入批处理界面,也能保存成模型,规模化作业时比手工点强得多。

3.2 命令行 gdaladdo:参数组合才是关键

真正要谈优化,绕不开gdaladdo。最基本的形式是这样:

gdaladdo -r average --config COMPRESS_OVERVIEW DEFLATE image.tif 2 4 8 16 32 64

这行的意思是:用平均值算法,overview 用 DEFLATE 压缩,建 2 到 64 共六层。看起来简单,实际有几个参数值得细说。

压缩方式。COMPRESS_OVERVIEW控制 overview 的压缩。DEFLATE 是通用选择,无损、压缩比中等;LZW 类似但一般略慢;ZSTD 在新版本 GDAL 里可用,速度更快,如果 QGIS 用的 GDAL 支持,值得一试。如果原始是 8bit 三波段影像,且对精度不那么敏感,可以用 JPEG 压缩配PHOTOMETRIC_OVERVIEW YCBCR,体积能小一大截,但会引入有损误差,做定量分析的数据千万别这么干。

块大小。默认建出来的 overview 块大小可能跟原始不一致,读的时候会有额外的拼块开销。稳妥的做法是显式对齐:

gdaladdo -r average \ --config COMPRESS_OVERVIEW DEFLATE \ --config GDAL_TIFF_OVR_BLOCKSIZE 512 \ image.tif 2 4 8 16 32 64

GDAL_TIFF_OVR_BLOCKSIZE控制 overview 的块尺寸,512 是个比较均衡的值,太小块数多、索引开销大,太大会导致小块请求读进大量无用数据。

大文件与 BigTIFF。超过 4 GB 的文件必须走 BigTIFF,否则写到一半报错。加一个配置项就行:

gdaladdo -r average \ --config COMPRESS_OVERVIEW DEFLATE \ --config BIGTIFF_OVR_BLOCKSIZE 512 \ --config BIGTIFF_OVERVIEW YES \ large_image.tif 2 4 8 16 32 64 128

只读源与临时文件。如果源文件在只读位置,得用-ro让它以只读方式打开,然后把.ovr写到可写目录(需要配合--config GDAL_PAM_PROXY_DIR之类,实际要看版本)。

NoData 的处理。较新版本的gdaladdo支持-srcnodata和-dstnodata,能显式告诉它"这些值不参与计算"。老版本没有这个参数,就得先用gdal_translate -a_nodata把 NoData 值写进源文件的元数据里。这一点非常关键,下一节会详细讲。

参数不是背出来的,是试出来的。我的建议是:先拿一个代表性文件的子集做实验,用gdalinfo -stats看结果,确认没问题再全量跑。全量跑一次几十小时,返工成本太高。

3.3 三层验证:文件层、GDAL 层、QGIS 层

建完不等于生效,得验证。我一般分三层看。

第一层看文件:gdalinfo image.tif输出里会有一段Overviews或者Pyramids信息,列出每一层的尺寸。这一层确认 overview 确实写进去了。

第二层看读取:用gdalinfo -stats或者开--debug on看实际读的时候有没有命中 overview。更直接的办法是用gdal_translate带-outsize参数模拟小尺寸读取,观察耗时变化。

第三层也是最终的:在 QGIS 里实际缩放一遍。全图视图加载时间、连续缩放的流畅度、放大到原始分辨率时是否清晰,这三个指标一起看。有个小技巧——把图层属性的"金字塔"页签打开,如果能看到层级列表,说明 QGIS 认出来了;如果列表空着但文件里明明有,那多半是 QGIS 用的 GDAL 版本不认这个格式,或者.ovr文件名对不上。

4. 建了金字塔反而更糟?四类症状的排查链路

4.1 影像边缘发黑、发暗、出现黑框

这是最经典的问题,根源在 NoData 参与平均。举个例子:一张影像有效区域是不规则形状,周边填充值是 0,但没有在文件里声明"0 就是 NoData"。建 overview 的时候,average算法会把边缘窗口里的 0 一起平均进去,结果就是边缘一圈像素被拉暗,形成渐变黑边。缩得越小,黑边越宽。

排查顺序是这样的:先用gdalinfo看NoData Value有没有值。空的,基本就能确诊。解决办法有两条:

  • 源文件层面:gdal_translate -a_nodata 0 in.tif out.tif,把 NoData 明确写进去,再重建金字塔。
  • 构建层面:较新版本的gdaladdo直接加-srcnodata 0 -dstnodata 0。

还有一种情况不是 NoData 造成的:如果影像是 RGBA 四波段且 alpha 通道没被识别,也会出现类似的暗边。这时候要在 QGIS 里检查图层属性的透明度设置,或者在gdaladdo时确保 alpha 波段被正确识别。

补充一句经验:NoData 的值要和实际填充值一致。见过有人在源数据里填的是 255,元数据里写的是 0,结果建完金字塔边缘出现一圈白边,排查了半天才发现是元数据写错了。

4.2 分类图斑糊成一团、出现不存在的类别

这个问题的原因很单纯:算法选错了。分类栅格用了average或者cubic,平均出来一个 3.7,而类别只有 1、2、3、4,于是渲染器找不到对应颜色,要么显示为透明,要么被拉伸成奇怪的颜色。

判断方法很直观:把视图缩到概览级别,如果原本清晰的边界变得模糊、出现半透明过渡,基本就是插值类算法造成的。修复很简单,重建的时候换成mode或者nearest。mode的效果一般比nearest好,因为它做的是窗口投票,不会像抽样那样随机丢掉小块图斑。

我个人的偏好是:分类数据一律用mode,只有在类别极多、窗口内众数不明显的情况下才退回nearest。另外,分类栅格的 overview 也不要用有损压缩,JPEG 会把不同类别的像素混在一起,这在语义上是灾难性的。

4.3 文件明明有金字塔,缩放还是卡

这一类排查起来最费劲,因为有多个可能的原因,得一个个排除。

第一个怀疑对象:QGIS 没读到 overview。可能的原因包括.ovr文件和主文件不在同一目录、文件名后缀大小写不一致、内部 overview 写的格式 QGIS 的 GDAL 版本不支持。用 QGIS 属性面板的"金字塔"页签看一眼,最直接。

第二个:块大小不对。如果 overview 的块是 128×128,而每次请求要读的区域横跨几十个块,请求开销就会很大。解决办法是重建 overview 时指定GDAL_TIFF_OVR_BLOCKSIZE 512,并且让原始文件的块大小和 overview 对齐(比如原始也是 512)。原始文件不分块(striped)的时候,这一点尤其明显,因为条带式的 TIFF 每次读取都要跨越很长的数据。

第三个:压缩太狠。用了最高级别的 DEFLATE 或者 ZSTD,单块解压耗时比读原始数据还长。这种情况在机械盘上不明显,在 SSD 或者内存盘上就会暴露出来。折中方案是降低压缩级别,--config COMPRESS_OVERVIEW DEFLATE --config ZLEVEL 6之类的配置可以调。

第四个:QGIS 的渲染管线本身。多波段影像如果叠加了复杂的符号化(比如多波段彩色配拉伸、伪彩色色带、混合模式),渲染耗时可能远大于读取耗时。这时候优化金字塔没有意义,得去调渲染设置——关闭不必要的重采样、简化色带、降低画布刷新频率。

我的排查顺序是:先看属性面板有没有识别出 overview,再看请求耗时(用--debug on抓日志),最后才怀疑渲染。别一上来就重建金字塔,那是最费时的操作,八成也不是根因。

4.4 拉伸效果变了,原来的配色全乱

这个坑比较隐蔽。QGIS 打开栅格时会做统计(最小值、最大值、均值、标准差),用来做对比度拉伸。如果 overview 建进去之后,统计计算把 overview 层也算进去了,得到的极值可能和全分辨率不一致,拉伸结果就会偏色。

尤其在"Estimated"和"Actual"统计之间切换的时候,你能看到画面明显变样。解决办法是在图层属性里手动锁定最小/最大值,或者把统计值固化到.aux.xml里(用gdalinfo -stats生成后随数据一起分发)。这样不管谁打开、有没有 overview,颜色都是一致的。

还有个小细节:如果数据做过位深转换(比如 16bit 转 8bit),一定要在建金字塔之前转完。先建 overview 再转位深,等于白建一次。

5. 压缩、分块、缓存:让金字塔真正跑起来的配套设置

5.1 压缩算法不是越强越好

压缩和读取速度之间是一条曲线,不是单调关系。DEFLATE 级别从 6 提到 9,文件能小几个百分点,但构建时间可能翻倍,读取时解压也更慢。我一般的做法是:

数据特点压缩方案说明
8bit 三波段正射影像DEFLATE 级别 6,或 ZSTD兼顾体积与速度
16bit 多光谱DEFLATE 级别 6无损是硬要求
分类栅格DEFLATE 或 LZW绝对不能用 JPEG
展示用影像(可接受有损)JPEG + YCBCR体积能降一半以上
DEM 浮点DEFLATE 或 ZSTD浮点压缩比一般,别期待太高

有一点必须强调:overview 的压缩和主数据的压缩是两回事,可以分开设。主数据无压缩、overview 用 DEFLATE 是完全合理的组合——主数据保证精度,overview 保证浏览速度。

5.2 块大小对齐,读取次数能差一个量级

分块(tiling)对性能的影响比很多人想的大。条带式存储的 TIFF,读一个小窗口可能要跨越整个文件高度;分块存储的,只需要读相邻的几个块。overview 层也一样。

实际配置里,我一般统一成 512×512:

gdal_translate -of GTiff \ -co TILED=YES -co BLOCKXSIZE=512 -co BLOCKYSIZE=512 \ -co COMPRESS=DEFLATE -co BIGTIFF=IF_SAFER \ in.tif out.tif gdaladdo -r average \ --config COMPRESS_OVERVIEW DEFLATE \ --config GDAL_TIFF_OVR_BLOCKSIZE 512 \ out.tif 2 4 8 16 32 64

为什么是 512 而不是 256 或者 1024?256 块数太多,索引和请求开销上来;1024 单块太大,局部读取会读进大量无用数据。512 是个经验上的甜点,绝大多数场景够用。当然如果你的典型视口特别大(比如 4K 屏幕全屏浏览),可以试试 1024,实测对比再定。

5.3 GDAL 缓存与 QGIS 设置的配合

GDAL 有一个块缓存,由GDAL_CACHEMAX控制。默认值通常偏小(几十到一百多 MB),大图浏览时会频繁淘汰。调到 512 MB 到 1 GB 往往有明显改善,尤其是反复缩放同一区域的时候。

在 QGIS 里可以通过"设置 → 选项 → GDAL"配置这些环境变量,也可以直接设系统环境变量。命令行验证的时候可以直接带上:

gdalinfo --config GDAL_CACHEMAX 1024 image.tif

另外 QGIS 自身也有栅格缓存设置,在"选项 → 渲染"里能调。这个缓存的是已经渲染好的图像块,和 GDAL 的块缓存是两层,配合起来效果最好:GDAL 缓存负责"少读磁盘",QGIS 缓存负责"少重复渲染"。

还有一个容易忽略的点:网络盘场景下缓存的意义更大。同样是 512 MB 缓存,本地 SSD 上可能感知不明显,但在延迟高的网络存储上,能减少大量往返请求。

6. 两套可复现的处理链路,照着改就能用

6.1 正射影像:从原始 TIFF 到流畅底图

假设手头是一批无压缩的 8bit 三波段正射影像,单幅几十 GB,目标是在 QGIS 里做浏览底图,最小看到 1:50000。

第一步,先确认原始分辨率和 NoData 情况:

gdalinfo -stats input.tif | head -40

看Pixel Size、NoData Value、Block三项。如果Block显示的是256x256之类就是已分块,显示一整行数字就是条带式,需要重排。

第二步,重排加分块加压缩:

gdal_translate -of GTiff \ -co TILED=YES -co BLOCKXSIZE=512 -co BLOCKYSIZE=512 \ -co COMPRESS=DEFLATE -co ZLEVEL=6 \ -co BIGTIFF=IF_SAFER \ -co NUM_THREADS=ALL_CPUS \ input.tif step1.tif

第三步,确认 NoData 已写入(gdalinfo里能看到NoData Value),没有的话补一步:

gdal_translate -a_nodata 0 step1.tif step2.tif

第四步,建金字塔,层数按前面算的 64 封顶:

gdaladdo -r average \ --config COMPRESS_OVERVIEW DEFLATE \ --config GDAL_TIFF_OVR_BLOCKSIZE 512 \ --config BIGTIFF_OVERVIEW YES \ step2.tif 2 4 8 16 32 64

第五步,验证并固化统计值:

gdalinfo -stats step2.tif | grep -A5 Overviews

-stats会顺手把统计写进.aux.xml,随文件一起分发,QGIS 打开时拉伸就一致了。

这套流程跑下来,一幅 40 GB 左右的影像大概需要一到几小时,取决于磁盘和 CPU。时间主要花在重排和压缩上,建 overview 本身反而快。

6.2 DEM:连续数据要防的是"台阶"和"边缘"

DEM 的处理逻辑和影像不完全一样。核心差异在算法和位深:DEM 一般是 16bit 整型或者 32bit 浮点,用average或者cubic都行,但nearest会让地形出现明显台阶,在山脊和沟谷处尤其难看。

另外 DEM 常见的问题是"边界悬崖":数据范围边缘外的填充值(常是 -9999 或者 0)参与平均后,会在边缘形成一圈不真实的低值或高值。处理方式和影像一样,先把 NoData 声明清楚。

gdal_translate -a_nodata -9999 dem_raw.tif dem_clean.tif gdaladdo -r average \ --config COMPRESS_OVERVIEW DEFLATE \ --config GDAL_TIFF_OVR_BLOCKSIZE 512 \ dem_clean.tif 2 4 8 16 32 64

如果 DEM 要做坡度、坡向这类派生计算,一定用原始分辨率的数据算,不要用 overview 层。overview 是给显示用的,拿它算派生量会得到平滑过头的结果。

还有一点:DEM 的渲染常用山体阴影配合色彩映射,QGIS 里会实时计算 hillshade,这个计算本身就很吃 CPU。这种情况下金字塔能解决读取问题,但渲染还是慢。可行的办法是预先生成一份 hillshade 栅格作为独立图层叠加,把计算成本前置。

6.3 实测对比与参数速查

为了有个直观感受,我用同一批数据做过几组对比(量级参考,具体数值依赖硬件和磁盘):

场景全图视图加载连续缩放流畅度文件体积变化
无金字塔、条带式、无压缩30 秒以上每级都卡基准
有金字塔、条带式4 至 6 秒好转但仍有卡顿+30%
有金字塔、512 分块1 至 2 秒基本流畅+30%
有金字塔、512 分块、DEFLATE1 至 2 秒流畅+5% 至 +10%
COG(内嵌 overview)1 秒左右流畅与上者相当

这张表最想说明的是:金字塔解决的是"读多少",分块解决的是"怎么读",压缩解决的是"读多快",三者不是替代关系。只建金字塔不分块,效果会打折扣;只分块不建金字塔,全图视图还是慢。

常用参数速查:

参数作用常用值
-r降采样算法average / mode / nearest
--config COMPRESS_OVERVIEWoverview 压缩DEFLATE / ZSTD
--config GDAL_TIFF_OVR_BLOCKSIZEoverview 块大小512
--config BIGTIFF_OVERVIEW是否用 BigTIFFYES
-srcnodata/-dstnodataNoData 处理与源数据一致
--config GDAL_CACHEMAX缓存大小(MB)512 至 1024

最后分享一个我在实际工作中养成的小习惯:每批数据处理完,都用 QGIS 打开抽查三张——一张最小幅面、一张最大幅面、一张边缘形状最不规则的。前两张看性能,第三张看 NoData 有没有处理好。这个抽查花不了几分钟,但能把大部分问题拦在交付之前。金字塔这个事,说到底不是"建不建"的问题,是"建得对不对"的问题,而正确与否,往往就藏在那几个参数和源数据的元信息里。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询