一、函数概述
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, -- 掩码及加权参数
-- 后续参数同上
);
三、回调函数规范
- 函数签名:
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;
- 参数解析:
- 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';
五、应用场景
- 遥感影像处理:
- 自定义滤波(如高斯滤波、边缘检测)、指数计算、图像分类。
- 地形分析:
- 坡度 / 坡向计算、地形湿度指数 (TRI)、汇水面积分析。
- 时空模式识别:
- 多时相栅格的变化检测、趋势分析(如 NDVI 时间序列滤波)。
- 机器学习特征工程:
- 栅格特征提取(如纹理、形态学特征)、特征融合。
六、性能优化策略
- 向量化运算:
- 在回调函数中避免逐像素循环,优先使用数组操作(如ARRAY_AGG)。
- 缓存中间结果:
- 对重复使用的参数(如权重矩阵)通过userargs传递,避免重复计算。
- 分块并行处理:
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;
七、注意事项
- 函数 immutable 属性:
- 回调函数必须声明为IMMUTABLE,确保并行计算时结果一致。
- 内存管理:
- 大邻域窗口(如 distancex=10)可能导致内存溢出,建议分块处理。
- 坐标系与分辨率匹配:
- 多栅格运算时需确保坐标系、分辨率一致,必要时使用ST_Resample和ST_Transform。
- NoData 处理:
- 回调函数需显式处理 NULL 值(如IF value IS NOT NULL THEN...)。
通过ST_MapAlgebra的回调函数机制,用户可实现几乎任何栅格处理逻辑,从简单的邻域统计到复杂的机器学习特征提取。该函数作为 PostGIS 栅格处理的可编程接口,为地理空间分析提供了高度灵活的扩展能力,是高级栅格数据处理的核心工具。