了解QGIS栅格地形分析的曲率滤波器?


12

我已经阅读了几个QGis-1.7.4栅格滤波器的源代码,这些栅格滤波器计算斜率,纵横比和曲率。

过滤器中有一个计算总曲率的公式令我困惑。

源文件位于QGis的当前版本中,具有以下路径:

qgis-1.7.4 / src / analysis / raster / qgstotalcurvaturefilter.cpp

该过滤器的目的是在九单元格窗口中计算表面的总曲率。功能代码如下:

float QgsTotalCurvatureFilter::processNineCellWindow( 
   float* x11, float* x21, float* x31, 
   float* x12, float* x22, float* x32, 
   float* x13, float* x23, float* x33 ) {

  ... some code deleted ...

  double dxx = ( *x32 - 2 * *x22 + *x12 ) / ( 1 );
  double dyy = ( -*x11 + *x31 + *x13 - *x33 ) / ( 4 * cellSizeAvg*cellSizeAvg );
  double dxy = ( *x21 - 2 * *x22 + *x23 ) / ( 1 );

  return dxx*dxx + 2*dxy*dxy + dyy*dyy;
}

我对“ dxx”公式和返回表达式没问题。但是我认为“ dyy”和“ dxy”公式是相反的:这使得总结果关于x和y维度不对称。

我是否缺少某些东西,或者应该将双导数表达式替换为:

  double dxx = ( *x32 - 2 * *x22 + *x12 ) / ( 1 ); // unchanged
  // inversion of the two following:
  double dxy = ( -*x11 + *x31 + *x13 - *x33 ) / ( 4 * cellSizeAvg*cellSizeAvg );
  double dyy = ( *x21 - 2 * *x22 + *x23 ) / ( 1 );
  return dxx*dxx + 2*dxy*dxy + dyy*dyy; // unchanged

如果这些公式不符合我的想法,或者我错了,您能否告诉我您对这些公式的看法?在后一种情况下,您知道为什么公式必须关于x和y不对称吗?


3
请报告这些问题,以便将其修复。hub.qgis.org
projects/

哼,如何登录此链接?当然,该网站似乎没有与论坛共享帐户,但是我看不到任何“创建帐户” ...预先感谢您的回答。
Tapadi 2012年

1
该网站使用osgeo登录名www2.osgeo.org/cgi-bin/ldap_create_user.py
underdark

Answers:


8

您的推测是正确的。 检查对称性是一个好主意:(高斯)曲率是表面的固有属性。因此,旋转网格不应改变它。但是,旋转会引入离散误差-旋转90度的倍数除外。因此,任何此类旋转均应保留曲率。

通过利用微积分的第一个概念,我们可以了解正在发生的事情:导数是差商的极限。这就是我们真正需要知道的。

dxx假定它是x方向上二阶导数的离散近似。通过沿着穿过单元的水平断面对表面进行采样,可以计算出这种特殊的近似值(从多种可能中得出)。横断面位于第2行和第2列的中心单元格上,写为(2,2),通过(1,2,2,2,2)和(3,2)单元格。

沿该样条线,阶导数由它们的商(* x32- * x22)/ L和(* x22- * x12)/ L近似表示,其中L是像元之间的(公共)距离(显然等于cellSizeAvg)。通过这些微分的商得到二阶导数,得到

dxx = ((*x32-*x22)/L - (*x22-*x12)/L)/L
    = (*x32 - 2 * *x22 + *x12) / L^2.

注意除以L ^ 2!

类似地,dyy认为是在y方向上的第二偏导数的离散近似。横断面是垂直的,穿过(2,1),(2,2)和(2,3)的像元。该公式将与该公式相同,dxx但带有下标。那将是问题中的第三个公式-但您仍然需要除以L ^ 2。

dxy可以通过将两个单元格分开来估计混合的二阶偏导数。例如,可以通过从右侧的值*减去左侧的值* x13来估计单元格(2,3)(顶部中间单元,而不是中央单元!)上x的一阶导数。 x33,然后除以这些单元格之间的距离2L。通过(* x31-* x11)/(2L)估算单元格(2,1)(底部中间单元格)相对于x的一阶导数。 他们的差异除以2L,估计混合部分,得出

