0

私は問題があります。gdal_csharp.dllライブラリを使用してタイルにマップを切り取りました(gdal_retile.pyスクリプトを に書き直しましたC#)。1 つのケースを除いて、すべて正常に動作します。nodata値のある領域 (境界線上のタイル)を切り取り、それらをJPEGファイルとして保存すると、nodata領域は黒くなります (白が必要です) - 以下にタイルの例を示します。使用しようとしましtBand.SetNoDataValue(0);たが、黒いnot-nodata値(都市名、道路名など)に白い点が含まれることがあります...

タイルの例:タイル no1タイル no2

設定方法がわかりませんSetNoDataValue(/* what to write in here? */)... この問題を解決する別の方法があるのではないでしょうか?

これが私の方法です:

private void CreatePyramidTile(MosaicInfo levelMosaicInfo, int offsetX, int offsetY, int width, int height, string tileName, DataSource ogrds)
{
    double sx = levelMosaicInfo.ScaleX * _scaleFactor;
    double sy = levelMosaicInfo.ScaleY * _scaleFactor;

    AffineTransformDecorator dec =
        new AffineTransformDecorator(new[]
                                         {
                                             levelMosaicInfo.Ulx + offsetX*sx, sx, 0,
                                             levelMosaicInfo.Uly + offsetY*sy, 0, sy
                                         });

    Dataset sFh = levelMosaicInfo.GetDataSet((int) Math.Round(dec.Ulx),
                                             (int) Math.Round((dec.Uly + height*dec.ScaleY)),
                                             (int) Math.Round((dec.Ulx + width*dec.ScaleX)),
                                             (int) Math.Round(dec.Uly));

    if (sFh == null)
    {
        return;
    }

    if (ogrds != null)
    {
        var points = dec.PointsFor(width, height);
        AddFeature(ogrds, tileName, points);
    }

    DataType bt;
    if (_bandType == DataType.GDT_Unknown)
    {
        bt = levelMosaicInfo.BandType;
    }
    else
    {
        bt = _bandType;
    }

    double[] geotransform = { dec.Ulx, dec.ScaleX, 0, dec.Uly, 0, dec.ScaleY };
    int bands = levelMosaicInfo.Bands;

    Dataset tFh;
    if (_memDriver == null)
    {
        tFh = _driver.Create(tileName, width, height, bands, bt, _createOptions.ToArray());
    }
    else
    {
        tFh = _memDriver.Create(tileName, width, height, bands, bt, _createOptions.ToArray());
    }

    if (tFh == null)
    {
        throw new Exception("Creation failed, terminating gdal_tile.");
    }

    tFh.SetGeoTransform(geotransform);
    tFh.SetProjection(levelMosaicInfo.Projection);
// I think, the problem occurs in this loop; I tried to set nodata values
    for (int band = 1; band < bands + 1; band++)
    {
        Band tBand = tFh.GetRasterBand(band);

        if (levelMosaicInfo.Ct != null)
        {
            tBand.SetRasterColorTable(levelMosaicInfo.Ct);
        }
        tBand.SetRasterColorInterpretation(levelMosaicInfo.Ci[band - 1]);
//                tBand.SetNoDataValue(0);
    }

    var res = Gdal.ReprojectImage(sFh, tFh, null, null, _resamplingMethod, 0, 0, null, null);

    if (res != 0)
    {
        throw new Exception("Reprojection failed for " + tileName + ", error " + res + ".");
    }

    levelMosaicInfo.CloseDataSet(ref sFh);

    if (_memDriver != null)
    {
        Dataset ttFh = _driver.CreateCopy(tileName, tFh, 0, _createOptions.ToArray(), null, null);
        ttFh.Dispose();
    }

    tFh.Dispose();
}

[編集]
まだ同じ問題があります...ループを変更しました:

for (int band = 1; band < bands + 1; band++)
{
    Band tBand = tFh.GetRasterBand(band);
    tBand.Fill(255, 0);
    tBand.SetNoDataValue(255);

    if (levelMosaicInfo.Ct != null)
    {
        tBand.SetRasterColorTable(levelMosaicInfo.Ct);
    }
    tBand.SetRasterColorInterpretation(levelMosaicInfo.Ci[band - 1]);
}

これで、変換方法によって問題が発生する可能性があると思います。私が取得したデータは8-bitフォーマットされています - タイルを再投影した後、90% が黒色で塗りつぶされています。まず、ソース データを24-bitusingpct2rgb.pyスクリプトに変換します (に書き換えますC#)。

コードは次のとおりです。

public Dataset Convert8To24Bit()
{
    Gdal.AllRegister();

    string[] argv = Gdal.GeneralCmdLineProcessor(_args, 0);

    int i = 1;
    while (i < argv.Count())
    {
        string arg = argv.ElementAt(i);
        switch (arg)
        {
            case "-of":
                i++;
                _format = argv[i];
                break;
            case "-b":
                i++;
                _bandNumber = int.Parse(argv[i]);
                break;
            case "-rgba":
                _outBands = 4;
                break;
            default:
                if (string.IsNullOrEmpty(_srcFileName))
                {
                    _srcFileName = argv[i];
                }
                else
                {
                    Usage();
                }
                break;
        }
        i++;
    }

    string tmpFileName = _srcFileName + ".bak";

    // open source file
    Dataset srcDS = Gdal.Open(_srcFileName, Access.GA_ReadOnly);
    if (srcDS == null)
    {
        throw new Exception("Unable to open " + _srcFileName + ".");
    }

    Band srcBand = srcDS.GetRasterBand(_bandNumber);

    // ensure we recognise the driver
    Driver dstDriver = Gdal.GetDriverByName(_format);
    if (dstDriver == null)
    {
        throw new Exception("\"" + _format + "\" not registered.");
    }

    // build color table
    int[][] lookup = new int[4][];
    lookup[0] = Enumerable.Range(0, 256).ToArray();
    lookup[1] = Enumerable.Range(0, 256).ToArray();
    lookup[2] = Enumerable.Range(0, 256).ToArray();
    lookup[3] = new int[256];

    for (i = 0; i < 256; i++)
    {
        lookup[3][i] = 255;
    }

    ColorTable ct = srcBand.GetRasterColorTable();

    if (ct != null)
    {
        for (i = 0; i < Math.Min(256, ct.GetCount()); i++)
        {
            ColorEntry entry = ct.GetColorEntry(i);
            for (int j = 0; j < 4; j++)
            {
                switch (j)
                {
                    case 0:
                        lookup[j][i] = entry.c1;
                        break;
                    case 1:
                        lookup[j][i] = entry.c2;
                        break;
                    case 2:
                        lookup[j][i] = entry.c3;
                        break;
                    case 3:
                        lookup[j][i] = entry.c4;
                        break;
                }
            }
        }
    }
    else
    {
        return srcDS;
    }

    // create the working file
    string tifFileName = string.Empty;
    if (_format.Equals("GTiff", StringComparison.OrdinalIgnoreCase))
    {
        tifFileName = tmpFileName;
    }
    else
    {
        tifFileName = Path.Combine(Directory.GetParent(tmpFileName).Name, "temp.gif");
    }

//            Driver gTiffDriver = Gdal.GetDriverByName("GTiff");
    Driver gTiffDriver = Gdal.GetDriverByName("MEM");

    Dataset tifDS = gTiffDriver.Create(tifFileName, srcDS.RasterXSize, srcDS.RasterYSize, _outBands, DataType.GDT_Byte,
                                       new string[] {});

    // we should copy projection information and so forth at this point
    tifDS.SetProjection(srcDS.GetProjection());
    double[] geotransform = new double[6];
    srcDS.GetGeoTransform(geotransform);
    tifDS.SetGeoTransform(geotransform);

    if (srcDS.GetGCPCount() > 0)
    {
        tifDS.SetGCPs(srcDS.GetGCPs(), srcDS.GetGCPProjection());
    }

    // do the processing one scanline at a time
    for (int iY = 0; iY < srcDS.RasterYSize; iY++)
    {
        byte[] srcData = new byte[srcDS.RasterXSize*1];
        srcBand.ReadRaster(0, iY, srcDS.RasterXSize, 1, srcData, srcDS.RasterXSize, 1, 0, 0);

        for (int iBand = 0; iBand < _outBands; iBand++)
        {
            int[] bandLookup = lookup[iBand];

            int[] dstData = new int[srcData.Count()];
            for (int index = 0; index < srcData.Count(); index++)
            {
                byte b = srcData[index];
                dstData[index] = bandLookup[b];
            }

            tifDS.GetRasterBand(iBand + 1).WriteRaster(0, iY, srcDS.RasterXSize, 1, dstData,
                                                       srcDS.RasterXSize, 1, 0, 0);
        }
    }

//            if (tifFileName != _srcFileName)
//            {
//                tifDS = Gdal.Open(tifFileName, Access.GA_ReadOnly);
//                dstDriver.CreateCopy(_srcFileName, tifDS, 0, new string[] { }, null, null);;
//            }

    srcDS.Dispose();

    return tifDS;
}

クラス全体: GdalRetile.csおよびTiffConverter.cs

4

2 に答える 2

2

ラスターの場合、NoDataが常に尊重されるとは限りません。JPEGは、ほとんどのソフトウェアのNoDataメタデータを尊重しません。したがって、「0」のNoDataがある場合、これは黒のピクセル値として解釈される可能性があります。デフォルトでは、ラスターは0または黒で塗りつぶされます。NoDataが何であるかを再定義する必要があるだけです。白にし、ピクセルタイプをバイトにする場合は、255にする必要があります。

提案として、データセットを作成した後、データをロードする前に、次のことを試してください。

...
    Band tBand = tFh.GetRasterBand(band);
    tBand.Fill(255); // otherwise it is filled with 0
    tBand.SetNoDataValue(255); // set metadata
...
于 2012-10-07T20:43:06.860 に答える
0

わかりました、私はこれに対する解決策を見つけました! TEMP結果タイルの背景である白で画像を塗りつぶしただけです。

メソッドの変更GetDataSet():

Dataset resultDS = _tempDriver.Create("TEMP", resultSizeX, resultSizeY, _bands, _bandType, new string[] { });

上記の行は次のように変更されました。

Dataset resultDS = _tempDriver.Create("TEMP", resultSizeX, resultSizeY, _bands, _bandType, new string[] { });
for (int i = 1; i < _bands + 1; i++)
{
    Band band = resultDS.GetRasterBand(i);
    band.Fill(255, 0);
}
于 2012-10-08T11:12:37.920 に答える