PostGIS强大栅格分析工具-栅格代数运算(回调函数版)【ST_MapAlgebra 】

一、函数概述

ST_MapAlgebra最灵活的栅格代数运算函数,支持通过用户自定义的回调函数对单栅格、多栅格或多波段进行像素级处理。与表达式版本不同,该函数通过注册存储过程(regprocedure)实现复杂逻辑,可处理邻域分析、自定义滤波、多源数据融合等高级场景,是栅格数据处理的可编程接口。

二、核心参数与语法结构

sql 复制代码
-- 多栅格/波段版本(变体1)
raster ST_MapAlgebra(
  rastbandarg[] rastbandargset,     -- 栅格-波段参数数组
  regprocedure callbackfunc,        -- 回调函数
  text pixeltype = NULL,            -- 输出像素类型
  text extenttype = 'INTERSECTION', -- 输出范围类型
  raster customextent = NULL,       -- 自定义范围
  integer distancex = 0,            -- X方向邻域距离
  integer distancey = 0,            -- Y方向邻域距离
  text[] VARIADIC userargs = NULL   -- 用户参数
);

-- 单栅格多波段版本(变体2-3)
raster ST_MapAlgebra(
  raster rast, integer[] nband,     -- 栅格及波段数组
  regprocedure callbackfunc,
  -- 后续参数同上
);

-- 双栅格版本(变体4)
raster ST_MapAlgebra(
  raster rast1, integer nband1,     -- 第一栅格及波段
  raster rast2, integer nband2,     -- 第二栅格及波段
  regprocedure callbackfunc,
  -- 后续参数同上
);

-- 带邻域掩码版本
raster ST_MapAlgebra(
  raster rast, integer nband,
  regprocedure callbackfunc,
  float8[] mask, boolean weighted,  -- 掩码及加权参数
  -- 后续参数同上
);

三、回调函数规范

  1. 函数签名:
