How can I perform in-browser contrast stretching/normalization?

拈花ヽ惹草 提交于 2020-01-13 03:45:31

问题


I have jpegs on a webpage. I would like to perform client-side equalization (contrast stretching) on these images without browser plugins. I would also accept a solution for histogram equalization.

I currently use a poor approximation with a combination of two CSS filters (-webkit-filter: contrast() brightness()).

I am hoping to be able to accomplish this with something like processing.js or pixastic.


回答1:


I do not know of a library that contains an efficient histogram equalization method without introducing too much overhead. However, you could lump together your own implementation pretty fast.

You could start with this very optimized histogram equalization algorithm for 8-bit single channel images taken from js-objectdetect based on back-projection:

/**
* 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;
}

You could apply this method to the individual channels of an RGB image independently, but this will produce undesired results. Wikipedia describes a better method:

"However, if the image is first converted to another color space, Lab color space, or HSL/HSV color space in particular, then the algorithm can be applied to the luminance or value channel without resulting in changes to the hue and saturation of the image." (Wikipedia)

You then need an image and a canvas element:

context = canvas.getContext("2d");
context.drawImage(image, 0, 0, canvas.width, canvas.height);
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);

convertRGBAToHSL(imageData.data, hsl);
equalizeHistogram(hsl[2], hsl[2]);
convertHSLToRGBA(hsl, rgba);

How to perform RGBA <-> HSL conversation in Javascript is described here.

Keep in mind that there are 511 possible luminance values for an 8-bit RGB image using the referenced conversion method. Your histogram should then be an array of 511 instead of 256 values. You also would have to make sure that your luminance values are in the correct range, possibly by multiplying with 510 or by modifying the conversion method:

// r, g, b are in [0..255]
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var luminance = max + min;



回答2:


You can't do this directly on images as far as I know. You need to draw your image on a canvas, which an HTML5 element (some canvas tutorials) and then use an algorithm (one algorithm I could find) to manipulate each pixel's color separately in order to perform the contrast stretch.

Hope that helped, though!



来源:https://stackoverflow.com/questions/12114643/how-can-i-perform-in-browser-contrast-stretching-normalization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!