GDAL库学习笔记(1):无缝拼接Google卫星图
开工之前要先了解一下瓦片地图,瓦片地图金字塔模型是一种多分辨率层次模型,从瓦片金字塔的底层到顶层,分辨率越来越低,但表示的地理范围不变。实现原理就是,首先确定地图服务平台所要提供的缩放级别的数量N,把缩放级别最低、地图比例尺最大的地图图片作为金字塔的底层,即第0层,并对其进行分块,从地图图片的左上角开始,从左至右、从上到下进行切割,分割成相同大小(比如256x256像素)的正方形地图瓦片,形成第0层瓦片矩阵;在第O层地图图片的基础上,按每2x2像素合成为一个像素的方法生成第1层地图图片,并对其进行分块,分割成与下一层相同大小的正方形地图瓦片,形成第1层瓦片矩阵;采用同样的方法生成第2层瓦片矩阵;…;如此下去,直到第N一1层,构成整个瓦片金字塔。
在Google地图中,地图数据由大量的正方形图片组成。共有2级缩放比例,每个地图图片都有坐标值,由X和Y值构成。比例因子zoom取值范围是(0-22)。操作地图滑竿显示更大比例尺地图时,图片的数量发生裂变。两种模式在请求及响应的速度方面有明显的差异,基于地图瓦片服务框架的响应速度要快于传统的WebGIS,同时对地图服务器的负载也相应小一些。
现在可以开工,首先准备好瓦片地图,如果是用来学习研究的话,我们可以通过一些第三方工具(当然自己写一个也可以)从谷歌地图抓取瓦片地图存放到本地,例如以C:\googlemas\satelite\x\y.jpg的格式存放,其中x,y,z分别代瓦片所在的列、行、缩放等级。


有了这些图我们开始拼接了,关于gdal库的介绍的文章很多了,现在我主要是介绍如何用C#来拼接谷歌地图,废话不多说了,直接上代码:

