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

山体阴影基本原理:

山体阴影是假想一个光源在某个方向和某个太阳高度的模拟下。用过临近像元的计算来生成一副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_radAspect_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); }

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

  1. ArcGIS使用技巧(四)——山体阴影

    新手,若有错误还请指正! 最近在制图的时候出现如下的情况(图1),怎么调整Display的三个参数都没用. 图 1 查看其信息,发现dem的像元大小为0.00027(图2),是未投影的 图 2 查看A ...

  2. Python下探究随机数的产生原理和算法

    资源下载 #本文PDF版下载 Python下探究随机数的产生原理和算法(或者单击我博客园右上角的github小标,找到lab102的W7目录下即可) #本文代码下载 几种随机数算法集合(和下文出现过的 ...

  3. 3D模板阴影原理

    3D模板阴影原理 1:先从3dsMax中导出一个简单的场景,一个园环,球,平面. 2:园环直接面向光源,园环对球体来说是一个光线的阻挡物,园环在它上面形成阴影,同时,园环和球体对平面来说是光线的阻挡物 ...

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

    (一)认识回归 回归是统计学中最有力的工具之中的一个. 机器学习监督学习算法分为分类算法和回归算法两种,事实上就是依据类别标签分布类型为离散型.连续性而定义的. 顾名思义.分类算法用于离散型分布预測, ...

  5. 机器学习经典算法具体解释及Python实现--K近邻(KNN)算法

    (一)KNN依旧是一种监督学习算法 KNN(K Nearest Neighbors,K近邻 )算法是机器学习全部算法中理论最简单.最好理解的.KNN是一种基于实例的学习,通过计算新数据与训练数据特征值 ...

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

    ---------------------------------------------------------------------------------------------------- ...

  7. 红黑树之 原理和算法详细介绍(阿里面试-treemap使用了红黑树) 红黑树的时间复杂度是O(lgn) 高度<=2log(n+1)1、X节点左旋-将X右边的子节点变成 父节点 2、X节点右旋-将X左边的子节点变成父节点

    红黑树插入删除 具体参考:红黑树原理以及插入.删除算法 附图例说明   (阿里的高德一直追着问) 或者插入的情况参考:红黑树原理以及插入.删除算法 附图例说明 红黑树与AVL树 红黑树 的时间复杂度 ...

  8. KMP算法具体解释(转)

    作者:July. 出处:http://blog.csdn.net/v_JULY_v/. 引记 此前一天,一位MS的朋友邀我一起去与他讨论高速排序,红黑树,字典树,B树.后缀树,包含KMP算法,只有在解 ...

  9. AdaBoost原理,算法实现

    前言: 当做重要决定时,大家可能综合考虑多个专家而不是一个人的意见.机器学习处理问题也是如此,这就是元算法背后的思路.元算法是对其他算法进行组合的一种方式,前几天看了一个称作adaboost方法的介绍 ...

随机推荐

  1. lua入门demo(HelloWorld+redis读取)

    1. lua入门demo 1.1. 入门之Hello World!! 由于我习惯用docker安装各种软件,这次的lua脚本也是运行在docker容器上 openresty是nginx+lua的各种模 ...

  2. Ubuntu 18.04搭建Git服务器

    学习链接:博客园.廖雪峰 一 前言 前面已经贴了两个链接,为什么还要再写一篇呢,因为可能由于个人能力问题,我觉得上面两篇写的都有点简略,有些地方不太好理解,并不能一次性成功搭建,所以想根据自己踩过的坑 ...

  3. iOS学习——@class和#import、#include的区别

    在iOS开发过程中,我们在一些源码中经常会看到导包的时候有的用#import进行导包,但是有的的时候也会看到用@class进行导包,那么这两种方式有什么区别呢? 一 @class和#import的主要 ...

  4. sql中base64解码、译码

    1.5.6版本及之后的版本的base64 主要就是两个MySQL内部函数to_base64和from_base64,使用也很简单,如下: 1)先查看MySQL的版本:mysql> select ...

  5. 如何配置React Native真机调试-iOS

    说在前面,本教程是建立在项目已经成功在模拟器上运行的基础上,如果你是还未配置好环境的新手,建议先从官网快速入门开始:官网英文版 . 中文版 ok, 切入正题,当你已经完成好环境配置,在模拟器上成功的运 ...

  6. springboot项目部署云服务器

    Springboot项目部署云服务器 springboot项目部署云服务器还是挺简单的 首先你要有java运行环境,就是jdk的安装,如果还没有装没有参考安装:阿里云ECS建网站(建站)超详细全套完整 ...

  7. 关于 Uboot 中有趣的 0xdeadbeef 填充

    在 Uboot 的 Start.S 中存在以下源码: .globl _start _start: b start_code ldr pc, _undefined_instruction ldr pc, ...

  8. zabbix实现百台服务器的自动化监控--技术流ken

    前言 最近有小伙伴通过Q联系到我说:公司现在有百多台服务器,想要部署zabbix进行监控,怎么实现自动化全网监控? 本篇博客将讲解一个我工作时做的一个实际项目,现在写出来供大家以后参考使用. 实现自动 ...

  9. golang使用chrome headless获取网页内容

    如今动态渲染的页面越来越多,爬虫们或多或少都需要用到headless browser来渲染待爬取的页面. 而最近广泛使用的headless browser解决方案PhantomJS已经宣布不再继续维护 ...

  10. 另类爬虫:从PDF文件中爬取表格数据

    简介   本文将展示一个稍微不一样点的爬虫.   以往我们的爬虫都是从网络上爬取数据,因为网页一般用HTML,CSS,JavaScript代码写成,因此,有大量成熟的技术来爬取网页中的各种数据.这次, ...