基于GDAL的遥感影像显示(C#版)

21 篇文章 0 订阅
3 篇文章 0 订阅

      

        说明:本文章转载自:http://blog.csdn.net/rsyaoxin/article/details/9220735


        接触GDAL有四五年多时间了,平时都是在C++下使用,最近需要在C#下调用GDAL,所以就开始学习了下,相比C++调用,C#下使用GDAL做图像处理的效率有点低,但是其简单易学,适合菜鸟上手,现把自己刚学到的心得跟大伙分享下,以遥感影像的显示为例。

1、  程序环境搭建

         首先,需要编译GDAL库的源代码。

       GDAL是一个非常强悍的遥感数据格式解析库,支持多种遥感数据格式的读写,而且还有一些算法实现。然而,它只是一个开源库,并不是一个单独的软件,而是C++写的源代码,需要编译成动态链接库后才能为我们程序调用,如果需要在C#/.Net环境下调用,还需特别编译C#版的DLL。关于编译的方法网上很多教程,我就不介绍了,具体编译步骤可以参照民录大哥的博客:http://blog.csdn.net/liminlu0314/article/details/6937194

      如果很难编译成功,需要编译后的版本,可以留下邮箱,或者给我发邮件RSyaoxin@163.com。

      编译完成后,我们会得到9个DLL文件(以GDAL1.10版为例):gdal110.dll、gdal_csharp.dll、gdal_wrap.dll、gdalconst_csharp.dll、gdalconst_wrap.dll、ogr_csharp.dll、ogr_wrap.dll、osr_csharp.dll、osr_wrap.dll。

注意:需要强调的一点是,如果编译GDAL时添加了额外的依赖库,需要将其动态链接库一并拷贝过来。比如,我编译GDAL库时就添加了HDF4、HDF5、JPEG2000、NetCDF、Proj4等文件格式支持,那么调用的时候就需要将hd425m.dll等拷贝到同上面几个DLL一起。

          其次,C#下的环境配置。

        我们首先建立一个Windows窗体应用程序,将上面得到的9个DLL文件拷贝到项目所在的文件夹,然后在解决方案面板下找到引用项,右键添加引用,选择gdal_csharp.dll将它添加进来,这样就可以在C#调用GDAL函数了。

         再次,初始化GDAL环境。具体做法是:

        using  OSGeo.GDAL;

        将上面这一句添加到namespace这一行前面。

        然后在构造函数或者Form_Load函数中添加下面两行:

        OSGeo.GDAL.Gdal.AllRegister();

        OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","YES");

        说明:第一行是注册所有的格式驱动,第二行是支持中文路径和名称,由于GDAL默认不支持中文路径,所以在编译的时候会修改源码让它支持中文路径,C++代码就可以直接支持了,但是会发现C#版还是会不支持,所以需要加上第二句。

       这样开发环境就搭建好了,可以直接调用GDAL函数进行图像处理了。

2、  关键代码

         C#下图像的显示方法有多种,最简单的方法就是构建位图。我们可以把GDAL下的Dataset转换为Bitmap供C#调用。在C#里面调用GDAL读取栅格数据的主要函数是ReadRaster,它相当于C++下的RasterIO函数,其有多重形式:

public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, byte[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr WriteRaster(int xOff, int yOff, int xSize, int ySize, byte[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, short[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr WriteRaster(int xOff, int yOff, int xSize, int ySize, short[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, int[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr WriteRaster(int xOff, int yOff, int xSize, int ySize, int[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, float[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr WriteRaster(int xOff, int yOff, int xSize, int ySize, float[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, double[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr WriteRaster(int xOff, int yOff, int xSize, int ySize, double[] buffer, 
    int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace)
public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, IntPtr buffer, i
    nt buf_xSize, int buf_ySize, DataType buf_type, int pixelSpace, int lineSpace)
public CPLErr WriteRaster(int xOff, int yOff, int xSize, int ySize, IntPtr buffer, 
    int buf_xSize, int buf_ySize, DataType buf_type, int pixelSpace, int lineSpace)
        这里面,xOff和yOff是指偏移量,即从影像的左上角起始坐标(xOff,yOff)开始读取数据。xSize和ySize是指读取图像数据的行列数,即宽度和高度,单位都是像素。Buffer是图像数据缓存。buf_xSize和buf_ySize是缓存区的大小,它们须与buffer申请的大小保持一致,通过这两个参数可以控制缩放,如果它们小于xSize和ySize就是将原图缩小,反之如果它们大于xSize和ySize就是将原图放大。pixelSpace和lineSpace一般默认取0即可。

       关键代码如下:

       

[csharp]  view plain copy
  1. /// <summary>  
  2.        /// GDAL栅格转换为位图  
  3.        /// </summary>  
  4.        /// <param name="ds">GDAL Dataset</param>  
  5.        /// <param name="showRect">显示区域</param>  
  6.        /// <param name="bandlist">需要显示的波段列表</param>  
  7.        /// <returns>返回Bitmap对象</returns>  
  8.        public Bitmap GetImage(OSGeo.GDAL.Dataset ds, Rectangle showRect, int[] bandlist)  
  9.        {  
  10.            int imgWidth = ds.RasterXSize;   //影像宽  
  11.            int imgHeight = ds.RasterYSize;  //影像高  
  12.   
  13.            float ImgRatio = imgWidth / (float)imgHeight;  //影像宽高比  
  14.   
  15.            //获取显示控件大小  
  16.            int BoxWidth = showRect.Width;  
  17.            int BoxHeight = showRect.Height;  
  18.   
  19.            float BoxRatio = imgWidth / (float)imgHeight;  //显示控件宽高比  
  20.              
  21.            //计算实际显示区域大小,防止影像畸变显示  
  22.            int BufferWidth, BufferHeight;     
  23.            if (BoxRatio >= ImgRatio)  
  24.            {  
  25.                BufferHeight = BoxHeight;  
  26.                BufferWidth = (int)(BoxHeight * ImgRatio);  
  27.            }  
  28.            else  
  29.            {  
  30.                BufferWidth = BoxWidth;  
  31.                BufferHeight = (int)(BoxWidth/ImgRatio);  
  32.            }  
  33.   
  34.            //构建位图  
  35.            Bitmap bitmap = new Bitmap(BufferWidth, BufferHeight,  
  36.                                     System.Drawing.Imaging.PixelFormat.Format24bppRgb);  
  37.              
  38.            if (bandlist.Length==3)     //RGB显示  
  39.            {  
  40.                int[] r = new int[BufferWidth * BufferHeight];  
  41.                Band band1 = ds.GetRasterBand(bandlist[0]);  
  42.                band1.ReadRaster(0, 0, imgWidth, imgHeight, r, BufferWidth ,BufferHeight, 0, 0);  //读取图像到内存  
  43.   
  44.                //为了显示好看,进行最大最小值拉伸显示  
  45.                double[] maxandmin1 = { 0, 0 };  
  46.                band1.ComputeRasterMinMax(maxandmin1,0);  
  47.   
  48.                int[] g = new int[BufferWidth * BufferHeight];  
  49.                Band band2 = ds.GetRasterBand(bandlist[1]);  
  50.                band2.ReadRaster(0, 0, imgWidth, imgHeight, g, BufferWidth, BufferHeight, 0, 0);  
  51.   
  52.                double[] maxandmin2 = { 0, 0 };  
  53.                band2.ComputeRasterMinMax(maxandmin2, 0);  
  54.                  
  55.                int[] b = new int[BufferWidth * BufferHeight];  
  56.                Band band3 = ds.GetRasterBand(bandlist[2]);  
  57.                band3.ReadRaster(0, 0, imgWidth, imgHeight, b, BufferWidth, BufferHeight, 0, 0);  
  58.   
  59.                double[] maxandmin3 = { 0, 0 };  
  60.                band3.ComputeRasterMinMax(maxandmin3, 0);  
  61.   
  62.                int i, j;  
  63.                for (i = 0; i < BufferWidth; i++)  
  64.                {  
  65.                    for (j = 0; j < BufferHeight; j++)  
  66.                    {  
  67.                        int rVal=Convert.ToInt32(r[i + j * BufferWidth]);  
  68.                        rVal = (int)((rVal - maxandmin1[0]) / (maxandmin1[1] - maxandmin1[0]) * 255);  
  69.   
  70.                        int gVal=Convert.ToInt32(g[i + j * BufferWidth]);  
  71.                        gVal = (int)((gVal - maxandmin2[0]) / (maxandmin2[1] - maxandmin2[0]) * 255);  
  72.   
  73.                        int bVal=Convert.ToInt32(b[i + j * BufferWidth]);  
  74.                        bVal = (int)((bVal - maxandmin3[0]) / (maxandmin3[1] - maxandmin3[0]) * 255);  
  75.   
  76.                        Color newColor = Color.FromArgb(rVal, gVal, bVal);  
  77.                        bitmap.SetPixel(i, j, newColor);  
  78.                    }  
  79.                }  
  80.            }   
  81.            else               //灰度显示  
  82.            {  
  83.                int[] r = new int[BufferWidth * BufferHeight];  
  84.                Band band1 = ds.GetRasterBand(bandlist[0]);  
  85.                band1.ReadRaster(0, 0, imgWidth, imgHeight, r, BufferWidth, BufferHeight, 0, 0);  
  86.   
  87.                double[] maxandmin1 = { 0, 0 };  
  88.                band1.ComputeRasterMinMax(maxandmin1, 0);  
  89.                  
  90.                int i, j;  
  91.                for (i = 0; i < BufferWidth; i++)  
  92.                {  
  93.                    for (j = 0; j < BufferHeight; j++)  
  94.                    {  
  95.                        int rVal = Convert.ToInt32(r[i + j * BufferWidth]);  
  96.                        rVal = (int)((rVal - maxandmin1[0]) / (maxandmin1[1] - maxandmin1[0]) * 255);  
  97.   
  98.                        Color newColor = Color.FromArgb(rVal, rVal, rVal);  
  99.                        bitmap.SetPixel(i, j, newColor);  
  100.                    }  
  101.                }  
  102.            }  
  103.   
  104.            return bitmap;  
  105.        }  

 

3、  主函数调用

  得到Bitmap,我们就可以在程序中调用它了。我们可以在窗体上加一个PictureBox控件来显示图像,其name设为pictureBox1。主要调用代码如下:

[csharp]  view plain copy
  1. private void ImageShow()  
  2.     {  
  3.         string filename="";  
  4.             OpenFileDialog dlg = new OpenFileDialog();  
  5.             dlg.Filter = "Tiff文件|*.tif|Erdas img文件|*.img|Bmp文件|*.bmp|jpeg文件|*.jpg|所有文件|*.*";  
  6.             if (dlg.ShowDialog() == DialogResult.OK)  
  7.             {  
  8.                 filename = dlg.FileName;  
  9.             }  
  10.   
  11.             if (filename == "")  
  12.             {  
  13.                 MessageBox.Show("影像路径不能为空");  
  14.                 return;  
  15.             }  
  16.         OSGeo.GDAL.Dataset ds= Gdal.Open(filename, Access.GA_ReadOnly);  
  17.         if(ds==null)  
  18.         {  
  19.         MessageBox.Show("影像打开失败");  
  20.         return;  
  21.         }  
  22.         Rectangle pictureRect = new Rectangle();  
  23.             pictureRect.X = 0;  
  24.             pictureRect.Y = 0;  
  25.             pictureRect.Width = this.pictureBox1.Width;  
  26.             pictureRect.Height = this.pictureBox1.Height;  
  27.               
  28.         int[] disband = {3,2,1};  
  29.               
  30.         Bitmap bitmap = GetImage(ds, pictureRect, disband);   //遥感影像构建位图  
  31.             pictureBox1.Image = bitmap;                   //将位图传递给PictureBox控件进行显示  
  32.               
  33.     }  




4、  结果展示

    这样我们就可以很容易地显示遥感影像了。



  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
要在Python中使用GDAL库进行遥感影像配准,您可以使用以下代码示例: ```python from osgeo import gdal def image_registration(input_image_path, reference_image_path, output_image_path): # 打开需要配准的影像 src_ds = gdal.Open(input_image_path) # 打开参考影像 ref_ds = gdal.Open(reference_image_path) # 获取需要配准影像的地理转换信息 src_geo_transform = src_ds.GetGeoTransform() # 获取参考影像的地理转换信息 ref_geo_transform = ref_ds.GetGeoTransform() # 创建一个空的输出影像,用于存储配准结果 out_ds = gdal.GetDriverByName('GTiff').Create(output_image_path, src_ds.RasterXSize, src_ds.RasterYSize, src_ds.RasterCount, src_ds.GetRasterBand(1).DataType) # 设置输出影像的地理转换信息为参考影像的地理转换信息 out_ds.SetGeoTransform(ref_geo_transform) # 设置输出影像的投影信息为参考影像的投影信息 out_ds.SetProjection(ref_ds.GetProjection()) # 进行影像配准 gdal.ReprojectImage(src_ds, out_ds, src_ds.GetProjection(), ref_ds.GetProjection(), gdal.GRA_NearestNeighbour) # 关闭数据集 src_ds = None ref_ds = None out_ds = None # 调用函数进行影像配准 input_image_path = 'input_image.tif' reference_image_path = 'reference_image.tif' output_image_path = 'output_image.tif' image_registration(input_image_path, reference_image_path, output_image_path) ``` 请确保将`input_image.tif`替换为需要配准的影像路径,`reference_image.tif`替换为参考影像路径,`output_image.tif`替换为输出影像路径。 这个示例代码中的`image_registration`函数接受三个参数,分别是需要配准的影像路径、参考影像路径和输出影像路径。函数会打开需要配准的影像和参考影像,并根据参考影像的地理转换信息和投影信息创建一个空的输出影像。然后使用最近邻插方法进行影像配准,最后关闭数据集。 希望这能对您有所帮助!如果您还有其他问题,请随时提问。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值