编程实现遥感图像彩色合成

  • 格式:doc
  • 大小:1.86 MB
  • 文档页数:7

编程实现遥感图像彩色合成 一、 实验目的 了解图像彩色合成的分类以及它们的特点,掌握真彩色、假彩色和伪彩色合成的基本原理和具体操作。

二、 实验要求

实现对单波段图像进行伪彩色合成,对多波段图像进行真彩色和伪彩色和合成。 三、 实验原理

1. 伪彩色合成:把单波段灰度图像中的不同灰度级按特定的函数关系变换成彩色,然后进行彩色图像显示的方法,可通过密度分割法实现; 2. 假彩色合成:选择多波段图像中的任意三个波段,分别赋予红、绿、蓝三种原色,在屏幕上合成彩色图像的方法,其中标准假彩色选择的三个波段是近红外、绿、蓝波段; 3. 真彩色合成:彩色合成中选择的波段的波长与红绿蓝的波长相同或近似,得到的图像的颜色与真彩色近似。

四、 实验思路

五、 实验步骤 根据图像数据组织格式读取其数据

将图像原始数据通过拉伸方式映射成对应的DN值

将指定波段或单波段的不同区域值赋给图像格式R、G、B三原色,合成图像显示

获取图像文件信息 (读取头文件) 1.新建项目文件:本实验选用的语言是C#,开发工具是VisualStudio2010,通

过“文件—新建—项目—C#—Windows窗体应用程序”,命名“彩色合成”即可; 2.编写代码:代码的功能模块,方法可根据实验方法的流程组织,具体如下:

(1).编写读取头文件代码:直接导入已有的“.cs”类文件即可;

(2).编写读取图像数据代码:直接载入前面实验已有的“.cs”类文件即

可; (3).编写灰度拉伸代码:灰度拉伸有很多中这里采用最简单的线性拉伸方式,公式为G=Gmin+(Gmax-Gmin)*(F-Fmin)/(Fmax-Fmin) F、G分别表示原始图像数据和原始图像数据,由于在“绘制直方图”实验中已有该代码,直接载入即可; (4).绘制图像代码:这里我采取的是BMP图像格式来显示图像文件可直接调用C#里的相关方法将字节数据显示为图像,具体代码见后文;

3.调试编译:通过VS2010断点等调试工具,可查看、排除程序错误,无语法、

逻辑错误后,编译生成程序文件即可; 4.运行程序查看结果:运行程序,加载实验数据,进行彩色合成,然后再通

过ENVI 的RGB显示方式,显示图像,对比看是否准确;

六、 结果与分析

1.结果 (1)、真彩色合成

灰度图像 彩色合成图像

与上图对比 (2).假彩色合成 4R、3G、2B假彩色合成 2.总结分析 (1).真彩色合成图像,颜色接近自然色,容易识别地物; (2).标准假彩色合成可以凸显植被(红色)、水体(黑色或蓝色)、城镇(深色)等信息。

七、 源代码

1.获取灰度图像 /// /// 使用byte[]数据,生成256色灰度 BMP 位图 /// /// /// /// /// public static Bitmap CreateBitmap(byte[] originalImageData, int originalWidth, int originalHeight) { //指定8位格式,即256色 Bitmap resultBitmap = new Bitmap(originalWidth, originalHeight, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);

//将该位图存入内存中 MemoryStream curImageStream = new MemoryStream(); resultBitmap.Save(curImageStream, System.Drawing.Imaging.ImageFormat.Bmp); curImageStream.Flush();

//由于位图数据需要DWORD对齐(4byte倍数),计算需要补位的个数 int curPadNum = ((originalWidth * 8 + 31) / 32 * 4) - originalWidth;

//最终生成的位图数据大小 int bitmapDataSize = ((originalWidth * 8 + 31) / 32 * 4) * originalHeight;

//数据部分相对文件开始偏移,具体可以参考位图文件格式 int dataOffset = ReadData(curImageStream, 10, 4);

//改变调色板,因为默认的调色板是32位彩色的,需要修改为256色的调色板 int paletteStart = 54; int paletteEnd = dataOffset; int color = 0;

for (int i = paletteStart; i < paletteEnd; i += 4) { byte[] tempColor = new byte[4]; tempColor[0] = (byte)color; tempColor[1] = (byte)color; tempColor[2] = (byte)color; tempColor[3] = (byte)0; color++;

curImageStream.Position = i; curImageStream.Write(tempColor, 0, 4); }

//最终生成的位图数据,以及大小,高度没有变,宽度需要调整 byte[] destImageData = new byte[bitmapDataSize]; int destWidth = originalWidth + curPadNum;

//生成最终的位图数据,注意的是,位图数据 从左到右,从下到上,所以需要颠倒 for (int originalRowIndex = originalHeight - 1; originalRowIndex >= 0; originalRowIndex--) { int destRowIndex = originalHeight - originalRowIndex - 1;

for (int dataIndex = 0; dataIndex < originalWidth; dataIndex++) { //同时还要注意,新的位图数据的宽度已经变化destWidth,否则会产生错位 destImageData[destRowIndex * destWidth + dataIndex] = originalImageData[originalRowIndex * originalWidth + dataIndex]; } }

//将流的Position移到数据段 curImageStream.Position = dataOffset;

//将新位图数据写入内存中 curImageStream.Write(destImageData, 0, bitmapDataSize);

curImageStream.Flush();

//将内存中的位图写入Bitmap对象 resultBitmap = new Bitmap(curImageStream);

return resultBitmap; }

/// /// 从内存流中指定位置,读取数据 /// /// /// /// /// public static int ReadData(MemoryStream curStream, int startPosition, int length) { int result = -1; byte[] tempData = new byte[length]; curStream.Position = startPosition; curStream.Read(tempData, 0, length); result = BitConverter.ToInt32(tempData, 0); return result; }

/// /// 向内存流中指定位置,写入数据 /// /// /// /// /// public static void WriteData(MemoryStream curStream, int startPosition, int length, int value) { curStream.Position = startPosition; curStream.Write(BitConverter.GetBytes(value), 0, length); } 2.获取彩色合成图像 /// /// 从rgb字节数组中获取图像 /// /// 图像宽 /// 图像高 /// rgb字节数组 /// 得到的图像 public static Bitmap GetDataPicture(int w, int h, byte[] data) {