void SaveBitmapBuffered(Dataset src, Dataset dst, int x, int y)
{
if (src.RasterCount < 3) {
System.Environment.Exit(-1);
} // Get the GDAL Band objects from the Dataset
Band redBand = src.GetRasterBand(1);
Band greenBand = src.GetRasterBand(2);
Band blueBand = src.GetRasterBand(3); // Get the width and height of the raster
int width = redBand.XSize;
int height = redBand.YSize; byte[] r = new byte[width * height];
byte[] g = new byte[width * height];
byte[] b = new byte[width * height]; redBand.ReadRaster(0, 0, width, height, r, width, height, 0, 0);
greenBand.ReadRaster(0, 0, width, height, g, width, height, 0, 0);
blueBand.ReadRaster(0, 0, width, height, b, width, height, 0, 0); Band wrb = dst.GetRasterBand(1);
wrb.WriteRaster(x * width, y * height, width, height, r, width, height, 0, 0);
Band wgb = dst.GetRasterBand(2);
wgb.WriteRaster(x * width, y * height, width, height, g, width, height, 0, 0);
Band wbb = dst.GetRasterBand(3);
wbb.WriteRaster(x * width, y * height, width, height, b, width, height, 0, 0);
} /// <summary>
/// 拼接瓦片
/// </summary>
/// <param name="tilesBounds"></param>
/// <param name="tilePath"></param>
/// <param name="outPutFileName"></param>
public void CombineTiles(TilesBounds tilesBounds, string tilePath, string outPutFileName)
{
if (File.Exists(outPutFileName))
{
File.Delete(outPutFileName);
}
int imageWidth = 256 * (tilesBounds.maxCol - tilesBounds.minCol + 1);
int imageHeight = 256 * (tilesBounds.maxRow - tilesBounds.minRow + 1); //Register driver(s).
Gdal.AllRegister();
Driver driver = Gdal.GetDriverByName("GTiff");
Dataset destDataset = driver.Create(outPutFileName, imageWidth, imageHeight, 3, DataType.GDT_Byte, null); for (int col = tilesBounds.minCol; col <= tilesBounds.maxCol; col++)
{
for (int row = tilesBounds.minRow; row <= tilesBounds.maxRow; row++)
{
try
{
string sourceFileName = tilePath + tilesBounds.zoomLevel.ToString() + "\\" + col.ToString() + "\\" + row.ToString() + ".jpg";
if (File.Exists(sourceFileName))
{
Dataset sourceDataset = Gdal.Open(sourceFileName, Access.GA_ReadOnly);
if (sourceDataset != null)
{
SaveBitmapBuffered(sourceDataset, destDataset, col - tilesBounds.minCol, row - tilesBounds.minRow);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
destDataset.Dispose(); } //调用
TilesBounds tilesBounds = new TilesBounds();
tilesBounds.minCol = 107901;
tilesBounds.maxCol = 107926;
tilesBounds.minRow = 49652;
tilesBounds.maxRow = 49668;
tilesBounds.zoomLevel = 17;
string outPutFileName = "c:\\北京卫星图" + tilesBounds.zoomLevel.ToString() + ".tif";
string tilePath = "C:\\googlemaps\\\satelite\\";
CombineTiles(tilesBounds, tilePath, outPutFileName);

ok,大功告成了,看看效果图吧。

GDAL库学习笔记(1):无缝拼接Google卫星图的更多相关文章
- numpy, matplotlib库学习笔记
Numpy库学习笔记: 1.array() 创建数组或者转化数组 例如,把列表转化为数组 >>>Np.array([1,2,3,4,5]) Array([1,2,3,4,5]) ...
- muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor
目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...
- muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制
目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...
- muduo网络库学习笔记(三)TimerQueue定时器队列
目录 muduo网络库学习笔记(三)TimerQueue定时器队列 Linux中的时间函数 timerfd简单使用介绍 timerfd示例 muduo中对timerfd的封装 TimerQueue的结 ...
- C++STL标准库学习笔记(三)multiset
C++STL标准库学习笔记(三)multiset STL中的平衡二叉树数据结构 前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标 ...
- 【python】numpy库和matplotlib库学习笔记
Numpy库 numpy:科学计算包,支持N维数组运算.处理大型矩阵.成熟的广播函数库.矢量运算.线性代数.傅里叶变换.随机数生成,并可与C++/Fortran语言无缝结合.树莓派Python v3默 ...
- C++STL标准库学习笔记(一)sort
前言: 近来在学习STL标准库,做一份笔记并整理好,方便自己梳理知识.以后查找,也方便他人学习,两全其美,快哉快哉! 这里我会以中国大学慕课上北京大学郭炜老师的<程序设计与算法(一)C语言程序设 ...
- Java学习笔记(四)——google java编程风格指南(上)
[前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...
- Java学习笔记(五)——google java编程风格指南(中)
[前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...
随机推荐
- 关于C语言静态链接的个人理解,欢迎指正
摘要:本篇主要介绍在静态链接中多个文件合并.地址确定.符号解析和重定位相关问题,以GCC编译器为例. 首先,链接器链接多个文件时,采用何种方式合并为一个文件?方式一,按序叠加,即多个文件依次叠 ...
- 将窗体显示在 PageControl 上
var AWinControl:TPageControl; begin AWinControl := PageControl1; if frmAbout = nil then Exit; frmAbo ...
- UrlDownloadFile, 线程下载文件, 带进度条
unit FileDownLoadThread; interface uses Classes, SysUtils, Windows, ActiveX, UrlMon; const S_ABORT = ...
- [Ubuntu]在Ubuntu下搭建自己的源服务器
1.摘要 网上有很很多关于搭建源镜像的文章,但是对于一般人来讲,用不着镜像所有的deb包,只对我们能用到的感兴趣.另外,对于一些在Ubuntu的源中没有的软件,我们也可以放在我们自己的源里,这 ...
- mvc和三层架构到底有什么区别
原文地址:http://zhidao.baidu.com/question/82001542.html?qbl=relate_question_3&word=MVC%20%CA%FD%BE%D ...
- 《Java web 开发实战经典》读书笔记
去年年末,也就是大四上学期快要结束的时候,当时保研的事情确定了下来,终于有了一些空闲的时间可以学点实用的技术. 之前做数据库课程设计的时候,也接触过java web的知识,当时做了一个卖二手书籍的网站 ...
- java.lang.UnsatisfiedLinkError: no XXX in java.library.path
其中涉及的测试源码如下: For those who didn't install Javawith default settings, a systematic way for solving JN ...
- MyCat 主键ID自增长配置
在实现分库分表的情况下,数据库自增主键已无法保证自增主键的全局唯一.为此,MyCat 提供了全局sequence,并且提供了包含本地配置和数据库配置等多种实现方式,实现方式主要有三种:本地文件方式.数 ...
- MyCat 介绍、分片规则、调优的内容收集
一.MyCat的简介 MyCat高可用.负载均衡架构图: 详细知识点: MySQL分布式集群之MyCAT(一)简介(修正) 二.MyCat的schema.xml讲解 详细知识点:MySQL分布式集群 ...
- SDK调试出错小技巧=。=
学习Unity小伙伴完全不懂Android编程抓错误是很困难的..... 1. 使用UnityPlayer.UnitySendMessage(); 发送到Unity使用OnGUI显示错误 2. 直接在 ...