sql 复制代码
CREATE OR REPLACE FUNCTION callback_func(
  value double precision[][][],   -- 三维值数组(栅格#,行,列)
  position integer[][],           -- 二维位置数组(栅格#,[x,y])
  VARIADIC userargs text[]         -- 用户参数
) RETURNS double precision AS $$
BEGIN
  -- 自定义逻辑
  RETURN 0.0;
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE;
  1. 参数解析:
  • valuerast_idxyx:第rast_idx个栅格中 (x,y) 位置的像素值(1-based)
  • position00:输出栅格的列号,position01:输出栅格的行号
  • userargs:用户传递的自定义参数(如阈值、权重)

四、应用案例

示例 1:单栅格邻域均值计算(3×3 窗口)

sql 复制代码
-- 定义邻域均值回调函数
CREATE OR REPLACE FUNCTION mean_callback(
  value double precision[][][], 
  position integer[][], 
  VARIADIC userargs text[]
) RETURNS double precision AS $$
DECLARE
  sum_val double precision := 0;
  count_val integer := 0;
  i integer; j integer;
BEGIN
  -- 遍历3×3邻域(distancex=1, distancey=1)
  FOR i IN 1..3 LOOP
    FOR j IN 1..3 LOOP
      IF value[1][i][j] IS NOT NULL THEN
        sum_val := sum_val + value[1][i][j];
        count_val := count_val + 1;
      END IF;
    END LOOP;
  END LOOP;
  RETURN CASE WHEN count_val > 0 THEN sum_val / count_val ELSE NULL END;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

-- 应用邻域均值
SELECT ST_MapAlgebra(
  rast := dem_rast,
  nband := 1,
  callbackfunc := 'mean_callback(double precision[], int[], text[])'::regprocedure,
  distancex := 1,
  distancey := 1
) AS smoothed_dem
FROM dem_table
WHERE region = 'mountain';

效果: 通过 3×3 窗口平滑高程栅格,减少噪声。

示例 2:多波段栅格主成分分析(PCA)

sql 复制代码
-- 定义PCA回调函数(简化版,仅演示结构)
CREATE OR REPLACE FUNCTION pca_callback(
  value double precision[][][], 
  position integer[][], 
  VARIADIC userargs text[]
) RETURNS double precision AS $$
DECLARE
  -- 假设userargs[0]为特征向量矩阵路径
  eigenvectors jsonb := userargs[0]::jsonb;
  band1_val double precision := value[1][1][1];
  band2_val double precision := value[2][1][1];
  pca1 double precision;
BEGIN
  -- 主成分1 = 0.7*band1 + 0.7*band2(示例权重)
  pca1 := 0.7 * band1_val + 0.7 * band2_val;
  RETURN pca1;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

-- 对多波段遥感影像执行PCA
SELECT ST_MapAlgebra(
  rastbandargset := ARRAY[
    ROW(landsat_rast, 4)::rastbandarg,  -- 红波段
    ROW(landsat_rast, 5)::rastbandarg   -- 近红外波段
  ],
  callbackfunc := 'pca_callback(double precision[], int[], text[])'::regprocedure,
  userargs := ARRAY['{"weights": [[0.7, 0.7]]}']
) AS pca_rast
FROM landsat_scene
WHERE date = '2023-07-15';

扩展: 实际 PCA 需先计算协方差矩阵,此示例为简化逻辑。

示例 3:双栅格加权融合(NDVI 与湿度指数)

sql 复制代码
-- 定义加权融合函数
CREATE OR REPLACE FUNCTION weighted_fusion(
  value double precision[][][], 
  position integer[][], 
  VARIADIC userargs text[]
) RETURNS double precision AS $$
DECLARE
  ndvi double precision := value[1][1][1];
  wetness double precision := value[2][1][1];
  ndvi_weight double precision := userargs[0]::double precision;
BEGIN
  -- 加权公式:result = ndvi*w + wetness*(1-w)
  RETURN ndvi * ndvi_weight + wetness * (1 - ndvi_weight);
END;
$$ LANGUAGE plpgsql IMMUTABLE;

-- 执行融合(NDVI权重0.6)
SELECT ST_MapAlgebra(
  rast1 := ndvi_rast, nband1 := 1,
  rast2 := wetness_rast, nband2 := 1,
  callbackfunc := 'weighted_fusion(double precision[], int[], text[])'::regprocedure,
  userargs := ARRAY['0.6']
) AS fused_rast
FROM raster_catalog
WHERE ndvi_date = '2023-06-01' AND wetness_date = '2023-06-05';

五、应用场景

  1. 遥感影像处理:
  • 自定义滤波(如高斯滤波、边缘检测)、指数计算、图像分类。
  1. 地形分析:
  • 坡度 / 坡向计算、地形湿度指数 (TRI)、汇水面积分析。
  1. 时空模式识别:
  • 多时相栅格的变化检测、趋势分析(如 NDVI 时间序列滤波)。
  1. 机器学习特征工程:
  • 栅格特征提取(如纹理、形态学特征)、特征融合。

六、性能优化策略

  1. 向量化运算:
  • 在回调函数中避免逐像素循环,优先使用数组操作(如ARRAY_AGG)。
  1. 缓存中间结果:
  • 对重复使用的参数(如权重矩阵)通过userargs传递,避免重复计算。
  1. 分块并行处理:
sql 复制代码
WITH tiles AS (
  SELECT (ST_Tile(rast, 1024, 1024)).* FROM large_raster
),
processed AS (
  SELECT ST_MapAlgebra(rast, nband, callback, ...) AS p_rast
  FROM tiles
  WHERE ST_Area(rast) > 0  -- 跳过空块
  PARALLEL 4  -- 开启4个并行工作者
)
SELECT ST_Mosaic(p_rast) FROM processed;

七、注意事项

  1. 函数 immutable 属性:
  • 回调函数必须声明为IMMUTABLE,确保并行计算时结果一致。
  1. 内存管理:
  • 大邻域窗口(如 distancex=10)可能导致内存溢出,建议分块处理。
  1. 坐标系与分辨率匹配:
  • 多栅格运算时需确保坐标系、分辨率一致,必要时使用ST_Resample和ST_Transform。
  1. NoData 处理:
  • 回调函数需显式处理 NULL 值(如IF value IS NOT NULL THEN...)。

通过ST_MapAlgebra的回调函数机制,用户可实现几乎任何栅格处理逻辑,从简单的邻域统计到复杂的机器学习特征提取。该函数作为 PostGIS 栅格处理的可编程接口,为地理空间分析提供了高度灵活的扩展能力,是高级栅格数据处理的核心工具。

相关推荐
gerrywhu1 天前
【应用实践】PostGIS实现NDVI计算与植被覆盖分级统计分析-以武汉市2025年为例
数据库·postgis·栅格数据分析·st_mapalgebra·ndvi计算·植被覆盖分级统计·植被覆盖计算
_未闻花名_2 天前
PostgreSQL的若干扩展安装和使用
spring boot·postgresql·postgis·timescaledb·pg_cron·pgmq·zhparser
fffzd8 天前
STM32:串口--DMA
stm32·单片机·嵌入式硬件·串口·dma·回调函数
gerrywhu25 天前
PostGIS实现栅格数据合并—影像拼接、镶嵌【ST_Union】
postgis·栅格数据分析·影像镶嵌·栅格合并·st_union·影像拼接
gerrywhu1 个月前
PostGIS实现栅格分块与瓦片生成【ST_Tile】
postgis·栅格数据分析·栅格分块·遥感影像分块·栅格瓦片生成·st_tile·瓦片生成
gerrywhu1 个月前
PostGIS实现栅格数据可视化-单波段映射为多波段彩色栅格【ST_ColorMap】
postgis·栅格分析·栅格数据可视化·st_colormap·多波段彩色栅格·彩色栅格
gerrywhu2 个月前
PostGIS实现栅格数据坐标系转换【ST_Transform】
postgis·坐标转换·栅格分析·栅格数据坐标转换·栅格坐标转换·st_transform
丷丩2 个月前
第 2 篇:入门实操|3dtubetilecreater 环境搭建全教程(零踩坑版)
3d·gis·postgis·管线·自动建模·管网
来自远方的老作者2 个月前
第9章 函数-9.9 函数式编程
python·函数·回调函数·lambda表达式·函数闭包·偏函数·函数装饰器