DEM山体阴影原理以及算法具体解释

山体阴影原理以及算法具体解释

山体阴影基本原理:

山体阴影是假想一个光源在某个方向和某个太阳高度的模拟下。用过临近像元的计算来生成一副0-255的灰度图。

一、山体阴影的主要參数:

1、  太阳光线的入射角度:这个角度的量算起点是正北方向,依照顺时针的方向,角度的范围是0到360度。例如以下图所看到的,默认的角度是315度,西北方向,例如以下图所看到的:

2、  太阳高度角:太阳高度角也简称太阳高度。是太阳光线和当地地平面之间的夹角,范围是0-90度,默认的太阳高度是45度,例如以下图所看到的:

二、山体阴影计算方法

山体阴影的计算公式例如以下

(1)  Hillshade = 255.0 * ((cos(Zenith_rad)* cos(Slope_rad)) +

(sin(Zenith_rad) * sin(Slope_rad) * cos(Azimuth_rad- Aspect_rad)))

假设Hillshade < 0, 则设Hillshade=0.

当中,Zenith_rad是太阳天顶角的的弧度数。Slope_rad是某一点的坡度弧度数,Azimuth_rad是指太阳光线方向角的弧度数。Aspect_rad是某一点的坡向弧度数。

计算山体阴影的照明光源的角度默认是太阳高度角,可是真正计算时。须要用到太阳天顶角,太阳天顶角的计算方法是90°-太阳高度角。所以有例如以下计算公式:

计算太阳天顶角弧度数:

(2)  Zenith_deg = 90 - Altitude

转换为弧度数:

(3)  Zenith_rad = Zenith * pi / 180.0
 
计算照明的方向:

照明的方向角是指定的角度数,山体阴影的计算公式须要弧度数。

首先,须要将地理上的指南针方向转换为数学上的向右的方向。即向右为起算的方向;其次。须要将角度转换为弧度。

转为数学上的方向角:

(4)  Azimuth_math = 360.0 - Azimuth + 90

注意假设 Azimuth_math >=360.0, 那么:

(5)  Azimuth_math = Azimuth_math - 360.0

转换为弧度:

(6)  Azimuth_rad = Azimuth_math * pi / 180.0
 
计算坡度和坡向
坡度和坡向是利用一个3*3的窗体在输入影像中訪问每一个像素,9个像素从左到右、从上到下分别用a-i表示,如图所看到的:
a b c
d e f
g h i
E像元X方向上的变化率採用例如以下的算法: 
(7)  [dz/dx] = ((c + 2f + i) - (a + 2d + g)) / (8 * cellsize)

E像元Y方向上的变化率採用例如以下的算法:

 (8)  [dz/dy] = ((g + 2h + i) - (a + 2b + c)) / (8 * cellsize)

坡度的弧度计算公式,考虑了Z因子(协调Z方向的单位和Xy平面上单位的一个系数):

(9)  Slope_rad = atan (z_factor * sqrt ([dz/dx]2 + [dz/dy]2)) 
 

坡向通过以下的方法进行计算:

If [dz/dx] is non-zero:

Aspect_rad= atan2 ([dz/dy], -[dz/dx])

if Aspect_rad< 0 then

Aspect_rad= 2 * pi + Aspect_rad

If [dz/dx] iszero:

if [dz/dy] >0 then

Aspect_rad= pi / 2

else if [dz/dy]< 0 then

Aspect_rad= 2 * pi - pi / 2

else

Aspect_rad = Aspect_rad

山体阴影计算演示样例:出自arcgis10.0帮助文档。

最后,奉上OpenCL实现的代码:

