コード例 #1
0
        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);
            }
        }
コード例 #2
0
        /// <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);
        }
コード例 #3
0
        /// <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);
            }
        }
コード例 #4
0
ファイル: BaseProcess.cs プロジェクト: TianChun525/RSImage
        /// <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);
            }
        }
コード例 #5
0
ファイル: BaseProcess.cs プロジェクト: TianChun525/RSImage
        /// <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);
            }
        }
コード例 #6
0
ファイル: BaseProcess.cs プロジェクト: TianChun525/RSImage
        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);
            }
        }
コード例 #7
0
ファイル: BaseProcess.cs プロジェクト: TianChun525/RSImage
        /// <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);
            }
        }
コード例 #8
0
ファイル: BaseProcess.cs プロジェクト: TianChun525/RSImage
        /// <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);
            }
        }
コード例 #9
0
ファイル: BaseProcess.cs プロジェクト: TianChun525/RSImage
        /// <summary>
        /// 波段直方图匹配。
        /// </summary>
        /// <param name="InputBand">输入的波段。</param>
        /// <param name="MatchBand">要匹配到的波段。</param>
        /// <param name="InputCumu">输入的数据集的累积概率表。</param>
        /// <param name="MatchingCumu">要匹配到的数据集的累积概率表。</param>
        /// <param name="OutDataType">输出的数据类型。</param>
        /// <returns>操作成功或失败。</returns>
        public static OSGeo.GDAL.Band HistogramMatching(OSGeo.GDAL.Band InputBand, OSGeo.GDAL.Band MatchBand, double[] InputCumu, double[] MatchingCumu, OSGeo.GDAL.DataType OutDataType)
        {
            try
            {
                int[] LUT   = HistogramMatching(InputCumu, MatchingCumu); //进行波段直方图匹配。
                int   xSize = InputBand.XSize;
                int   ySize = InputBand.YSize;

                OSGeo.GDAL.Driver Dri = OSGeo.GDAL.Gdal.GetDriverByName("Gtiff");
                if (Dri == null)
                {
                    throw new Exception("无法获取GDAL Driver。");
                }

                string tmpFileName = Tools.Common.GetTempFileName();

                FrmProgress FP = new FrmProgress()
                {
                    Text      = "正在进行波段直方图匹配...",
                    CanCancel = false,
                };

                Thread t = new Thread(() =>
                {
                    FP.ShowDialog();
                });
                t.SetApartmentState(ApartmentState.STA);
                t.Start();

                OSGeo.GDAL.Dataset DS = Dri.Create(tmpFileName, xSize, ySize, 1, OutDataType, null);
                FP.Output("已创建临时输出数据集\"" + tmpFileName + "\"");

                Tools.Common.GetMinimum(InputBand, out double inputBandMin);
                Tools.Common.GetMinimum(MatchBand, out double matchBandMin);

                for (int Row = 0; Row < ySize; Row++)
                {
                    FP.SetProgress1("正在处理:", Row + 1, ySize, "行");
                    double[] Values = new double[xSize];
                    //读取DN到数组
                    InputBand.ReadRaster(0, Row, xSize, 1, Values, xSize, 1, 0, 0);
                    for (int Col = 0; Col < xSize; Col++)
                    {
                        //防止GDAL自带方法算出的统计数据越界。
                        if ((Values[Col] - inputBandMin) <= 0)
                        {
                            Values[Col] = matchBandMin + LUT[0];
                            continue;
                        }
                        if ((Values[Col] - inputBandMin) >= LUT.Length - 1)
                        {
                            Values[Col] = matchBandMin + LUT[LUT.Length - 1];
                            continue;
                        }
                        Values[Col] = matchBandMin + LUT[(int)(Values[Col] - inputBandMin)];
                    }
                    //写结果到新栅格
                    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();
                return(DS.GetRasterBand(1));
            }
            catch (Exception err)
            {
                MessageBox.Show(err.ToString());
                return(null);
            }
        }
コード例 #10
0
        private void regression(List <Cell> samplePoints)
        {
            // 构造输入输出数据集

            // 样本数目
            int COUNT = samplePoints.Count;

            // 构造输入和输出数据集
            double[][] inputs  = new double[COUNT][];
            bool[]     outputs = new bool[COUNT];
            for (int i = 0; i < COUNT; i++)
            {
                Cell cell = samplePoints[i];
                int  pos  = cell.row * width + cell.col;
                inputs[i] = (from buffer in driveBuffers
                             select buffer[pos]).ToArray <double>();
                outputs[i] = cell.type;
            }



            var learner = new IterativeReweightedLeastSquares <Accord.Statistics.Models.Regression.LogisticRegression>()
            {
                Tolerance             = 1e-8, // 收敛参数
                Iterations            = 20,   // 最大循环数目
                Regularization        = 0,
                ComputeStandardErrors = true
            };


            Accord.Statistics.Models.Regression.LogisticRegression regression = learner.Learn(inputs, outputs);


            // 输出 odds
            StringBuilder strb = new StringBuilder();

            for (int i = 0; i <= inputs[0].Length; i++)
            {
                strb.AppendLine(" " + i + " : " + regression.GetOddsRatio(i));
            }
            updateConsoleEvent(strb.ToString());

            // 输出 weights
            StringBuilder strw = new StringBuilder();

            strw.AppendLine("权重系数:");
            strw.AppendLine("截距: " + regression.Intercept.ToString());
            var weights = regression.Weights;

            for (int i = 0; i < weights.Length; i++)
            {
                strw.AppendLine("权重" + (i + 1) + ":" + weights[i]);
            }
            updateConsoleEvent(strw.ToString());

            double[] result  = new double[width * height];
            double   minProp = double.MaxValue;

            double[] minInput = null;
            for (int row = 0; row < height; row++)
            {
                for (int col = 0; col < width; col++)
                {
                    int pos = row * width + col;
                    if (beginBuffer[pos] < 0 || !IsValid(pos))
                    {
                        result[pos] = this.landUse.NullInfo.LandUseTypeValue;
                        continue;
                    }
                    double[] input = (from buffer in driveBuffers
                                      select buffer[pos]).ToArray <double>();
                    double prop = regression.Probability(input);
                    if (prop < minProp)
                    {
                        minProp  = prop;
                        minInput = input;
                    }
                    result[pos] = prop;
                }
            }



            // 新建 GDAL dataset
            OSGeo.GDAL.Driver  driver  = OSGeo.GDAL.Gdal.GetDriverByName("GTIFF");
            OSGeo.GDAL.Dataset dataset = driver.Create(this.ResultLayerName, width, height, 1, OSGeo.GDAL.DataType.GDT_Float64, null);

            dataset.WriteRaster(0, 0, width, height, result, width, height, 1, new int[1] {
                1
            }, 0, 0, 0);
            dataset.FlushCache();
        }
コード例 #11
0
        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);
            }
        }
コード例 #12
0
        /// <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);
            }
        }
コード例 #13
0
ファイル: ImageSplit.cs プロジェクト: TianChun525/RSImage
        /// <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);
            }
        }
コード例 #14
0
        /// <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);
            }
        }
コード例 #15
0
        /// <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);
            }
        }