1. 功能简介
栅格数据前置过滤是在渲染之前对内存中的数据根据特定的规则进行处理,然后再进行数据渲染。本示例以定标为例进行示例代码编写。
定标(校准)是将遥感器所得的测量值变换为绝对亮度或变换为与地表反射率、表面温度等物理量有关的相对值的处理过程。或者说,遥感器定标就是建立遥感器每个探测器输出值与该探测器对应的实际地物辐射亮度之间的定量关系。它是遥感定量化的前提。
栅格后置过滤是对渲染过程的控制。本示例以曲线调整为例进行示例代码编写
灰度拉伸又叫对比度拉伸,它是最基本的一种灰度变换,使用的是最简单的分段线性变换函数,它的主要思想是提高图像处理时灰度级的动态范围。
[灰度拉伸函数]
2. 功能实现说明
2.1 实现思路及原理说明
本示例代码以FY-4A数据的定标为例,已经运用静止卫星数据读取方法,读取NOMChannel13波段数据为tiff。
前置过滤(以定标为例)
|
第一步
|
初始化前置过滤回调函数。
|
第二步
|
实现定标算法。
|
第三步
|
实例化自定义前置过滤对象。
|
第四步
|
为前置过滤对象设置前置过滤算法
|
第五步
|
接口转换
|
第六步
|
添加前置过滤器
|
后置过滤(以曲线拉伸为例)
|
第一步
|
初始化拉伸结果表。
|
第二步
|
添加折点。
|
第三步
|
根据折点,计算结果拉伸表。
|
第四步
|
实例化后置过滤器
|
第五步
|
设置对照表
|
第六步
|
接口转换,添加后置过滤条件
|
2.2 核心接口与方法
接口/类
|
方法
|
说明
|
前置过滤
|
Carto.PreFilterFunCallback
|
|
|
Carto.ICustomerPreRasterFilter
|
SetPreFilterFun
|
设置前置过滤算法
|
Carto.IrasterFilterProps
|
AddPreRasterFilter
|
添加前置过滤
|
后置过滤
|
Carto. ILutAfterFilter
|
SetLut
|
为指定波段设置对照表
|
Carto. IRasterFilterProps
|
AddAfterRasterFilter
|
添加后置过滤器
|
2.3 示例代码
项目路径
|
百度云盘地址下/PIE示例程序/07图层渲染/12.栅格过滤制
|
数据路径
|
百度云盘地址下/PIE示例数据/栅格数据/ FY/FY4A/
|
视频路径
|
百度云盘地址下/PIE视频教程/07图层渲染/12.栅格过滤控制.avi
|
示例代码
|
方法(一)
//前置过滤本示例以定标为例
//风云4A数据为例
IRasterLayer rasterLayer = mapControlMain.ActiveView.CurrentLayer as IRasterLayer;
IRasterRender rasterRender = RenderFactory.ImportFromFile(@"C:\Users\zhangyiwei\Desktop\TestData\ICV-BD.xml");
//实例化定标函数
CaliCommon common = new CaliCommon();
string hdfpath = (rasterLayer as ILayer).DataSourcePath;
common.Initialize(hdfpath, "NOMChannel13");
//添加前置过滤
PIE.Carto.ICustomerPreRasterFilter preFilter = new PIE.Carto.CustomerPreRasterFilter();
preFilter.SetPreFilterFun(common.CaliFunCallBack);
IRasterClassifyColorRampRender classRender = rasterRender as IRasterClassifyColorRampRender;
(classRender as IRasterFilterProps).AddPreRasterFilter(preFilter as IPreRasterFilter);
//地图刷新
rasterLayer.Render = rasterRender;
mapControlMain.ActiveView.PartialRefresh(ViewDrawPhaseType.ViewAll);
方法(二)
/// <summary>
/// 定标方法接口
/// </summary>
public interface ICaliFunction
{
/// <summary>
/// 定标回调函数
/// </summary>
PreFilterFunCallback CaliFunCallBack
{
get;
}
/// <summary>
/// 数据定标
/// </summary>
/// <param name="dataNeedCali">原始数据</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <param name="bandCount">波段</param>
/// <returns>定标后数据</returns>
float[] Cali<T>(T[] dataNeedCali, int width, int height, int bandCount);
/// <summary>
/// 定标算法函数
/// </summary>
unsafe bool CaliFilter(IntPtr valuesA, IntPtr valuesB);
}
/// <summary>
/// 风云4A数据的定标方法
/// </summary>
public class CaliCommon : ICaliFunction
{
/// <summary>
/// 定标数据
/// </summary>
private float[] m_DBDatas = null;
/// <summary>
/// 定标数据长度
/// </summary>
private int m_Count = ;
/// <summary>
/// 定标回调函数
/// </summary>
private PreFilterFunCallback m_CaliFunCallBack = null;
/// <summary>
/// 构造函数
/// </summary>
public CaliCommon()
{
}
/// <summary>
/// 定标回调函数
/// </summary>
public PreFilterFunCallback CaliFunCallBack
{
get
{
return m_CaliFunCallBack;
}
}
/// <summary>
/// 初始化定标方法
/// </summary>
/// <param name="strFilePath_HDF">hdf文件路径</param>
/// <param name="chanelName">通道名称</param>
/// <returns></returns>
public bool Initialize(string strFilePath_HDF, string chanelName)
{
string calName = chanelName.Replace("NOM", "CAL");
string calFilePath = System.IO.Path.GetDirectoryName(strFilePath_HDF) + "\\" + calName+".tiff";
IRasterDataset rasterDataset = PIE.DataSource.DatasetFactory.OpenRasterDataset(calFilePath, OpenMode.ReadOnly);
int height = rasterDataset.GetRasterYSize();
m_DBDatas = new float[height];
int[] bandMap = { };
rasterDataset.Read(, , , height, m_DBDatas, , height, PixelDataType.Float32, , bandMap);
(rasterDataset as IDisposable).Dispose();
m_Count = m_DBDatas.Length;
m_CaliFunCallBack = new PreFilterFunCallback(CaliFilter);
GC.KeepAlive(m_CaliFunCallBack);
return true;
}
/// <summary>
/// 数据定标
/// </summary>
/// <param name="dataNeedCali">原始数据</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <param name="bandCount">波段</param>
/// <returns>定标后数据</returns>
public float[] Cali<T>(T[] dataNeedCali, int width, int height, int bandCount)
{
if (dataNeedCali == null || dataNeedCali.Length < )
{
return null;
}
float[] dataCali = new float[width * height * bandCount];
for (int j = ; j < height; j++)
{
for (int i = ; i < width; i++)
{
for (int m = ; m < bandCount; m++)
{
int nIndex = (j * width + i) * bandCount + m;
int value = Convert.ToInt32(dataNeedCali[nIndex]);
if (value < || value >= m_Count)
{
dataCali[nIndex] = ;
}
else
{
dataCali[nIndex] = m_DBDatas[value];
}
}
}
}
return dataCali;
}
/// <summary>
/// 定标算法
/// </summary>
/// <param name="valuesA">定标前</param>
/// <param name="valuesB">定标后</param>
/// <returns></returns>
public unsafe bool CaliFilter(IntPtr valuesA, IntPtr valuesB)
{
if (m_DBDatas == null)
{
return false;
}
IPixelBuffer pixelBuffer = PIE.DataSource.DatasetFactory.ConstructCLRPixelBuffer(valuesA.ToPointer());
int width = pixelBuffer.Width;
int height = pixelBuffer.Height;
int bandCount = pixelBuffer.BandMap.Length;
float[] valuesData = new float[width * height * bandCount];
short* byteValues = (short*)(pixelBuffer.GetData_Ref().ToPointer());
for (int j = ; j < height; j++)
{
for (int i = ; i < width; i++)
{
for (int m = ; m < bandCount; m++)
{
int nIndex = (j * width + i) * bandCount + m;
int value = *(byteValues + nIndex);
if (value < || value >= m_Count)
{
valuesData[nIndex] = ;
}
else
{
valuesData[nIndex] = m_DBDatas[value];
}
}
}
}
pixelBuffer.SetData(PixelDataType.Float32, valuesData);
return true;
}
}
|
2.4 示例截图
(一) 前置过滤
(二) 后置过滤