__kernel void hillshade_kernel( __global const float *pSrcData,
						 __global float *pDestData,const int nWidth,const int nHeight
						 , struct HillshadeOption hillOption)
{
	int j = get_global_id(0);
	int i = get_global_id(1);

	if (j >= nWidth || i >= nHeight)
		return;

	int nTopTmp = i-1;
	int nBottomTmp = i+1;
	int nLeftTep = j-1;
	int nRightTmp = j+1;

	//处理边界情况
	if (0 == i)
	{
		nTopTmp = i;
	}
	if (0 == j)
	{
		nLeftTep = j;
	}
	if (i == nHeight-1)
	{
		nBottomTmp = i;
	}
	if (j == nWidth-1)
	{
		nRightTmp = j;
	}
	__local float afRectData[9];
	afRectData[0] = pSrcData[nTopTmp*nWidth+nLeftTep];
	afRectData[1] = pSrcData[nTopTmp*nWidth+j];
	afRectData[2] = pSrcData[nTopTmp*nWidth+nRightTmp];

	afRectData[3] = pSrcData[i*nWidth+nLeftTep];
	afRectData[4] = pSrcData[i*nWidth+j];
	afRectData[5] = pSrcData[i*nWidth+nRightTmp];

	afRectData[6] = pSrcData[nBottomTmp*nWidth+nLeftTep];
	afRectData[7] = pSrcData[nBottomTmp*nWidth+j];
	afRectData[8] = pSrcData[nBottomTmp*nWidth+nRightTmp];

	const float degreesToRadians = (M_PI_F / 180);

	float dx = ((afRectData[2]+ afRectData[5]*2 + afRectData[8]) -
		(afRectData[0] + afRectData[3]*2 + afRectData[6])) / (8 * hillOption.dbEwres);

	float dy = ((afRectData[6] + afRectData[7]*2 + afRectData[8]) -
		(afRectData[0]+ afRectData[1]*2 + afRectData[2])) / (8 * hillOption.dbNsres);

	//计算坡度(弧度)
	float key = sqrt(dx *dx + dy * dy);
	float dfSlope = atan( hillOption.dfzScaleFactor *  key);

	//计算坡向(弧度)
	float dfAspect = 0;
	if (dx != 0)
	{
		dfAspect = atan2(dy,-dx);
		if (dfAspect < 0)
		{
			dfAspect += 2* M_PI_F;
		}
	}

	if (dx == 0)
	{
		if (dy > 0.0f)
		{
			dfAspect = M_PI_F / 2;
		}

		else if (dy < 0.0f)
			dfAspect = M_PI_F + M_PI_F / 2;
	}

	//将太阳高度和太阳光线角度转换为要求的格式
	float dfZenithDeg = hillOption.dfAltitude;

	float dfAzimuthRad = hillOption.dfAzimuth;

	//最后计算山体阴影值
	float dfHillshade = 255 * (cos(dfZenithDeg)*cos(dfSlope) +
		sin(dfZenithDeg)*sin(dfSlope)*cos(dfAzimuthRad-dfAspect));
	if (dfHillshade < 0)
	{
		dfHillshade = 0;
	}

	if (dfHillshade >= 255)
	{
		dfHillshade = 255;
	}

	pDestData[i*nWidth+j] = (int)(dfHillshade+1/2); 

}
时间: 2024-11-05 17:30:09

DEM山体阴影原理以及算法具体解释的相关文章

DEM山体阴影原理以及算法详解

山体阴影原理以及算法详解 山体阴影基本原理: 山体阴影是假想一个光源在某个方向和某个太阳高度的模拟下,用过临近像元的计算来生成一副0-255的灰度图. 一.山体阴影的主要参数: 1.  太阳光线的入射角度:这个角度的量算起点是正北方向,按照顺时针的方向,角度的范围是0到360度,如下图所示,默认的角度是315度,西北方向,如下图所示: 2.  太阳高度角:太阳高度角也简称太阳高度.是太阳光线和当地地平面之间的夹角,范围是0-90度,默认的太阳高度是45度,如下图所示: 二.山体阴影计算方法 山体

arcgis中山体阴影制作方法研究

一. 数据介绍 本文使用的数据为全国30米分辨率的ASTER DEM,数据量大小为58G,WGS84坐标,像元类型为SIGNED 16 BIT INTEGER.NASA公开了全球30米分辨率的ASTER DEM,并可以免费下载. 二.山体阴影生成 我们知道,在ArcMap中有Hillshade工具用来生成山体阴影;ERDAS提供Shaded Relief工具;ENVI的山体阴影工具存放在Topographic Modeling中.我们分别使用这三款软件进行山体阴影的生成,结果如下所示: 整个生成

