I am using image-js.
I have looked at the documentation and I do not see a function called normalize or histogram stretching. However I do see some histogram functions. Can I use the histogram functions to do a normalization on a grayscale PNG array of height values?
The image array is values of heights from range 0 - 255 black being lowest height white highest. I am using this array to create a grayscale heightmap image.
Clarify:
By normalize I mean normalizing an image colors in this case the grayscale. Like this project but using image-js https://www.npmjs.com/package/@jimp/plugin-normalize
The normalization I want to accomplished is described in this GIMP doc and listed below
From GIMP: 8.10. Normalize
The Normalize command scales the brightness values of the active layer so that the darkest point becomes black and the brightest point becomes as bright as possible, without altering its hue. This is often a “magic fix” for images that are dim or washed out. “Normalize” works on layers from RGB, Grayscale, and Indexed images.
Histogram stretching involves modifying the brightness (intensity) values of pixels in the image according to some mapping function that specifies an output pixel brightness value for each input pixel brightness value. For a grayscale digital image, this process is straightforward.
A. For an RGB color space digital image, histogram stretching can be accomplished by converting the image to a hue, saturation, intensity (HSI) color space representation of the image and applying the brightness mapping operation to the intensity information alone.
Histogram stretching involves modifying the brightness (intensity) values of pixels in the image according to some mapping function that specifies an output pixel brightness value for each input pixel brightness value. For a grayscale digital image, this process is straightforward.
To adjust image contrast, use the mouse cursor to translate the Black Level and White Level sliders while observing results appearing in both the image and histogram windows. Alternatively, the blue arrow buttons can be activated with the mouse to incrementally move the sliders, either to the right or left.
Histograms of digital images provide a graphical representation of image contrast characteristics and are useful in evaluating contrast deficiencies such as low or high contrast, or inadequate dynamic range. Manipulation of the histogram can correct poor contrast and brightness to dramatically improve the quality of digital images.
Manipulation of the histogram can correct poor contrast and brightness to dramatically improve the quality of digital images. Histogram stretching involves modifying the brightness (intensity) values of pixels in the image according to some mapping function that specifies an output pixel brightness value for each input pixel brightness value.
Image normalization
is called also histogram stretching
Option 1
Use D3.js
instead of image-js for this task, like tis code from this source
<!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>
Option 2
From this histogram equalization algorithm for 8-bit single channel images taken from js-objectdetect you could write you own function using image-js, better explained in this answer
/**
* 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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With