Frage

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.

War es hilfreich?

Lösung

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;

Andere Tipps

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!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top