高斯模糊原理,算法

高斯模糊原理,算法 参考文章:图像卷积与滤波的一些知识点 要学习高斯模糊我们首先要知道一些基本概念: 线性滤波与卷积的基本概念 线性滤波可以说是图像处理最基本的方法,它可以允许我们对图像进行处理,产生很多不同的效果.做法很简单.首先,我们有一个二维的滤波器矩阵(有个高大上的名字叫卷积核)和一个要处理的二维图像.然后,对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,然后加起来,作为该像素位置的值.这样就完成了滤波过程. 对图像和滤波矩阵进行逐个元素相乘再求和的操作就相当于将一

二叉树链表中一个结论的证明以及 Successor() 函数中算法的解释

首先, 先明确 “结点 x 的 successor” 的概念. 这句话的概念是, successor 是整个二叉树中, key 仅比 x 的 key 大的结点. 求证: 若 x 有两个孩子, 那么其 successor 没有左孩子. 证明: 若 x 有两个孩子, 则其右子树存在.在二叉树链表中, 对于任意 x 的右子树都是 key 比 x 的 key 大的结点的集合, 即{y|y->key > x->key}.根据 successor  的定义, 若 x->rightChild ≠

红黑树(一)之 原理和算法详细介绍---转帖

目录1 红黑树的介绍2 红黑树的应用3 红黑树的时间复杂度和相关证明4 红黑树的基本操作(一) 左旋和右旋5 红黑树的基本操作(二) 添加6 红黑树的基本操作(三) 删除 作者:Sky Wang    于 2013-08-08 概述:R-B Tree,又称为"红黑树".本文参考了<算法导论>中红黑树相关知识,加之自己的理解,然后以图文的形式对红黑树进行说明.本文的主要内容包括:红黑树的特性,红黑树的时间复杂度和它的证明,红黑树的左旋.右旋.插入.删除等操作. 请尊重版权,转

3D模板阴影原理

3D模板阴影原理 1:先从3dsMax中导出一个简单的场景,一个园环,球,平面. 2:园环直接面向光源,园环对球体来说是一个光线的阻挡物,园环在它上面形成阴影,同时,园环和球体对平面来说是光线的阻挡物,所以,同时在其上面形成阴影. 3: 要产生模板阴影,先要找出在园环和球体上面面向光线的面,去除背向光线的面,通过测试光线同园环和球体上面每一个所组成的小角形的法线的夹角是否小于90度,即光线矢量同法线矢量的点积要大于零. 4:在余下的所有面向光线的面中,把每个面的每条边可以保存到一个Vector中

MapReduce原理——PageRank算法Java版

Page Rank就是MapReduce的来源,下文是一个简单的计算PageRank的示例. import java.text.DecimalFormat; /**  * Created by jinsong.sun on 2014/7/15.  */ public class PageRankCaculator {     public static void main(String[] args) {         double[][] g = calcG(genS(), 0.85);  

KMP算法具体解释(贴链接)

------------------------------------------------------------------------------------------------------------------------------------------------------ 欢迎光临天资小屋:http://user.qzone.qq.com/593830943/main --------------------------------------------------

机器学习经典算法具体解释及Python实现--线性回归(Linear Regression)算法

(一)认识回归 回归是统计学中最有力的工具之中的一个. 机器学习监督学习算法分为分类算法和回归算法两种,事实上就是依据类别标签分布类型为离散型.连续性而定义的. 顾名思义.分类算法用于离散型分布预測,如前面讲过的KNN.决策树.朴素贝叶斯.adaboost.SVM.Logistic回归都是分类算法.回归算法用于连续型分布预測.针对的是数值型的样本,使用回归.能够在给定输入的时候预測出一个数值.这是对分类方法的提升,由于这样能够预測连续型数据而不不过离散的类别标签. 回归的目的就是建立一个回归方程