用BandMath和BandMathX实现图像的运算¶
使用BandMath的简单微积分¶
这个 BandMath 应用程序提供了一种简单而高效的方式来执行逐个像素的操作。它根据用户定义的数学表达式计算逐带运算。下面的代码计算两个图像的前两个带之间的绝对差值。
otbcli_BandMath -il input_image_1 input_image_2
-exp "abs(im1b1 - im2b1)"
-out output_image
命名约定“im” [x] B类 [y] “指定第X个输入图像的第y个频段。
这个 BandMath 应用程序嵌入了中列出的内置运算符和函数 muparser documentation 从而允许有大量可能的操作选择。
使用BandMathX的高级图像操作¶
的一个限制是 BandMath 应用是它只能输出单波段图像,因为u-parser库只支持标量表达式。相反, BandMathX 应用程序基于 mu-parserX 库可以输出单波段和多波段图像,并支持包含标量、向量和矩阵的表达式。下面的代码计算两个图像之间的差异:
otbcli_BandMathX -il input_image_1 input_image_2
-exp "im1 - im2"
-out output_image
此应用程序生成的输出图像具有与输入图像相同的条带数,并且每个生成的条带包含输入图像中相应条带之间的差异。
语法:第一个元素¶
变量及其说明:
变数 | 类型 | 描述 |
---|---|---|
IM1 | 矢量 | 来自第一个输入的像素,由n个分量/波段组成(第一个图像以1为索引) |
Im1bj | 标量 | 来自第一个输入的像素的第j个分量(第一个波段以1为索引) |
Im1bjNkxp | 矩阵 | 来自第一个输入的第j个分量的像素的邻域(“N”),大小为kxp |
Im1bjMini | 标量 | 全局统计:来自第一个输入的第j个频段的最小值 |
Im1bjMaxi | 标量 | 全局统计:从第一个输入开始的第j个频段的最大值 |
Im1bjMean | 标量 | 全局统计:来自第一个输入的第j个频段的平均值 |
Im1bjSum | 标量 | 全局统计:从第一个输入开始的第j个频段的总和 |
Im1bjVar | 标量 | 全局统计:从第一个输入开始的第j个频段的方差 |
Im1PhyX和im1PhyY | 标量 | 第一个输入在X和Y方向上的间距 |
此外,我们还有表示当前像素(标量)索引的泛型变量idxX和idxY。
请注意,使用全局统计将自动使过滤器(或应用程序)从相关输入图像请求尽可能大的区域,而无需用户干预。
例如,下面的公式(两个像素相加)
IM1+IM2
仅当两个第一个输入具有相同的波段数时才正确。此外,即使IM1表示仅由一个带组成的图像的一个像素,下列公式也不一致:
IM1+1
标量不能与向量相加。相反,正确的公式是(人们可以注意到 muParserX 允许动态定义向量):
Im1+{1}
或
Im1+{1,1,1,...,1}
如果IM1由n个成分组成。
另一方面,变量im1b1被表示为标量;因此我们有以下不同的可能性:
正确/不正确的表达方式:
表达式 | 状态 |
---|---|
Im1b1+1 | 对,是这样 |
{im1b1}+{1} | 对,是这样 |
Im1b1+{1} | 不正确 |
{im1b1}+1 | 不正确 |
Im1+{im2b1,im2b2} | 如果im1表示两个分量的像素(等效于im1+im2),则更正 |
乘除也可以做类似的说明,例如下面的公式是不正确的:
\{im2b1,im2b2\} * \{1,2\}
而这一条是正确的:
\{im2b1,im2b2\} * \{1,2\}'
或者更简单地说(仅当IM2包含两个组件时):
Im2*{1,2}‘
关于除法,该运算最初不是在两个向量之间定义的(见下一节 新的运算符和函数 )。
现在,让我们回到第一个公式:这个公式指定在频段之间添加两个图像。使用 muParserX LIB,我们现在可以只用一个公式来定义这样的运算,而不是用很多公式(和带数一样多)。我们将这一新功能称为 batch mode ,它直接产生于在 muParserX 框架。
使用邻里关系的行动¶
让我们简单介绍一下邻域变量。这些变量是为每个特定输入和每个特定频段定义的。最后两个数字kxp表示该社区的大小。所有邻域都居中:这意味着k和p只能是奇数。此外,k表示x方向上的维度(列数),p表示y方向上的维度(行数)。例如,im1b3N3x5表示以下邻域:
。 | 。 | 。 |
---|---|---|
。 | 。 | 。 |
。 | 。 | 。 |
。 | 。 | 。 |
。 | 。 | 。 |
例如,下面的代码使用输入图像的第一个带区,将每个像素周围3x3邻域中的平均值减去像素值:
otbcli_BandMathX -il input_image_1 input_image_2
-exp "im1b1 - mean(im1b1N3x3)"
-out output_image
从根本上说,邻域表示为 muParserX 框架;因此,关于数学上定义明确的公式的评论仍然有效。
涉及位操作的操作¶
有时,操作位而不是实数很有用。例如,有时将多个二进制掩码一起存储在单波段整数图像中。
为了操作位,需要将其数据转换为整数(因为数据是以浮点数的形式读取的)。要做到这一点, muParserX 具有类型转换运算符:(Int)。为您的图像添加前缀将允许您执行此类操作。
- 示例:
(int)im1b1 & 0b00000001
(按位AND)(int)im1b1 >> 1
(右移运算符)
新的运算符和函数¶
除了中提供的运算符和函数外 muParserX 已在(https://beltoforion.de/article.php?a=muparserx),内部实施了新的OTB。这些问题可分为两类:
- 对原来没有为向量和矩阵定义的现有运算符/函数的改编(例如cos、sin等)。这些新的运算符/函数保留了原来的名称,我们在其中添加了向量(vcos、vsin等)的前缀“v”。
- 真正的新运算符/函数。
关于最后一个类别,下面是已实现的运算符或函数的列表(它们都在otbParserXPlugins.h/.cxx文件中实现 OTB/Modules/Filtering/MathParserX ):
Operators div and dv: 第一个运算符允许定义两个向量(甚至矩阵)的按元素除法,前提是它们具有相同的维度。第二种方法允许定义向量/矩阵除以标量(分量除以相同的唯一值)。例如:
Im1~div~im2
Operators mult and mlt: 这些运算符是前几个运算符的对偶。例如:
IM1~MULT~IM2
Operators pow and pw: 第一个运算符允许定义两个向量(甚至是矩阵)的按元素求幂,前提是它们具有相同的维度。第二种方法允许定义向量/矩阵除以标量(分量以相同的唯一值为指数)。例如:
IM1~电源~IM2
IM1~PW~2.0
请注意,可以使用运算符‘*’而不是‘pw’。但是‘pw’稍微宽容一些,它可以将一维向量作为正确的操作数。
Function bands: 此功能允许从图像中选择特定的波段,和/或以新的矢量重新排列它们;例如:
频段(IM1,{1,2,1,1})
从第一个输入中生成由带1、带2、带1和带1值组成的4个分量的向量。请注意,必须使用花括号才能选择所需的波段索引。
Function dotpr: 此函数允许两个向量或矩阵(实际上在我们的例子中是一个核和一个像素邻域)之间的点积:
sum_{(i,j)}m_1(i,j)*m_2(i,j)
例如:
Dotpr(内核1,im1b1N3x5)
如果kernel1和im1b1N3x5具有相同的维度,则是正确的。
Function mean: 此函数允许计算给定向量或邻域的平均值(该函数可以接受所需的任意多个输入;每个输入计算一个平均值)。例如:
平均值(im1b1N3x3、im1b2N3x3、im1b3N3x3、im1b4N3x3)
注意:来自muparserX本身的限制使得使用唯一变量传递所有这些邻居是不可能的。
Function var: 该函数计算给定向量或邻域的方差(该函数可以接受所需的任意多个输入;每个输入计算一个变量值)。例如:
Var(Im1b1N3x3)
Function median: 此函数计算给定矢量或邻域的中值(该函数可以接受所需的任意多个输入;每个输入计算一个中值)。例如:
中位数(Im1b1N3x3)
Function corr: 此函数计算相同维度的两个向量或矩阵之间的相关性(此函数接受两个输入)。例如:
Corr(im1b1N3x3,im1b2N3x3)
Function maj: 此函数计算向量或矩阵中表示最多的元素(该函数可以接受所需的任意多个输入;每个输入计算一个主要元素值)。例如:
Maj(im1b1N3x3,im1b2N3x3)
Function vmin and vmax: 这些函数计算给定向量或邻域的最小或最大值(只有一个输入,输出是一个1x1矩阵)。例如:
(vmax(Im3b1N3x5)+vmin(Im3b1N3x5))~div~{2.0}
Function cat: 该函数将多个表达式的结果连接到一个多维向量中,而不管它们各自的维度(该函数可以接受所需的任意多个输入)。例如:
CAT(im3b1、vmin(Im3b1N3x5)、中位数(Im3b1N3x5)、Vmax(Im3b1N3x5))
注意:在设置表达式时,用户应优先使用分号(;),而不是直接使用此功能。过滤器或应用程序将自动调用函数‘cat’。例如:
Im3b1;vmin(Im3b1N3x5);中位数(Im3b1N3x5);vmax(Im3b1N3x5)
Function ndvi: 该函数实现了经典的归一化差异植被指数;它接受两个输入。例如:
NDVI(im1b1、im1b4)
第一个参数与可见的红色波段有关,第二个参数与近红外波段有关。
下表总结了不同的函数和运算符。
函数和运算符摘要:
变数 | 备注 |
---|---|
NDVI | 两个输入 |
谱带 | 两个输入;第二个矢量输入的长度给出输出的尺寸 |
点对点树 | 多个输入 |
猫 | 多个输入 |
小气 | 多个输入 |
变量 | 多个输入 |
中位数 | 多个输入 |
麦吉 | 多个输入 |
柯尔 | 两个输入 |
Div和dv | 操作员 |
MULT和MLT | 操作员 |
战俘和战俘 | 操作员 |
VNorm | 使现有函数适应向量:一个输入 |
真空吸尘器 | 使现有函数适应向量:一个输入 |
Vmin | 使现有函数适应向量:一个输入 |
VMAX | 使现有函数适应向量:一个输入 |
VCoS | 使现有函数适应向量:一个输入 |
VSIN | 使现有函数适应向量:一个输入 |
VTAN | 使现有函数适应向量:一个输入 |
Vtanh | 使现有函数适应向量:一个输入 |
Vsinh | 使现有函数适应向量:一个输入 |
VCOSH | 使现有函数适应向量:一个输入 |
vlog | 使现有函数适应向量:一个输入 |
Vlog10 | 使现有函数适应向量:一个输入 |
凸起 | 使现有函数适应向量:一个输入 |
VSQRT | 使现有函数适应向量:一个输入 |
向量2比例 | 一维向量到标量 |
上下文和常量¶
多亏了 -incontext 可以将常量值传递给应用程序,以便在表达式中使用它。对于常量的定义,必须遵循以下模式:#type name value。例如:
#F expo 1.1 #M kernel1 { 0.1 , 0.2 , 0.3 ; 0.4 , 0.5 , 0.6 ; 0.7 , 0.8 , 0.9 ; 1 , 1.1 , 1.2 ; 1.3 , 1.4 , 1.5 }
正如我们所看到的,#I/#F允许定义整型/浮点型常量,而#M允许定义向量/矩阵。还可以在同一个文本文件中使用模式#E Expr定义表达式。例如:
#F expo 1.1 #M kernel1 { 0.1 , 0.2 , 0.3 ; 0.4 , 0.5 , 0.6 ; 0.7 , 0.8 , 0.9 ; 1 , 1.1 , 1.2 ; 1.3 , 1.4 , 1.5 } #E dotpr(kernel1,im1b1N3x5)