5

我正在使用image-js

我查看了文档,但没有看到称为标准化或直方图拉伸的函数。但是我确实看到了一些直方图函数。我可以使用直方图函数对高度值的灰度 PNG 数组进行归一化吗?

图像数组是从 0 到 255 范围内的高度值,黑色是最低高度,白色最高。我正在使用这个数组来创建一个灰度高度图图像。

阐明:

归一化是指在这种情况下对图像颜色进行归一化灰度。喜欢这个项目,但使用 image-js https://www.npmjs.com/package/@jimp/plugin-normalize

我想要完成的规范化在这个 GIMP 文档中描述并在下面列出

来自 GIMP: 8.10。标准化

Normalize命令缩放活动层的亮度值,使最暗点变为黑色,最亮点变得尽可能亮,而不会改变其色调。对于暗淡或褪色的图像,这通常是一种“神奇的修复”。“标准化”适用于 RGB、灰度和索引图像的图层。

4

1 回答 1

5

图像normalization也被称为histogram stretching

选项1

使用D3.js此任务代替 image-js,例如来自此源的 tis 代码

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
    canvas { width:50%; float: left}
  </style>
</head>
<body>
  <canvas id="imageOriginalCanvas"></canvas>
    <canvas id="imageCanvas"></canvas>

  <script>

    var cnv = document.getElementById('imageCanvas');
    var ctx = cnv.getContext('2d');
    var cnvori = document.getElementById('imageOriginalCanvas');
    var ctxori = cnvori.getContext('2d');

        var colorScales = {
      'linearBlackAndWhite': function(values){
        return d3.scale.linear()
          .domain(d3.extent(values))
          .range(['#000', '#fff']);
      },
      'histogramEqualize': function(values){
        var buckets = 100;
        var quantiles = d3.scale.quantile()
            .domain(values)
            .range(d3.range(buckets))
            .quantiles();

        var stopCount = quantiles.length;
        var linearScale = d3.scale.linear()
            .domain([0, stopCount - 1])
            .range([d3.rgb('rgb(0, 0, 0)'), d3.rgb('rgb(255, 255, 255)')]);
        
        var grayScale = d3.range(stopCount).map(function(d){
          return linearScale(d);
        });

        return d3.scale.linear().domain(quantiles).range(grayScale);
      }
    };

    var img = new Image;
    img.onload = function(){

      cnvori.width = cnv.width = img.width;
      cnvori.height = cnv.height = img.height;
      ctx.drawImage(img, 0, 0, img.width, img.height);
      ctxori.drawImage(img, 0, 0, img.width, img.height);

      var imgData = ctx.getImageData(0, 0, img.width, img.height);

      var rasterData = [];
      for(j = 0; j < (imgData.data.length / 4); j++){
        var brightness = d3.lab(d3.rgb(imgData.data[j * 4], 
                            imgData.data[j * 4 + 1], 
                            imgData.data[j * 4 + 2])).l;
        rasterData.push(imgData.data[j * 4] === 0 ? null : brightness);
      }

      var scale = colorScales.histogramEqualize(rasterData);

      for(j = 0; j < rasterData.length; j++){
        var scaledColor = scale(rasterData[j]);
        var color = d3.rgb(scaledColor);
        imgData.data[j * 4] = color.r;
        imgData.data[j * 4 + 1] = color.g;
        imgData.data[j * 4 + 2] = color.b;
        imgData.data[j * 4 + 3] = 255;
      }

      ctx.putImageData(imgData, 0, 0);
    };
    img.crossOrigin = '';   
    img.src = 'https://upload.wikimedia.org/wikipedia/commons/0/08/Unequalized_Hawkes_Bay_NZ.jpg';

  </script>
</body>

选项 2

从这个从js-objectdetect获取的 8 位单通道图像的直方图均衡算法中,您可以使用 image-js 编写自己的函数,在这个答案中有更好的解释

/**
* Equalizes the histogram of an unsigned 1-channel image with values
* in range [0, 255]. Corresponds to the equalizeHist OpenCV function.
*
* @param {Array} src 1-channel source image
* @param {Array} [dst] 1-channel destination image. If omitted, the
* result is written to src (faster)
* @return {Array} Destination image
*/
equalizeHistogram = function(src, dst) {
    var srcLength = src.length;
    if (!dst) { dst = src; }

    // Compute histogram and histogram sum:
    var hist = new Float32Array(256);
    var sum = 0;
    for (var i = 0; i < srcLength; ++i) {
        ++hist[~~src[i]];
        ++sum;
    }

    // Compute integral histogram:
    var prev = hist[0];
    for (var i = 1; i < 256; ++i) {
        prev = hist[i] += prev;
    }

    // Equalize image:
    var norm = 255 / sum;
    for (var i = 0; i < srcLength; ++i) {
        dst[i] = hist[~~src[i]] * norm;
    }
    return dst;
}
于 2021-10-18T22:48:11.107 回答