/// <summary> /// 获取原始坡度线 /// </summary> /// <param name="Lev">提取级别,越高内容越丰富</param> static OSGeo.OGR.Layer getPDX(int Lev) { //创建原始坡度线 polygon shpDataSet.deleteLayerByName("slopeLine"); OSGeo.OGR.Layer slopePolyLayer = shpDataSet.CreateLayer("slopeLine", null, OSGeo.OGR.wkbGeometryType.wkbPolygon, null); //获取分块数量 int Maxcnt = GetCutNumberOfImg(""); //开始计算 StaticTools.msgLine("createSlopeLine..."); for (int i = 0; i < Lev; i++) { //坡度阈值,每次变化得到的内容有所不同,最后合在一个polygon中 ImprotLevel = 85 - i * 5; for (int ii = 0; ii < Maxcnt; ii++) { TKDataF(slopePolyLayer, ii); StaticTools.progress((ii + 1) * (i + 1) * 100 / (Lev * Maxcnt), string.Format("{0}/{1}on{2}/{3}", ii, Maxcnt, i, Lev)); } } slopeDataSet.Dispose(); //提线完成,删掉坡度图 if (IsDelete) { gdalDriver.Delete(slopePath); } return(slopePolyLayer); }
private void labDSMin_TextChanged(object sender, EventArgs e) { if (labDSMin.Text != "") { OSGeo.GDAL.Gdal.AllRegister(); OSGeo.GDAL.Dataset ds = OSGeo.GDAL.Gdal.Open(labDSMin.Text, OSGeo.GDAL.Access.GA_ReadOnly); double[] a = new double[6]; ds.GetGeoTransform(a); double xx = a[0]; double yy = a[3]; double size = a[1]; double xSixe = ds.RasterXSize; double ySixe = ds.RasterYSize; labInFileInfo.Text += labDSMin.Text + ":\r" + "\r\n" + "左上角X坐标:" + xx.ToString() + "\r" + "左上角Y坐标:" + yy.ToString() + "\r" + "像元尺寸:" + size.ToString() + "\r" + "图像大小:" + xSixe.ToString() + "*" + ySixe.ToString(); ds.Dispose(); } else { labInFileInfo.Text = ""; } }
public void Dispose() { GC.SuppressFinalize(this); if (_gDS != null) { _gDS.Dispose(); _gDS = null; } }
/************************************ 生成等值线 **********************************************/ public static string dzx(string filePath) { Console.WriteLine("开始创建等值线!"); OSGeo.OGR.Ogr.RegisterAll(); OSGeo.GDAL.Gdal.AllRegister(); //无效值 double noDataValue; //0不使用无效值,1使用无效值 int hasDataValue; //读入数据源 OSGeo.GDAL.Dataset inData = OSGeo.GDAL.Gdal.Open(filePath, OSGeo.GDAL.Access.GA_ReadOnly); //分析数据源 inData.GetRasterBand(1).GetNoDataValue(out noDataValue, out hasDataValue); double min, max, mean, std; inData.GetRasterBand(1).GetStatistics(0, 1, out min, out max, out mean, out std); int jianG = 2; int count = Convert.ToInt32((max - min) / jianG + 0.5); double[] shu = new double[count]; for (int i = 0; i < count; i++) { shu[i] = min + jianG * i; } //创建空的SHP OSGeo.OGR.Ogr.RegisterAll(); OSGeo.OGR.Driver dr = OSGeo.OGR.Ogr.GetDriverByName("ESRI shapefile"); string a = StaticTools.tempFilePath("shp", "原始等值线"); OSGeo.OGR.DataSource ds = dr.CreateDataSource(a, null); OSGeo.OGR.Layer dzxLayer = ds.CreateLayer("", null, OSGeo.OGR.wkbGeometryType.wkbMultiLineString, null); OSGeo.OGR.FieldDefn fieldDf0 = new OSGeo.OGR.FieldDefn("LID", OSGeo.OGR.FieldType.OFTInteger); OSGeo.OGR.FieldDefn fieldDf1 = new OSGeo.OGR.FieldDefn("EVE", OSGeo.OGR.FieldType.OFTReal); dzxLayer.CreateField(fieldDf0, 1); //ID dzxLayer.CreateField(fieldDf1, 1); //Value //Band(1), 间隔, 起始高度, 分段数量, 分段值数组, 是否有无效值, 无效值, 预置图层. ID字段, 高度值字段, null , null OSGeo.GDAL.Gdal.ContourGenerate(inData.GetRasterBand(1), jianG, min, count, shu, hasDataValue, noDataValue, dzxLayer, 0, 1, null, null); if (dzxLayer.GetFeatureCount(0) > 0) { Console.WriteLine("等值线创建完成!"); } else { Console.WriteLine("等值线创建失败!"); } ds.Dispose(); inData.Dispose(); return(a); }
public static bool FT(OSGeo.GDAL.Dataset InputDS, OSGeo.GDAL.DataType OutDataType, string OutPath) { try { if (InputDS == null) { throw new ArgumentNullException("输入数据集为空。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, xSize, ySize, InputDS.RasterCount, OutDataType, null); Tools.Common.CopyMetadata(InputDS, DS); //Matrix<Complex32> M = new Matrix<Complex32>; //for (int i = 0; i < InputDS.RasterCount; i++) //{ for (int Row = 0; Row < ySize; Row++) { float[] Values = new float[xSize]; Complex32[] c = new Complex32[xSize]; //读取DN到数组 InputDS.GetRasterBand(1).ReadRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); for (int Col = 0; Col < xSize; Col++) { c[Col] = new Complex32(Values[Col], 0); } //M.Add(c); //写结果到新栅格 //DS.GetRasterBand(1).WriteRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); DS.FlushCache(); Thread.Sleep(1); } //} Dri.Dispose(); DS.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
/// <summary> /// 模拟结束事件监听辅助函数 /// </summary> protected void SimulateEndHelper(BaseCa ca) { // 将模拟结果添加到系统中 double[] buffer = ca.BeginBuffer; int width = ca.Width; int height = ca.Height; //var map = GIS.FrameWork.Application.App.Map; // 保存输出结果 var path = Application.StartupPath + @"\log"; if (!Directory.Exists(path)) //如果不存在就创建file文件夹 { Directory.CreateDirectory(path); //创建该文件夹 } var outputPath = path + @"\" + (dateNow.ToString("MMddyyhhmmss")) + (this.uuid++) + ".tif"; OSGeo.GDAL.Driver driverSave = OSGeo.GDAL.Gdal.GetDriverByName("GTiff"); OSGeo.GDAL.Dataset datasetSave = driverSave.Create(outputPath, width, height, 1, OSGeo.GDAL.DataType.GDT_Byte, null); datasetSave.WriteRaster(0, 0, width, height, buffer, width, height, 1, new int[1] { 1 }, 0, 0, 0); datasetSave.SetProjection(ca.projStr); datasetSave.SetGeoTransform(ca.geoTransform); datasetSave.GetRasterBand(1).SetNoDataValue(ca.noDataVal); datasetSave.FlushCache(); datasetSave.Dispose(); driverSave.Dispose(); //// 翻转图像 ? //buffer = InvertImage(buffer, width, height); MessageBox.Show("模拟结束, 输出文件:" + outputPath); //// 新建 GDAL dataset //OSGeo.GDAL.Driver driver = OSGeo.GDAL.Gdal.GetDriverByName("MEM"); //OSGeo.GDAL.Dataset dataset = driver.Create("", width, height, 1, OSGeo.GDAL.DataType.GDT_Float64, null); //dataset.WriteRaster(0, 0, width, height, buffer, width, height, 1, new int[1] { 1 }, 0, 0, 0); //// 将GDAL dataset转化为IRaster数据集 //DotSpatial.Data.IRaster raster = GIS.GDAL.RasterConverter.Gdal2DSRaster(dataset, 1); //raster.Name = "Result"; //map.Layers.Add(raster); }
private void Dispose(bool disposing) { if (!disposed) { if (disposing) { if (_GdalDataset != null) { try { _GdalDataset.Dispose(); } finally { _GdalDataset = null; } } } disposed = true; } }
private void openFileDSM_FileOk(object sender, CancelEventArgs e) { labDSMin.Text = openFileDSM.FileName; OSGeo.GDAL.Gdal.AllRegister(); OSGeo.GDAL.Dataset ds = OSGeo.GDAL.Gdal.Open(openFileDSM.FileName, OSGeo.GDAL.Access.GA_ReadOnly); double[] a = new double[6]; ds.GetGeoTransform(a); double xx = a[0]; double yy = a[3]; double size = a[1]; double xSixe = ds.RasterXSize; double ySixe = ds.RasterYSize; labInFileInfo.Text += openFileDSM.SafeFileName + ":\r" + "\r\n" + "左上角X坐标:" + xx.ToString() + "\r" + "左上角Y坐标:" + yy.ToString() + "\r" + "像元尺寸:" + size.ToString() + "\r" + "图像大小:" + xSixe.ToString() + "*" + ySixe.ToString(); ds.Dispose(); }
/// <summary> /// 辐射定标。 /// </summary> /// <param name="InputDS">输入的栅格数据集。</param> /// <param name="OutDataType">输出的数据类型。</param> /// <param name="Gain">增益倍数。</param> /// <param name="Offset">偏移量。</param> /// <param name="OutPath">输出栅格数据集的位置。</param> /// <returns>返回操作成功或失败。</returns> public static bool ApplyGainAndOffset(OSGeo.GDAL.Dataset InputDS, OSGeo.GDAL.DataType OutDataType, List <double> Gain, List <double> Offset, string OutPath) { try { if (InputDS == null) { throw new ArgumentNullException("输入数据集为空。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } if ((Gain.Count != InputDS.RasterCount) || (Offset.Count != InputDS.RasterCount)) { throw new IndexOutOfRangeException("增益数据或偏移数据与输入数据集波段数不符。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } FrmProgress FP = new FrmProgress() { Text = "正在进行辐射定标...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, xSize, ySize, InputDS.RasterCount, OutDataType, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为" + OutDataType.ToString() + "。"); Tools.Common.CopyMetadata(InputDS, DS); for (int i = 0; i < InputDS.RasterCount; i++) //遍历每个波段 { FP.SetProgress2("正在处理波段:", i + 1, InputDS.RasterCount, ""); for (int Row = 0; Row < ySize; Row++) //遍历每一行(y) { FP.SetProgress1("正在处理:", Row + 1, ySize, "行"); double[] Values = new double[xSize]; //读取DN到数组 InputDS.GetRasterBand(i + 1).ReadRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); for (int Col = 0; Col < xSize; Col++) //对每一个值进行计算 { Values[Col] = GainOffset(Values[Col], Gain[i], Offset[i]); } //写结果到新栅格 DS.GetRasterBand(i + 1).WriteRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } } FP.Finish(); Dri.Dispose(); DS.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
/// <summary> /// 二值化。 /// </summary> /// <param name="InputDS">输入的数据集。</param> /// <param name="Threshold">分割阈值。</param> /// <param name="ZeroValue">小于阈值的像元值被设为...</param> /// <param name="OneValue">大于阈值的像元值被设为...</param> /// <param name="OutDataType">输出的数据类型。</param> /// <param name="OutPath">输出栅格数据集的位置。</param> /// <returns>操作成功或失败。</returns> public static bool Binarize(OSGeo.GDAL.Dataset InputDS, double Threshold, double ZeroValue, double OneValue, OSGeo.GDAL.DataType OutDataType, string OutPath) { try { if (InputDS == null) { throw new ArgumentNullException("输入数据集为空。"); } if (InputDS.RasterCount != 1) { throw new ArgumentException("输入的数据集波段大于1。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; FrmProgress FP = new FrmProgress() { Text = "正在进行二值化操作...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, xSize, ySize, 1, OutDataType, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为" + OutDataType.ToString() + "。"); Tools.Common.CopyMetadata(InputDS, DS); for (int Row = 0; Row < ySize; Row++) { FP.SetProgress1("正在处理:", Row + 1, ySize, "行"); double[] Values = new double[xSize]; InputDS.GetRasterBand(1).ReadRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); for (int Col = 0; Col < xSize; Col++) { //阈值应用 if (Values[Col] < Threshold) { Values[Col] = ZeroValue; } else { Values[Col] = OneValue; } } DS.GetRasterBand(1).WriteRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } FP.Finish(); Dri.Dispose(); DS.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.Message); return(false); } }
public static bool ConvertToAAIGrid(OSGeo.GDAL.Dataset InputDS, string ConvertTo, string OutPath) { try { if (InputDS == null) { throw new ArgumentNullException("输入数据集为空。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } if (InputDS.RasterCount != 1) { throw new ArgumentOutOfRangeException("重分类的影像不是灰度影像。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName(ConvertTo); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; FrmProgress FP = new FrmProgress() { Text = "正在进行格式转换...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); double NoDataValue = -9999; int HasNoDataValue = -1; InputDS.GetRasterBand(1).GetNoDataValue(out NoDataValue, out HasNoDataValue); OSGeo.GDAL.Dataset DS = Dri.CreateCopy(OutPath, InputDS, 0, null, null, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为" + DS.GetRasterBand(1).DataType.ToString() + "。"); if (HasNoDataValue == 1) { DS.GetRasterBand(1).SetNoDataValue(NoDataValue); } for (int Row = 0; Row < ySize; Row++) { FP.SetProgress1("正在处理:", Row + 1, ySize, "行"); double[] Values = new double[xSize]; InputDS.GetRasterBand(1).ReadRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); DS.GetRasterBand(1).WriteRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); //DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } DS.Dispose(); FP.Finish(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
/// <summary> /// NoData值替换。将非NoData值替换为指定值。 /// </summary> /// <param name="InputDS">输入的数据集。</param> /// <param name="NoDataValue">NoData值。</param> /// <param name="ReplaceValue">非NoData值替换为的值。</param> /// <param name="OutDataType">输出的数据类型。</param> /// <param name="OutPath">输出数据集的路径。</param> /// <returns>操作成功或失败。</returns> public static bool ReplaceNoData(OSGeo.GDAL.Dataset InputDS, double NoDataValue, double ReplaceValue, OSGeo.GDAL.DataType OutDataType, string OutPath, double NewNoDataValue = -9999) { try { if (InputDS == null) { throw new ArgumentNullException("输入数据集为空。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } if (InputDS.RasterCount != 1) { throw new ArgumentOutOfRangeException("替换值的影像不是灰度影像。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; FrmProgress FP = new FrmProgress() { Text = "正在进行非NoData值替换...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, xSize, ySize, 1, OutDataType, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为" + OutDataType.ToString() + "。"); Tools.Common.CopyMetadata(InputDS, DS); DS.GetRasterBand(1).SetNoDataValue(NoDataValue); for (int Row = 0; Row < ySize; Row++) { FP.SetProgress1("正在处理:", Row + 1, ySize, "行"); double[] Values = new double[xSize]; InputDS.GetRasterBand(1).ReadRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); for (int Col = 0; Col < xSize; Col++) { if (Math.Abs(Values[Col] - NoDataValue) > 1e-7) { //将ReplaceValue与NoDataValue的值设置为一样的可以仅更改NoData值 if (Math.Abs(ReplaceValue - NoDataValue) > 1e-7) { Values[Col] = ReplaceValue; } } else { Values[Col] = NewNoDataValue; } } DS.GetRasterBand(1).WriteRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } DS.Dispose(); FP.Finish(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
/// <summary> /// 重分类。 /// </summary> /// <param name="InputDS">输入的数据集。</param> /// <param name="ReplaceList">用于对照值替换的表。</param> /// <param name="OutDataType">输出的数据类型。</param> /// <param name="OutPath">输出数据集的路径。</param> /// <param name="DefaultValue">若值不在ReplaceList中,则该像元的值设为。</param> /// <returns>操作成功或失败。</returns> public static bool Reclassify(OSGeo.GDAL.Dataset InputDS, List <double[]> ReplaceList, OSGeo.GDAL.DataType OutDataType, string OutPath, double DefaultValue = 0.03) { try { if (InputDS == null) { throw new ArgumentNullException("输入数据集为空。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } if (InputDS.RasterCount != 1) { throw new ArgumentOutOfRangeException("重分类的影像不是灰度影像。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; FrmProgress FP = new FrmProgress() { Text = "正在进行重分类...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); double NoDataValue = -9999; int HasNoDataValue = -1; InputDS.GetRasterBand(1).GetNoDataValue(out NoDataValue, out HasNoDataValue); OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, xSize, ySize, 1, OutDataType, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为" + OutDataType.ToString() + "。"); if (HasNoDataValue == 1) { DS.GetRasterBand(1).SetNoDataValue(NoDataValue); } Tools.Common.CopyMetadata(InputDS, DS); for (int Row = 0; Row < ySize; Row++) { FP.SetProgress1("正在处理:", Row + 1, ySize, "行"); double[] Values = new double[xSize]; InputDS.GetRasterBand(1).ReadRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); for (int Col = 0; Col < xSize; Col++) { //值为NoData if (Math.Abs(Values[Col] - NoDataValue) < 1e-7) { continue; } int i = -1; //对照表进行值替换 for (i = 0; i < ReplaceList.Count; i++) { if (Values[Col] == ReplaceList[i][0]) { Values[Col] = ReplaceList[i][1]; break; } } if (i == ReplaceList.Count) { Values[Col] = 0.03; } } DS.GetRasterBand(1).WriteRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } DS.Dispose(); FP.Finish(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
public static bool CutImage(OSGeo.GDAL.Dataset InputDS, int CutWidth, int CutHeight, OSGeo.GDAL.DataType OutDataType, string OutFolder) { try { if (InputDS == null) { throw new ArgumentNullException("输入的数据集不可为空。"); } if (String.IsNullOrWhiteSpace(OutFolder)) { throw new ArgumentNullException("输出路径为空或非法。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } //取输入的宽、高、波段最小值创建输出数据集。 int Width = InputDS.RasterXSize; int Height = InputDS.RasterYSize; int Rows = Height / CutHeight; int Cols = Width / CutWidth; FrmProgress FP = new FrmProgress() { Text = "正在进行影像裁剪...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); FP.Output("输出的目录为:" + OutFolder); FP.Output("输出的数据类型为:" + OutDataType.ToString()); for (int row = 0; row < Rows; row++) { FP.SetProgress2("总进度:", row + 1, Rows, ""); string ParentPath = row.ToString(); Directory.CreateDirectory(Path.Combine(OutFolder, ParentPath)); for (int col = 0; col < Cols; col++) { FP.SetProgress1("当前行进度:", col + 1, Cols, ""); string OutName = row.ToString() + "_" + col.ToString() + ".tif"; OSGeo.GDAL.Dataset DS = Dri.Create(Path.Combine(OutFolder, ParentPath, OutName), CutWidth, CutHeight, InputDS.RasterCount, OutDataType, null); for (int band = 1; band <= InputDS.RasterCount; band++) { double[] buf = new double[CutWidth * CutHeight]; InputDS.GetRasterBand(band).ReadRaster(col * CutWidth, row * CutHeight, CutWidth, CutHeight, buf, CutWidth, CutHeight, 0, 0); DS.GetRasterBand(band).WriteRaster(0, 0, CutWidth, CutHeight, buf, CutWidth, CutHeight, 0, 0); } ////单行读取写入,防止爆内存。 //for (int cRow = 0; cRow < CutHeight; cRow++) //{ // double[] buf = new double[CutWidth]; // InputDS.GetRasterBand(band).ReadRaster(col * CutWidth, row * CutHeight + cRow, CutWidth, 1, buf, CutWidth, 1, 0, 0); // DS.GetRasterBand(band).WriteRaster(0, cRow, CutWidth, 1, buf, CutWidth, 1, 0, 0); // DS.FlushCache(); // Thread.Sleep(1); //} DS.FlushCache(); DS.Dispose(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } } FP.Finish(); InputDS.Dispose(); Dri.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
/// <summary> /// 数据集相除。 /// </summary> /// <param name="D1">被除数据集。</param> /// <param name="D2">除数据集。</param> /// <param name="OutDataType">输出数据集的数据类型。</param> /// <param name="OutPath">输出路径。</param> /// <returns>操作成功或失败。</returns> public static bool Divide(OSGeo.GDAL.Dataset D1, OSGeo.GDAL.Dataset D2, OSGeo.GDAL.DataType OutDataType, string OutPath) { try { if (D1 == null || D2 == null) { throw new ArgumentNullException("输入的数据集不可为空。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } //取输入的宽、高、波段最小值创建输出数据集。 int Width = Math.Min(D1.RasterXSize, D2.RasterXSize); int Height = Math.Min(D1.RasterYSize, D2.RasterYSize); int band = Math.Min(D1.RasterCount, D2.RasterCount); FrmProgress FP = new FrmProgress() { Text = "正在进行数据集除法运算...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, Width, Height, band, OutDataType, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为" + OutDataType.ToString() + "。"); Tools.Common.CopyMetadata(D1, DS); for (int bandcount = 1; bandcount <= band; bandcount++) { FP.SetProgress2("正在处理", bandcount, band, "波段"); for (int row = 0; row < Height; row++) { FP.SetProgress1("正在处理:", row + 1, Height, "行"); double[] d1Tmp = new double[Width]; double[] d2Tmp = new double[Width]; double[] dsTmp = new double[Width]; D1.GetRasterBand(bandcount).ReadRaster(0, row, Width, 1, d1Tmp, Width, 1, 0, 0); D2.GetRasterBand(bandcount).ReadRaster(0, row, Width, 1, d2Tmp, Width, 1, 0, 0); for (long i = 0; i < Width; i++) { if (d2Tmp[i] == 0) { dsTmp[i] = 0; } else { dsTmp[i] = d1Tmp[i] / d2Tmp[i]; } } DS.GetRasterBand(bandcount).WriteRaster(0, row, Width, 1, dsTmp, Width, 1, 0, 0); DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } } FP.Finish(); Dri.Dispose(); DS.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
/// <summary> /// ISO Data分类算法。 /// </summary> /// <param name="InputDS">输入的数据集。</param> /// <param name="MinKind">最小分类数。</param> /// <param name="MaxKind">最大分类数。</param> /// <param name="MaxItera">最大迭代次数。</param> /// <param name="CenterDiff">最大中心变化率</param> /// <param name="MinPixelNumInClass">类内最小像元数。</param> /// <param name="MaxClassStddev">最大类内标准差</param> /// <param name="MinClassDist">最小类间距离。</param> /// <param name="OutPath">结果数据集输出路径。</param> /// <returns>操作成功或失败。</returns> public static bool IsoData(OSGeo.GDAL.Dataset InputDS, int MinKind, int MaxKind, int MaxItera, double CenterDiff, int MinPixelNumInClass, double MaxClassStddev, double MinClassDist, string OutPath) { try { if (InputDS == null) { throw new ArgumentNullException("输入数据集为空。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } int bandNum = InputDS.RasterCount; int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; FrmProgress FP = new FrmProgress() { Text = "正在进行ISO Data分类...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, xSize, ySize, 1, OSGeo.GDAL.DataType.GDT_Byte, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为GDT_Byte。"); Tools.Common.CopyMetadata(InputDS, DS); int tmpItera = 1; bool tmpContinue = true; double[] min = new double[bandNum]; double[] max = new double[bandNum]; double[] mean = new double[bandNum]; double[] stddev = new double[bandNum]; int InitKind = (MinKind + MaxKind) / 2; List <ClusterCenter> ICenter = new List <ClusterCenter>(); //计算数据集各波段统计数据 for (int i = 0; i < bandNum; i++) { Tools.Common.GetStatistics(InputDS.GetRasterBand(i + 1), out min[i], out max[i], out mean[i], out stddev[i]); } //初始化聚类中心 for (int i = 0; i < InitKind; i++) { ICenter.Add(new ClusterCenter(bandNum)); for (int band = 0; band < bandNum; band++) { ICenter[i].NewCenter[band] = ICenter[i].OldCenter[band] = mean[band] + stddev[band] - 2 * i * stddev[band] / InitKind; } } //循环体 while (tmpContinue) { FP.Output("正在迭代第" + tmpItera.ToString() + "次..."); FP.SetProgress2("正在迭代:", tmpItera, MaxItera, "次"); //清空所有聚类中心的和、平均值、标准差、像元列表 foreach (ClusterCenter C in ICenter) { C.ResetAll(); } //重置所有类的像元计数为0 for (int i = 0; i < ICenter.Count; i++) { ICenter[i].PixelCount = 0; } for (int i = 0; i < ICenter.Count; i++) { string tmpCenter = "第" + (i + 1).ToString() + "类中心:"; for (int band = 0; band < bandNum; band++) { tmpCenter += ICenter[i].OldCenter[band] + ", "; } FP.Output(tmpCenter); } //遍历数据集每一行 for (int row = 0; row < ySize; row++) { FP.SetProgress1("正在处理:", row + 1, ySize, "行"); double[][] tmpInput = new double[bandNum][]; //用于存储输入像元的交错数组 //将一行的所有波段像元值读取入交错数组 for (int band = 0; band < bandNum; band++) { tmpInput[band] = new double[xSize]; InputDS.GetRasterBand(band + 1).ReadRaster(0, row, xSize, 1, tmpInput[band], xSize, 1, 0, 0); } byte[] tmpOut = new byte[xSize]; //用于存储输出像元的数组 //遍历一行的每一列,对像元分类 for (int col = 0; col < xSize; col++) { double[] tmpPix = new double[bandNum]; //临时存储单个像元所有波段的数组 //将指定行列的所有波段像元转储到数组 for (int band = 0; band < bandNum; band++) { tmpPix[band] = tmpInput[band][col]; } double[] tmpDis = new double[ICenter.Count]; //单个像元到不同聚类中心的距离数组 //计算像元到不同聚类中心的距离 for (int i = 0; i < ICenter.Count; i++) { tmpDis[i] = Distance(tmpPix, ICenter[i].OldCenter); } double tmpMinDis = tmpDis[0]; //最小距离 int tmpClass = 0; //分类 //计算最小值及分类 for (int i = 1; i < ICenter.Count; i++) { if (tmpDis[i] < tmpMinDis) { tmpMinDis = tmpDis[i]; tmpClass = i; } } //将该像元添加到对应聚类的列表中 ICenter[tmpClass].CenterList.Add(tmpPix); //写入分类并增加对应类的像元计数 tmpOut[col] = (byte)(tmpClass + 1); ICenter[tmpClass].PixelCount += 1; } DS.GetRasterBand(1).WriteRaster(0, row, xSize, 1, tmpOut, xSize, 1, 0, 0); DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } //重新计算每个集群的均值和方差 foreach (ClusterCenter c in ICenter) { c.GetStddev(); //计算方差之前会自动求和和平均值 //将聚类中所有像元的平均值作为聚类的新中心? for (int band = 0; band < bandNum; band++) { c.NewCenter[band] = c.CenterMean[band]; } } for (int i = 0; i < ICenter.Count; i++) { string tmpCenter = "聚类后第" + (i + 1).ToString() + "类:"; tmpCenter += "\r\n\t像元数:" + ICenter[i].PixelCount + ", "; tmpCenter += "\r\n\t和:"; for (int band = 0; band < bandNum; band++) { tmpCenter += ICenter[i].CenterTotal[band] + ", "; } tmpCenter += "\r\n\t平均中心:"; for (int band = 0; band < bandNum; band++) { tmpCenter += ICenter[i].CenterMean[band] + ", "; } tmpCenter += "\r\n\t标准差:"; for (int band = 0; band < bandNum; band++) { tmpCenter += ICenter[i].CenterStddev[band] + ", "; } FP.Output(tmpCenter); } bool tmpCenterModified = false; //判断是否有聚类中心数量的变动 Delete: //删除像元数在阈值以下的聚类 for (int i = 0; i < ICenter.Count; i++) { if (ICenter[i].PixelCount < MinPixelNumInClass) { FP.Output("第" + (i + 1).ToString() + "类像元数只有" + ICenter[i].PixelCount.ToString() + "个,将被删除。"); if (ICenter.Count - 1 >= MinKind) { tmpCenterModified = true; ICenter.RemoveAt(i); goto Delete; } else { FP.Output("第" + (i + 1).ToString() + "类删除失败,已达到最小分类数。"); goto EndDelete; } } } EndDelete :; //合并与分裂 List <ClusterCenter> tmpChangeCenter = new List <ClusterCenter>(); //用于暂存对全局列表的更改 //偶次合并 if (tmpItera % 2 == 0) { Combine: for (int i = 0; i < ICenter.Count; i++) { for (int j = 0; j < ICenter.Count; j++) { //不与自身比较 if (i == j) { continue; } //类间距离小于设定阈值,进行合并 if (Distance(ICenter[i].CenterMean, ICenter[j].CenterMean) < MinClassDist) { FP.Output("第" + (i + 1).ToString() + "类和第" + (j + 1).ToString() + "类的距离过小,为" + Distance(ICenter[i].CenterMean, ICenter[j].CenterMean) + ",将被合并。"); if (ICenter.Count - 1 >= MinKind) { tmpCenterModified = true; tmpChangeCenter.Add(new ClusterCenter(ICenter[i], ICenter[j])); //合并两类并在临时列表中新建中心。 //考虑i、j的大小,依次删除全局列表中对应索引处的中心(从大的开始删除)。 if (i > j) { ICenter.RemoveAt(i); ICenter.RemoveAt(j); } else { ICenter.RemoveAt(j); ICenter.RemoveAt(i); } //每次迭代是只合并一次嘛?如果是的话就不需要goto goto Combine; } else { FP.Output("第" + (i + 1).ToString() + "类和第" + (j + 1).ToString() + "类合并失败,已达到最小分类数。"); goto EndCombine; } } } } EndCombine :; } else //奇次分裂 { Split : for (int i = 0; i < ICenter.Count; i++) { if (ICenter[i].MaxStddev > MaxClassStddev) { FP.Output("第" + (i + 1).ToString() + "类的类内最大方差为" + ICenter[i].MaxStddev.ToString() + ",将被分裂。"); if (ICenter.Count + 1 <= MaxKind) { tmpCenterModified = true; ClusterCenter C1 = new ClusterCenter(bandNum); ClusterCenter C2 = new ClusterCenter(bandNum); //新建两聚类,中心为旧中心加减方差的一半 //分裂后中心的参数怎么算? for (int band = 0; band < bandNum; band++) { //只改变大于标准差的中心值,若不大于则保持不变。 if (ICenter[i].CenterStddev[band] > MaxClassStddev) { C1.OldCenter[band] = C1.NewCenter[band] = ICenter[i].NewCenter[band] + ICenter[i].CenterStddev[band] / 2; C2.OldCenter[band] = C2.NewCenter[band] = ICenter[i].NewCenter[band] - ICenter[i].CenterStddev[band] / 2; } else { C1.OldCenter[band] = C1.NewCenter[band] = ICenter[i].NewCenter[band]; C2.OldCenter[band] = C2.NewCenter[band] = ICenter[i].NewCenter[band]; } //C1.OldCenter[band] = C1.NewCenter[band] = ICenter[i].NewCenter[band] + MaxClassStddev / 2; //C2.OldCenter[band] = C2.NewCenter[band] = ICenter[i].NewCenter[band] - MaxClassStddev / 2; } tmpChangeCenter.Add(C1); tmpChangeCenter.Add(C2); ICenter.RemoveAt(i); goto Split; } else { FP.Output("第" + (i + 1).ToString() + "类分裂失败,已达到最大分类数。"); goto EndSplit; } } } EndSplit :; } double tmpCenterChangeMax = 100000000; //仅在聚类中心数量没有变化的时候才计算中心变化率 if (!tmpCenterModified) { double[] tmpCenterChange = new double[ICenter.Count]; //计算聚类中心变化率 for (int i = 0; i < ICenter.Count; i++) { for (int band = 0; band < bandNum; band++) { if (Math.Abs(ICenter[i].OldCenter[band]) <= 1e-7) //分母为0 { tmpCenterChange[i] += Math.Abs(ICenter[i].NewCenter[band] - ICenter[i].OldCenter[band]) / 0.0001; } else { tmpCenterChange[i] += Math.Abs(ICenter[i].NewCenter[band] - ICenter[i].OldCenter[band]) / ICenter[i].OldCenter[band]; } } tmpCenterChange[i] /= bandNum; } //计算最大变化率 tmpCenterChangeMax = tmpCenterChange[0]; for (int i = 1; i < ICenter.Count; i++) { if (tmpCenterChange[i] > tmpCenterChangeMax) { tmpCenterChangeMax = tmpCenterChange[i]; } } FP.Output("中心变化率:" + tmpCenterChangeMax + ",阈值:" + CenterDiff); FP.SetProgress1("最大中心变化率:", CenterDiff, tmpCenterChangeMax, ""); } else { FP.Output("第" + tmpItera.ToString() + "次迭代出现聚类中心的合并或分裂,不计算中心变化率..."); } //将新的中心变为旧的中心,准备开始新一轮迭代 for (int i = 0; i < ICenter.Count; i++) { for (int band = 0; band < bandNum; band++) { ICenter[i].OldCenter[band] = ICenter[i].NewCenter[band]; } } //将临时新建的聚类中心添加到全局聚类中心的末尾,并清空临时聚类中心 ICenter.AddRange(tmpChangeCenter); tmpChangeCenter.Clear(); tmpItera++; //判断是否继续循环。 if (tmpItera % 2 == 0) { if (((MaxItera > 1) && (tmpItera > MaxItera)) || (!tmpCenterModified && tmpCenterChangeMax < CenterDiff) || (tmpItera > 10000)) { tmpContinue = false; } } } FP.Finish(); DS.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
static void Main(string[] args) { OSGeo.GDAL.Gdal.AllRegister(); OSGeo.OGR.Ogr.RegisterAll(); //shp驱动 OSGeo.OGR.Driver shpDataDriver = OSGeo.OGR.Ogr.GetDriverByName("ESRI shapefile"); //shp数据源 shpDataSet = shpDataDriver.CreateDataSource(shpSavePath, null); //img驱动 gdalDriver = OSGeo.GDAL.Gdal.GetDriverByName("HFA"); //dsm数据源 dsmDataset = OSGeo.GDAL.Gdal.Open(dsmPath, OSGeo.GDAL.Access.GA_Update); //dsm数据信息 dsmDataset.GetGeoTransform(dsm_Transform); dsm_Xsize = dsmDataset.RasterXSize; dsm_Ysize = dsmDataset.RasterYSize; //投影信息 srs = dsmDataset.GetProjectionRef() == "" ? null : new OSGeo.OSR.SpatialReference(dsmDataset.GetProjectionRef()); Stopwatch aTime = new Stopwatch(); aTime.Start(); //1 坡度图 buildSlope(); StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); //2 坡度线 OSGeo.OGR.Layer pdx = getPDX(1); StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); OSGeo.OGR.Layer slopeCleanLayer = cleanLayer(pdx, 200, 5000); StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); //3 等高线 OSGeo.OGR.Layer dzx = getDZX_(); StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); OSGeo.OGR.Layer dzxPolyLayer = cleanDZX(dzx); StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); //4 筛选 OSGeo.OGR.Layer selectLayer = selectionFeatuers(slopeCleanLayer, dzxPolyLayer); StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); OSGeo.OGR.Layer resLayer = cleanLayer_FF(selectLayer); StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); // 最小外接矩形 getMinOutLineFromLayerToLayer(resLayer); StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); //5 简化 jianhua(resLayer, 175, 5); StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); //6 高度值 未完成 //getH(resLayer); //StaticTools.msgLine($"完成!用时:{aTime.Elapsed.ToString()}\n"); aTime.Restart(); shpDataSet.Dispose(); shpDataDriver.Dispose(); dsmDataset.Dispose(); gdalDriver.Dispose(); // aTime.Stop(); Console.Write("Press any key to continue . . . "); Console.ReadKey(true); }
/// <summary> /// 平滑锐化算法。 /// </summary> /// <param name="InputDS">输入的栅格数据集。</param> /// <param name="OutDataType">输出的数据类型。</param> /// <param name="Method">平滑锐化方法。</param> /// <param name="OutPath">输出栅格数据集的位置。</param> /// <returns>返回操作成功或失败。</returns> public static bool SmoothSharpening(OSGeo.GDAL.Dataset InputDS, OSGeo.GDAL.DataType OutDataType, SmoothShapeninngMethods Method, string OutPath) { try { if (InputDS == null) { throw new ArgumentNullException("输入数据集为空。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; FrmProgress FP = new FrmProgress() { Text = "正在进行平滑锐化操作...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); FP.Output("选择的平滑/锐化方法为:\"" + (typeof(SmoothShapeninngMethods).GetField((Method).ToString()).GetCustomAttributes(false)[0] as DescriptionAttribute).Description + "\""); OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, xSize, ySize, InputDS.RasterCount, OutDataType, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为" + OutDataType.ToString() + "。"); Tools.Common.CopyMetadata(InputDS, DS); for (int band = 0; band < InputDS.RasterCount; band++) //遍历每个波段 { FP.SetProgress1("正在处理", band + 1, InputDS.RasterCount, "波段"); for (int Row = 0; Row < ySize - 2; Row++) //从第1行遍历至倒数第三行 { FP.SetProgress2("正在处理", Row, ySize - 2, "行"); double[] Values = new double[3 * xSize]; //读取的数值 double[] Result = new double[xSize]; //结果数值 InputDS.GetRasterBand(band + 1).ReadRaster(0, Row, xSize, 3, Values, xSize, 3, 0, 0); //读取3行 Array.Copy(Values, xSize, Result, 0, xSize); // for (int Col = 0; Col < xSize - 2; Col++) //对每一个值进行计算 { double[,] Input = new double[3, 3]; for (int i = 0; i < 3; i++) { Input[i, 0] = Values[Col + i * xSize]; Input[i, 1] = Values[Col + i * xSize + 1]; Input[i, 2] = Values[Col + i * xSize + 2]; } Result[Col + 1] = SmoothSharpening(Input, Method); //计算输入数据中心像元的值 } //写结果到新栅格 DS.GetRasterBand(band + 1).WriteRaster(0, Row + 1, xSize, 1, Result, xSize, 1, 0, 0); } if ((Method.ToString()).Contains("Smooth")) { double[] row = new double[xSize]; InputDS.GetRasterBand(band + 1).ReadRaster(0, 0, xSize, 1, row, xSize, 1, 0, 0); //读取第一行 DS.GetRasterBand(band + 1).WriteRaster(0, 0, xSize, 1, row, xSize, 1, 0, 0); InputDS.GetRasterBand(band + 1).ReadRaster(0, ySize - 1, xSize, 1, row, xSize, 1, 0, 0); //读取最后一行 DS.GetRasterBand(band + 1).WriteRaster(0, ySize - 1, xSize, 1, row, xSize, 1, 0, 0); } DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } FP.Finish(); Dri.Dispose(); DS.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
public static bool CalculateFloodArea(string InDir, string OutDir) { try { if (!Directory.Exists(InDir)) { throw new FileNotFoundException("输入路径不存在。"); } if (!Directory.Exists(OutDir)) { Directory.CreateDirectory(OutDir); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } FrmProgress FP = new FrmProgress() { Text = "正在处理洪水范围...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); bool createFlag = true; string[] ascFiles = Directory.GetFiles(InDir); int xSize = 0; int ySize = 0; OSGeo.GDAL.Dataset rangeDS = new OSGeo.GDAL.Dataset(IntPtr.Zero, false, null); OSGeo.GDAL.Dataset depthDS = new OSGeo.GDAL.Dataset(IntPtr.Zero, false, null); OSGeo.GDAL.Dataset timeDS = new OSGeo.GDAL.Dataset(IntPtr.Zero, false, null); for (int i = 0; i < ascFiles.Length; i++) { FP.SetProgress2("正在处理文件:", i + 1, ascFiles.Length, ""); string tmpPath = ascFiles[i]; FP.Output("正在处理:" + (i + 1).ToString() + ". " + tmpPath); if (tmpPath.Substring(tmpPath.LastIndexOf(".")) != ".txt") { FP.Output(tmpPath + "不是txt文件。"); continue; } OSGeo.GDAL.Dataset tmpDS = OSGeo.GDAL.Gdal.Open(tmpPath, OSGeo.GDAL.Access.GA_ReadOnly); if (createFlag) { xSize = tmpDS.RasterXSize; ySize = tmpDS.RasterYSize; string inDirName = Path.GetDirectoryName(tmpPath).Substring(Path.GetDirectoryName(tmpPath).LastIndexOf("\\") + 1); rangeDS = Dri.Create(Path.Combine(OutDir, inDirName + "_floodRange.tiff"), xSize, ySize, 1, OSGeo.GDAL.DataType.GDT_Float32, null); Tools.Common.CopyMetadata(tmpDS, rangeDS); FP.Output("已创建输出数据集\"" + Path.Combine(OutDir, inDirName + "_floodRange.tiff") + "\"。"); depthDS = Dri.Create(Path.Combine(OutDir, inDirName + "_floodDepth.tiff"), xSize, ySize, 1, OSGeo.GDAL.DataType.GDT_Float32, null); Tools.Common.CopyMetadata(tmpDS, depthDS); FP.Output("已创建输出数据集\"" + Path.Combine(OutDir, inDirName + "_floodDepth.tiff") + "\"。"); timeDS = Dri.Create(Path.Combine(OutDir, inDirName + "_floodTime.tiff"), xSize, ySize, 1, OSGeo.GDAL.DataType.GDT_Float32, null); Tools.Common.CopyMetadata(tmpDS, timeDS); FP.Output("已创建输出数据集\"" + Path.Combine(OutDir, inDirName + "_floodTime.tiff") + "\"。"); createFlag = false; } for (int Row = 0; Row < ySize; Row++) { double[] tmpValues = new double[xSize]; double[] rangeValues = new double[xSize]; double[] depthValues = new double[xSize]; double[] timeValues = new double[xSize]; tmpDS.GetRasterBand(1).ReadRaster(0, Row, xSize, 1, tmpValues, xSize, 1, 0, 0); rangeDS.GetRasterBand(1).ReadRaster(0, Row, xSize, 1, rangeValues, xSize, 1, 0, 0); depthDS.GetRasterBand(1).ReadRaster(0, Row, xSize, 1, depthValues, xSize, 1, 0, 0); timeDS.GetRasterBand(1).ReadRaster(0, Row, xSize, 1, timeValues, xSize, 1, 0, 0); for (int Col = 0; Col < xSize; Col++) { //计算洪水范围 if (Math.Abs(tmpValues[Col]) <= 1e-7) //Nodata { continue; } else { rangeValues[Col] = 1; if (tmpValues[Col] > depthValues[Col]) { depthValues[Col] = tmpValues[Col]; } timeValues[Col] += 1; } } rangeDS.GetRasterBand(1).WriteRaster(0, Row, xSize, 1, rangeValues, xSize, 1, 0, 0); rangeDS.FlushCache(); depthDS.GetRasterBand(1).WriteRaster(0, Row, xSize, 1, depthValues, xSize, 1, 0, 0); depthDS.FlushCache(); timeDS.GetRasterBand(1).WriteRaster(0, Row, xSize, 1, timeValues, xSize, 1, 0, 0); timeDS.FlushCache(); } tmpDS.Dispose(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } FP.Finish(); rangeDS.Dispose(); depthDS.Dispose(); timeDS.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
/// <summary> /// 影像直方图匹配。 /// </summary> /// <param name="InputDS">输入的数据集。</param> /// <param name="MatchDS">要匹配到的数据集。</param> /// <param name="InputCumu">输入的数据集的累积概率表。</param> /// <param name="MatchingCumu">要匹配到的数据集的累积概率表。</param> /// <param name="OutDataType">输出的数据类型。</param> /// <param name="OutPath">输出栅格数据集的位置。</param> /// <returns>操作成功或失败。</returns> public static bool HistogramMatching(OSGeo.GDAL.Dataset InputDS, OSGeo.GDAL.Dataset MatchDS, double[][] InputCumu, double[][] MatchingCumu, OSGeo.GDAL.DataType OutDataType, string OutPath) { try { if (InputDS.RasterCount != MatchDS.RasterCount) { throw new ArgumentException("数据集波段数不一致。"); } FrmProgress FP = new FrmProgress() { Text = "正在进行影像直方图匹配...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); int[][] LUT = new int[InputDS.RasterCount][]; FP.Output("正在计算查找表..."); for (int i = 0; i < InputDS.RasterCount; i++) { LUT[i] = HistogramMatching(InputCumu[i], MatchingCumu[i]); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, xSize, ySize, InputDS.RasterCount, OutDataType, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为" + OutDataType.ToString() + "。"); Tools.Common.CopyMetadata(InputDS, DS); for (int bandcount = 0; bandcount < InputDS.RasterCount; bandcount++) { FP.SetProgress2("正在处理", bandcount + 1, InputDS.RasterCount, "波段"); Tools.Common.GetMinimum(InputDS.GetRasterBand(bandcount + 1), out double inputDSBandMin); Tools.Common.GetMinimum(MatchDS.GetRasterBand(bandcount + 1), out double matchDSBandMin); for (int Row = 0; Row < ySize; Row++) { FP.SetProgress1("正在处理", Row + 1, ySize, "行"); double[] Values = new double[xSize]; //读取DN到数组 InputDS.GetRasterBand(bandcount + 1).ReadRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); for (int Col = 0; Col < xSize; Col++) { //防止GDAL自带方法算出的统计数据越界。 if ((Values[Col] - inputDSBandMin) <= 0) { Values[Col] = matchDSBandMin + LUT[bandcount][0]; continue; } if ((Values[Col] - inputDSBandMin) >= LUT[bandcount].Length - 1) { Values[Col] = matchDSBandMin + LUT[bandcount][LUT[bandcount].Length - 1]; continue; } Values[Col] = matchDSBandMin + LUT[bandcount][(int)(Values[Col] - inputDSBandMin)]; } //写结果到新栅格 DS.GetRasterBand(bandcount + 1).WriteRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0); DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } } FP.Finish(); Dri.Dispose(); DS.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }
/// <summary> /// K-Means算法。 /// </summary> /// <param name="InputDS">输入的数据集。</param> /// <param name="Kind">分类数。</param> /// <param name="MaxItera">最大迭代次数。</param> /// <param name="CenterDiff">聚类中心变化率阈值。</param> /// <param name="OutPath">输出路径。</param> /// <returns>操作成功或失败。</returns> public static bool KMeans(OSGeo.GDAL.Dataset InputDS, int Kind, int MaxItera, double CenterDiff, string OutPath) { try { if (InputDS == null) { throw new ArgumentNullException("输入数据集为空。"); } if (String.IsNullOrWhiteSpace(OutPath.Trim())) { throw new ArgumentNullException("输出路径为空或非法。"); } OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff"); if (Dri == null) { throw new Exception("无法获取GDAL Driver。"); } int bandNum = InputDS.RasterCount; int xSize = InputDS.RasterXSize; int ySize = InputDS.RasterYSize; FrmProgress FP = new FrmProgress() { Text = "正在进行K-Means分类...", }; Thread t = new Thread(() => { FP.ShowDialog(); }); t.SetApartmentState(ApartmentState.STA); t.Start(); OSGeo.GDAL.Dataset DS = Dri.Create(OutPath, xSize, ySize, 1, OSGeo.GDAL.DataType.GDT_Byte, null); FP.Output("已创建输出数据集\"" + OutPath + "\",数据类型为GDT_Byte。"); Tools.Common.CopyMetadata(InputDS, DS); int tmpItera = 0; bool tmpContinue = true; double[] min = new double[bandNum]; double[] max = new double[bandNum]; double[] mean = new double[bandNum]; double[] stddev = new double[bandNum]; ClusterCenter[] KCenter = new ClusterCenter[Kind]; //计算数据集各波段统计数据 for (int i = 0; i < bandNum; i++) { Tools.Common.GetStatistics(InputDS.GetRasterBand(i + 1), out min[i], out max[i], out mean[i], out stddev[i]); } //初始化聚类中心 for (int i = 0; i < Kind; i++) { KCenter[i] = new ClusterCenter(bandNum); for (int band = 0; band < bandNum; band++) { KCenter[i].NewCenter[band] = KCenter[i].OldCenter[band] = mean[band] + stddev[band] - 2 * i * stddev[band] / Kind; } } //循环体 while (tmpContinue) { FP.Output("正在迭代第" + (tmpItera + 1).ToString() + "次..."); FP.SetProgress2("正在迭代:", tmpItera + 1, MaxItera, "次"); //重置所有类的像元计数为1 for (int i = 0; i < Kind; i++) { KCenter[i].PixelCount = 1; } for (int i = 0; i < Kind; i++) { string tmpCenter = "第" + (i + 1).ToString() + "类中心:\r\n"; for (int band = 0; band < bandNum; band++) { tmpCenter += "\t第" + (band + 1).ToString() + "波段中心:" + KCenter[i].OldCenter[band] + "\r\n"; } FP.Output(tmpCenter); } //遍历数据集每一行 for (int row = 0; row < ySize; row++) { FP.SetProgress1("正在处理:", row + 1, ySize, "行"); double[][] tmpInput = new double[bandNum][]; //用于存储输入像元的交错数组 //将一行的所有波段像元值读取入交错数组 for (int band = 0; band < bandNum; band++) { tmpInput[band] = new double[xSize]; InputDS.GetRasterBand(band + 1).ReadRaster(0, row, xSize, 1, tmpInput[band], xSize, 1, 0, 0); } byte[] tmpOut = new byte[xSize]; //用于存储输出像元的数组 //遍历一行的每一列,对像元分类 for (int col = 0; col < xSize; col++) { double[] tmpPix = new double[bandNum]; //临时存储单个像元所有波段的数组 //将指定行列的所有波段像元转储到数组 for (int band = 0; band < bandNum; band++) { tmpPix[band] = tmpInput[band][col]; } double[] tmpDis = new double[Kind]; //单个像元到不同聚类中心的距离数组 //计算像元到不同聚类中心的距离 for (int i = 0; i < Kind; i++) { tmpDis[i] = Distance(tmpPix, KCenter[i].OldCenter); } double tmpMinDis = tmpDis[0]; //最小距离 int tmpClass = 0; //分类 //计算最小值及分类 for (int i = 1; i < Kind; i++) { if (tmpDis[i] < tmpMinDis) { tmpMinDis = tmpDis[i]; tmpClass = i; } } //更新聚类中心 for (int band = 0; band < bandNum; band++) { KCenter[tmpClass].NewCenter[band] = (KCenter[tmpClass].NewCenter[band] * KCenter[tmpClass].PixelCount + tmpPix[band]) / (KCenter[tmpClass].PixelCount + 1); } //写入分类并增加对应类的像元计数 tmpOut[col] = (byte)(tmpClass + 1); KCenter[tmpClass].PixelCount += 1; } DS.GetRasterBand(1).WriteRaster(0, row, xSize, 1, tmpOut, xSize, 1, 0, 0); DS.FlushCache(); Thread.Sleep(1); if (FP.Canceled) { Thread.Sleep(500); FP.Finish(); throw new OperationCanceledException("操作被用户取消。"); } } for (int i = 0; i < Kind; i++) { string tmpCenter = "聚类后第" + (i + 1).ToString() + "类:\r\n\t新中心:"; for (int band = 0; band < bandNum; band++) { tmpCenter += KCenter[i].NewCenter[band] + ", "; } FP.Output(tmpCenter); } double[] tmpCenterChange = new double[Kind]; //计算聚类中心变化率 for (int i = 0; i < Kind; i++) { for (int band = 0; band < bandNum; band++) { if (Math.Abs(KCenter[i].OldCenter[band]) <= 1e-7) //分母为0 { tmpCenterChange[i] += Math.Abs(KCenter[i].NewCenter[band] - KCenter[i].OldCenter[band]) / 0.0001; } else { tmpCenterChange[i] += Math.Abs(KCenter[i].NewCenter[band] - KCenter[i].OldCenter[band]) / KCenter[i].OldCenter[band]; } } tmpCenterChange[i] /= bandNum; } //计算最大变化率 double tmpCenterChangeMax = tmpCenterChange[0]; for (int i = 1; i < Kind; i++) { if (tmpCenterChange[i] > tmpCenterChangeMax) { tmpCenterChangeMax = tmpCenterChange[i]; } } FP.Output("中心变化率:" + tmpCenterChangeMax + ",阈值:" + CenterDiff); FP.SetProgress1("最大中心变化率:", CenterDiff, tmpCenterChangeMax, ""); //将新的中心变为旧的中心,准备开始新一轮迭代 for (int i = 0; i < Kind; i++) { for (int band = 0; band < bandNum; band++) { KCenter[i].OldCenter[band] = KCenter[i].NewCenter[band]; } } tmpItera++; //判断是否继续循环 if (((MaxItera > 1) && (tmpItera > MaxItera)) || (tmpCenterChangeMax < CenterDiff) || (tmpItera > 10000)) { tmpContinue = false; } } FP.Finish(); DS.Dispose(); return(true); } catch (Exception err) { MessageBox.Show(err.ToString()); return(false); } }