dxy = ((*x33 - *x13)/(2L) - (*x31 - *x11)/(2L))/(2L)
    = (*x33 - *x13 - *x31 + *x11) / (4 L^2).

我不太确定“总”曲率是什么意思,但是它可能是高斯曲率(这是主曲率的乘积)。根据Meek&Walton 2000(方程2.4),通过将dxx * dyy-dxy ^ 2(注意是负号!-这是一个行列式)除以表面梯度范数的平方来获得高斯曲率。因此,问题中引用的返回值并不完全是曲率,但它看起来确实像是高斯曲率的混乱局部表达式。

然后,我们在代码中发现了六个错误,其中大多数是严重的:

  1. dxx需要除以L ^ 2,而不是1。

  2. dyy需要除以L ^ 2,而不是1。

  3. dxy的符号不正确。(不过,这对曲率公式没有影响。)

  4. 如您所注意,dyy和dxy的公式混合在一起。

  5. 返回值中的术语缺少负号。

  6. 它实际上不计算曲率,而仅计算曲率的有理表达式的分子。


作为一个非常简单的检查,让我们验证修改后的公式对于二次曲面上的水平位置是否返回了合理的值。以这样的位置为坐标系的原点,并以其高程为零高度,所有这样的表面都具有以下形式的方程

elevation = a*x^2 + 2b*x*y + c*y^2.

对于常数a,b和c。中心正方形位于坐标(0,0)处,其左侧的一个坐标为(-L,0),依此类推。九个海拔分别为

*x13 *x23 *x33     (a-2b+c)L^2, (c)L^2, (a+2b+c)L^2
*x12 *x22 *x32  =  (a)L^2,      0,      (a)L^2
*x11 *x21 *x31     (a+2b+c)L^2, (c)L^2, (a-2b+c)L^2

根据修改后的公式,

dxx = (a*L^2 - 2*0 + a*L^2) / L^2
    = 2a;

dxy = ((a+2b+c)L^2 - (a-2b+c)L^2 - (a-2b+c)L^2 + (a+2b+c)L^2)/(4L^2)
    = 2b;

dyy = ... [computed as in dxx] ... = 2c.

曲率估计为2a * 2c-(2b)^ 2 = 4(ac-b ^ 2)。(在这种情况下,Meek&Walton公式中的分母是一个。)这有意义吗?尝试一些简单的a,b和c值:

  • a = c = 1,b =0。这是一个圆形的抛物面;其高斯曲率应为正。4(ac-b ^ 2)的值确实为正(等于4)。

  • a = c = 0,b =1。这是一张薄片的双曲面-鞍形- 曲率表面的标准示例。果然4(ac-b ^ 2)= -4。

  • a = 1,b = 0,c = -1。这是一张纸的双曲面(旋转45度)的另一个方程。再一次,4(ac-b ^ 2)= -4。

  • a = 1,b = 0,c =0。这是一个折叠成抛物线形的平面。现在,4(ac-b ^ 2)= 0:零高斯曲率可以正确检测该表面的平坦度。

如果您尝试这些示例中问题中的代码,您将发现它总是得到错误的值。


每天早上阅读您的详尽报道总是很有趣的。
Tomek 2012年

@Tomek现在一个外交(机智且高度模棱两可)的评论!:-)
whuber

1
非常感谢您提供如此完整的答案!由于要确保要报告的内容,因此我将报告公式错误。:)
Tapadi

@whuber:我可以确认Tomek的回复,在这个论坛上阅读您的评论总是很有趣,而且我总是从他们那里学到新东西!感谢您与我们免费分享宝贵的知识!!您是否愿意再问一个问题:在任何GIS应用程序中,执行地形(栅格)的曲率分析时,始终是高斯曲率?从来没有平均曲率?
马可(Marco)2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.