使用C#版本GDAL读取复数图像
GDAL的C#版本虽然在很多算法接口没有导出,但是在读写数据中的接口基本上都是完全导出了。使用ReadRaster和WriteRaster方法来进行读写,同时对这两个方法进行了重载,对于常用的数据类型可以不用指定数据类型直接进行读取即可。但是对于复数类型就有点复杂了。下面就针对GDAL如何来读取复数数据来进行一个简单的说明。
我们知道,在使用GDAL读取数据的时候使用的是ReadRaster这个函数,这个函数重载了6个,函数声明分别如下,以Dataset的ReadRaster为例,Band类中的ReadRaster与之类似。
OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Byte[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Int16[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Single[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Double[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.IntPtr, System.Int32, System.Int32, OSGeo.GDAL.DataType, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
前五个函数的声明基本上完全一致,除了第五个参数,分别是Byte[],Int16[],Int32[],Single[],Double[]。分别对应的是将图像中的像素值使用8U,16U\16S,32U\32S,32F和64F。如果图像数据是普通的数据(这里指的是除复数图像之外),那么这五个函数完全可以满足所有的需求。但是如果图像是复数图像(复数图像就是图像的像素值是由复数组成的,比如通过傅立叶变换后的图像),这时,上面的五个函数就有点爱莫能助了,就需要上面的第六个函数来出场救急了 www.lefeng123.com
第六个函数的声明和C\C++的声明完全一致,使用C\C++的同学对这个接口应该比较熟悉。这个函数可以替代上面五个函数来使用,但是比较麻烦的时,就是传入的参数会比较多,首先看一个例子。使用普通的方式来读取一个单波段8U的数据(Landsat5的一个数据)。从数据中读取100×100大小的数据,直接使用ReadRaster的Byte接口。
static void ReadRaster()
{
string strFile = @"D:\Data\landsat\etp139r26_5t19900902\p139r26_5t19900902_nn1.tif";
OSGeo.GDAL.Gdal.AllRegister();
OSGeo.GDAL.Dataset ds = OSGeo.GDAL.Gdal.Open(strFile, OSGeo.GDAL.Access.GA_ReadOnly);
int []bandmap = new int [1];
bandmap[0] = 1;
//读取Byte类型
Byte[] data = new Byte[100 * 100];
OSGeo.GDAL.CPLErr err = ds.ReadRaster(3000, 2000, 100, 100, data, 100, 100, 1, bandmap, 0, 0, 0);
//将读取的数据输出
for (int i = 0; i < 100; i++ )
{
for (int j = 0; j < 100; j++)
{
Console.WriteLine("{0}", ddata[i*100+j]);
}
}
Console.WriteLine("done\n");
}
下面看看如何使用第六个接口来完成上面的功能,代码如下:
static void ReadRaster()
{
string strFile = @"D:\Data\landsat\etp139r26_5t19900902\p139r26_5t19900902_nn1.tif";
OSGeo.GDAL.Gdal.AllRegister();
OSGeo.GDAL.Dataset ds = OSGeo.GDAL.Gdal.Open(strFile, OSGeo.GDAL.Access.GA_ReadOnly);
int []bandmap = new int [1];
bandmap[0] = 1;
//读取Byte类型
Byte[] data = new Byte[100 * 100];
//构造一个IntPtr,大小为100×100个Byte
IntPtr ptr = Marshal.AllocCoTaskMem(data.Length);
//需要指明读取的数据类型
OSGeo.GDAL.CPLErr err = ds.ReadRaster(3000, 2000, 100, 100, ptr, 100, 100, OSGeo.GDAL.DataType.GDT_Byte, 1, bandmap, 0, 0, 0);
//将读取到的数据拷贝到data中
Marshal.Copy(ptr, data, 0, data.Length);
//将读取的数据输出
for (int i = 0; i < 100; i++ )
{
for (int j = 0; j < 100; j++)
{
Console.WriteLine("{0}", ddata[i*100+j]);
}
}
Console.WriteLine("done\n");
}
从上面的代码中可以看出,使用第六个函数的时候,需要一个IntPtr的类型,使用Marshal类中的AllocCoTaskMem函数来进行分配内存空间(不知道C#中的说法是啥,按照C\C++中应该就是分配空间)。需要注意的是,分配的大小是按照字节(Byte)为单位的。接下来在调用ReadRaster时需要指定数据类型,调用之后,像素值应该都存储在这个IntPtr中了,然后再使用Marshal类中的Copy函数将IntPtr中的数据拷贝到Byte数组data中即可 www.tfjy386.com
通过上面的代码,我们大致知道第六个ReadRaster的大致用法,接下来我们通过这个方法来读取一个复数类型的图像。没有复数类型的图像,可以使用ENVI随便打开一个图像,然后在Transform菜单下有个FFT,将打开的数据进行傅立叶变换,输出的结果就是一个复数图像。这里我将上面使用的Landsat的数据使用FFT转了下。使用下面的代码进行打开。
static void ReadRaster()
{
string strFile = @"D:\Data\landsat\etp139r26_5t19900902\p139r26_5t19900902_nn1_fft.tif";
OSGeo.GDAL.Gdal.AllRegister();
OSGeo.GDAL.Dataset ds = OSGeo.GDAL.Gdal.Open(strFile, OSGeo.GDAL.Access.GA_ReadOnly);
int []bandmap = new int [1];
bandmap[0] = 1;
//读取复数类型,由于一个复数由两个数据组成,所以读取100×100的像元需要2倍普通图像的大小
double[] data = new double[100 * 100 * 2];
//构造一个IntPtr,大小为100×100×2个double,一个double为4个byte,所以下面的长度要乘以8
IntPtr ptr = Marshal.AllocCoTaskMem(data.Length*8);
//需要指明读取的数据类型
OSGeo.GDAL.CPLErr err = ds.ReadRaster(0, 0, 100, 100, ptr, 100, 100, OSGeo.GDAL.DataType.GDT_CFloat64, 1, bandmap, 0, 0, 0);
//将读取到的数据拷贝到data中
Marshal.Copy(ptr, data, 0, data.Length*8);
//将读取的数据输出
int in1 = 0;
for (int i = 0; i < 100; i++ )
{
for (int j = 0; j < 100; j++)
{
Console.WriteLine("({0}*i+{1})", ddata[in1++], ddata[in1++]);
}
}
Console.WriteLine("done\n");
}
在上面的代码中,一个复数由实部和虚部组成,所以一个像素值就对应于普通图像的2个像素值,故读取100×100大小的数据就需要分配普通图像2倍的大小。除此之外与读取普通图像一样,不过在最后获取像素值的时候,复数图像的像素值是顺序存储的,即实部,虚部,实部,虚部...这样的顺序来进行存储。
使用C#版本GDAL读取复数图像的更多相关文章
- OpenCV imread读取jpg图像的一个大坑
长话短说 版本区间[OpenCV3.0.0, OpenCV3.4.1]内的OpenCV,(至少在windows下,使用官方提供的预编译版本),imread读取jpg图片后的像素值,和版本区间[Open ...
- GDAL关于读写图像的简明总结
读写影像可以说是图像处理最基础的一步.关于使用GDAL读写影像,平时也在网上查了很多资料,就想结合自己的使用心得,做做简单的总结. 在这里写一个例子:裁剪lena图像的某部分内容,将其放入到新创建的. ...
- GDAL读取的坐标起点在像素左上角还是像素中心?
目录 1. 问题 2. 结论 3. 例外 1. 问题 笔者在处理地理栅格数据的时候,总是会发生偏差半个像素的问题. 比如说通过ArcMap打开一张.tif,查看其地理信息:同时用记事本打开.tfw,比 ...
- GDAL读取Shp问题解决:Unable to open EPSG support file gcs.csv
在GIS软件的开发中,经常用到开源库GDAL读取Shp数据,当shp数据中包含投影信息时,可能会遇到“Unable to open EPSG support file gcs.csv”错误提示,该错误 ...
- ArcGIS二次开发之读取遥感图像像素值的做法
作者:朱金灿 来源:http://blog.csdn.net/clever101 首先是读取遥感图像的R.G.B波段数据的做法.读取R.G.B波段数据的像素值主要通过IRaster接口的Read方法在 ...
- VTK读取序列化图像
vtk获取内存中图像数据 原文链接:http://blog.csdn.net/zmy3376365/article/details/7717721 内存中有段图片数据 ,使用VTK来读入,然后就可以 ...
- Halcon一日一练:读取文件目录图像的三种方法
第一种方法: 读了一个单一图像: read_image(Image,'fabrik') 这种方式可以快速的读取软件自身携带的库图像文件,系统设定了库图像映像文件的快速读取方式,我们也可以通过绝对地址的 ...
- 从二进制数据流中构造GDAL可以读取的图像数据
在很多时候,我们的图像数据往往都不是文件方式存储在磁盘上,而是可能从网络或者数据库中获取的是二进制的图像数据流.最简单的方式和最容易想到的方式就是将这个文件流保存到磁盘上形成一个文件,然后再使用GDA ...
- 从二进制数据流中构造GDAL可以读取的图像数据(C#)
在上一篇博客中,讲了一下使用GDAL从文件流中构造一个GDAL可以识别的数据来进行处理.原以为这个接口在C#中没有,仔细看了下GDAL库中源码,发现C#版本也有类似的函数,下面是GDAL库中的一个C# ...
随机推荐
- 14.4.2 Change Buffer 延迟写
14.4.2 Change Buffer change buffer 是一个特殊的数据结构 用于cahce 改变的secondary index pages 当被影响的pages 不在buffer p ...
- Ubuntu 14.04 升级后 VPN 无法连接的问题
如果不知道怎么配置 VPN Server(IPSEC + L2TP),可以看这篇文章(英文). 问题表现: 将 Ubuntu 12.04 通过自动更新 —— do-release-upgrade —— ...
- -_-#【Better JS Code】插入迭代值
+function() { var i = 0 var values = ['xiaoming', 'xiaohong'] var name = values[i] i++ console.log(n ...
- 深入JS系列学习3
深入JS系列学习3 深入理解JavaScript系列(9):根本没有"JSON对象"这回事! 很多JavaScript开发人员都错误地把JavaScript对象字面量(Object ...
- DataTable排序(来自其他空间)
DataTable排序 DataRow[] rows = dataTable1.Select("", "ord asc"); DataTable t = Dat ...
- C - Building a Space Station - poj 2031
空间站是有一些球状的房间组成的,现在有一些房间但是没有相互连接,你需要设计一些走廊使他们都相通,当然,有些房间可能会有重合(很神奇的样子,重合距离是0),你需要设计出来最短的走廊使所有的点都连接. 分 ...
- java中的泛型类及其使用
泛型的使用 集合的使用 一般集合的使用方式是: 比如有一个Person类 package com.atguigu.java; public class Person { // @Override // ...
- [Redux] Introduction
Single immutable state tree: Should be just one single javascript object. Describing the changes by ...
- [Falcor] Intro to JSON Graph
JSON is a very commonly used data interchange format. Unfortunately while most application domain mo ...
- Android实现计时与倒计时(限时抢购)的几种方法
在购物网站的促销活动中一般都有倒计时限制购物时间或者折扣的时间,这些都是如何实现的呢? 在一个安卓客户端项目中恰好遇到了类似的问题,一开始使用的是Timer与 TimerTask, 虽然此方法通用,但 ...