如何在Openlayers中对多个波段的Geotiff图像进行对比拉伸?

huangapple go评论61阅读模式
英文:

How to contrast stretch multiple bands Geotiff in Openlayers?

问题

In OpenLayers中,我想要实现通过Contrast Stretch Min和Max渲染多个波段的Geotiff,类似于QGIS或Geoserver使用SLD的方式。我已经查看了类似https://openlayers.org/en/latest/examples/cog-stretch.html和https://openlayers.org/en/latest/examples/cog-style.html的示例,但我没有找到我需要的方法。能帮助我吗?感谢任何线索或建议。谢谢。

英文:

In Openlayers,I want to realize render multiple bands Geotiff by Contrast Stretch Min and Max.
Like by QGIS or Geoserver using SLD:


<sld:RasterSymbolizer>
<sld:ChannelSelection>
  <sld:RedChannel>
    <sld:SourceChannelName>1</sld:SourceChannelName>
    <sld:ContrastEnhancement>
      <sld:Normalize>
        <sld:VendorOption name="minValue">-3.509304523468</sld:VendorOption>
        <sld:VendorOption name="maxValue">701.02770996094</sld:VendorOption>
        <sld:VendorOption name="algorithm">StretchToMinimumMaximum</sld:VendorOption>
      </sld:Normalize>
    </sld:ContrastEnhancement>
  </sld:RedChannel>
  <sld:GreenChannel>
    <sld:SourceChannelName>2</sld:SourceChannelName>
    <sld:ContrastEnhancement>
      <sld:Normalize>
        <sld:VendorOption name="minValue">12.172845840454</sld:VendorOption>
        <sld:VendorOption name="maxValue">20.350427627563</sld:VendorOption>
        <sld:VendorOption name="algorithm">StretchToMinimumMaximum</sld:VendorOption>
      </sld:Normalize>
    </sld:ContrastEnhancement>
  </sld:GreenChannel>
  <sld:BlueChannel>
    <sld:SourceChannelName>1</sld:SourceChannelName>
    <sld:ContrastEnhancement>
      <sld:Normalize>
        <sld:VendorOption name="minValue">-3.509304523468</sld:VendorOption>
        <sld:VendorOption name="maxValue">701.02770996094</sld:VendorOption>
        <sld:VendorOption name="algorithm">StretchToMinimumMaximum</sld:VendorOption>
      </sld:Normalize>
    </sld:ContrastEnhancement>
  </sld:BlueChannel>
</sld:ChannelSelection>
<sld:ContrastEnhancement/>
</sld:RasterSymbolizer>

I have seen the examples like https://openlayers.org/en/latest/examples/cog-stretch.html and
https://openlayers.org/en/latest/examples/cog-style.html.

But I dit not find the method which I need.
Can you help me ? Appreciate any clues or suggestions.Thank you.

答案1

得分: 0

有两种方法可以复制SLD:

要么让OpenLayers将其标准化并使用默认的RGBA样式。由于每个波段具有不同的最小和最大值,需要加载多个瓦片。

const rMin = -3.509304523468;
const rMax = 701.02770996094;

const gMin = 12.172845840454;
const gMax = 20.350427627563;

const bMin = -3.509304523468;
const bMax = 701.02770996094;

const source = new GeoTIFF({
  sources: [
    {
      bands: [1],
      min: rMin,
      max: rMax,
      url: url,
    },
    {
      bands: [2],
      min: gMin,
      max: gMax,
      url: url,
    },
    {
      bands: [3],
      min: bMin,
      max: bMax,
      url: url,
    },
  ],
});

const layer = new TileLayer({
  source: source,
});

或者自己在每个波段的最小值和最大值之间标准化,这应该更有效率。

function normalize(band, min, max) {
  return [
    '/',
    ['-', ['clamp', ['band', band], min, max], min],
    ['-', max, min],
  ];
}

const source = new GeoTIFF({
  normalize: false,
  sources: [
    {
      url: url,
    },
  ],
});

const layer = new TileLayer({
  source: source,
  style: {
    color: [
      'array',
      normalize(1, rMin, rMax),
      normalize(2, gMin, gMax),
      normalize(3, bMin, bMax),
      1,
    ],
  },
});
英文:

There are two ways to replicate that SLD

Either let OpenLayers normalize it and use the default RGBA style. As each band has different min and max values the url will need to be loaded multiple tiles

const rMin = -3.509304523468;
const rMax = 701.02770996094;

const gMin = 12.172845840454;
const gMax = 20.350427627563;

const bMin = -3.509304523468;
const bMax = 701.02770996094;

const source = new GeoTIFF({
  sources: [
    {
      bands: [1],
      min: rMin,
      max: rMax,
      url: url,
    },
    {
      bands: [2],
      min: gMin,
      max: gMax,
      url: url,
    },
    {
      bands: [3],
      min: bMin,
      max: bMax,
      url: url,
    },
  ],
});

const layer = new TileLayer({
  source: source,
});

Or normalize it between the min and max values for each band yourself, which should be more efficient

function normalize(band, min, max) {
  return [
    '/',
    ['-', ['clamp', ['band', band], min, max], min],
    ['-', max, min],
  ];
}

const source = new GeoTIFF({
  normalize: false,
  sources: [
    {
      url: url,
    },
  ],
});

const layer = new TileLayer({
  source: source,
  style: {
    color: [
      'array',
      normalize(1, rMin, rMax),
      normalize(2, gMin, gMax),
      normalize(3, bMin, bMax),
      1,
    ],
  },
});

huangapple
  • 本文由 发表于 2023年5月26日 11:16:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76337434.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定