Зависит ли метод canvas getImageData от машины/браузера?

Клиенту требовалась помощь с программой, которая извлекает доминирующий цвет изображения продукта.

Мне удалось быстро реализовать это на Javascript; Алгоритм, приведенный ниже, выбирает только центральный квадрат сетки 3x3 на изображении для быстрой оценки цвета футболки на изображении.

var image = new Image();
image.onload = function() {
    try {
        // get dominant color by sampling the central square of a 3x3 grid on image
        var dominantColor = getDominantColor();

        // output color
        $("#output").html(dominantColor);
    }
    catch(e) {
        $("#output").html(e);
    }
};
image.src = "sample_image.jpg";

function getDominantColor() {

    // Copy image to canvas
    var canvas = $("<canvas/>")[0];
    canvas.width = image.width;
    canvas.height = image.height;
    canvas.getContext("2d").drawImage(image, 0, 0);

    // get pixels from the central square of a 3x3 grid
    var imageData = canvas.getContext("2d").getImageData(canvas.width/3, canvas.height/3, canvas.width/3, canvas.height/3).data;

    var colorOccurrences = {};
    var dominantColor = "";
    var dominantColorOccurrence = 0;

    for(var i = 0; i < imageData.length; i += 4) {
        var red = imageData[i];
        var green = imageData[i+1];
        var blue = imageData[i+2];
        //var alpha = imageData[i+3]; // not required for this task

        var color = RGBtoHEX({"red": red, "green": green, "blue": blue});

        if(colorOccurrences[color] == undefined) {
            colorOccurrences[color] = 1;
        }
        else {
            colorOccurrences[color] ++;

            if(colorOccurrences[color] > dominantColorOccurrence) {
                dominantColorOccurrence = colorOccurrences[color];
                dominantColor = color;
            }
        }
    }

    return dominantColor;
}

function RGBtoHEX(rgb) {
    var hexChars = "0123456789ABCDEF";
    return "#"
            + (hexChars[~~(rgb.red/16)] + hexChars[rgb.red%16])
            + (hexChars[~~(rgb.green/16)] + hexChars[rgb.green%16])
            + (hexChars[~~(rgb.blue/16)] + hexChars[rgb.blue%16]);
}

Это изображение этот (предварительный просмотр ниже).

Образец продукта

Однако результаты, когда это изображение обрабатывается в приведенном выше коде, различаются на разных машинах/браузерах: #FF635E — это то, что я вижу на своем компьютере, работающем под управлением Windows7 и использующего Firefox 32. Мой клиент, работающий под управлением Mac, получает результат из #FF474B в Safari и #FF474C в Firefox 33.

Хотя результаты близки, почему в идеале они не совпадают? Действительно ли getImageData зависит от локальных настроек или данные JPG интерпретируются по-разному на разных компьютерах? ?

Изменить: это изображение не единичный случай. Такие цветовые вариации были замечены в диапазоне изображения, которое клиент запросил для обработки. Мой клиент и я получили разные результаты для одного и того же набора изображений.


person SNag    schedule 28.10.2014    source источник
comment
Это связано с тем, что браузер применяет цветовой профиль или нет, и какой именно.   -  person GameAlchemist    schedule 28.10.2014
comment
Может помочь сторонняя библиотека обработки изображений, которая не зависит от функциональности холста браузера. Например, это хорошая библиотека.   -  person Adam    schedule 06.08.2016
comment
Есть 2 других способа обойти это. Один из них — использовать WebGL и readPixels. WebGL может отключить коррекцию цвета, вызвав gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); перед загрузкой изображения. Затем вы должны рендерить его и считывать пиксели. Другой способ — использовать ImageBitmap API. К сожалению, похоже, что только Chrome поддерживает полную спецификацию с возможностью игнорировать преобразования цветового пространства.   -  person gman    schedule 10.12.2018


Ответы (1)


Да. Этот факт используется отпечатком холста:

Один и тот же элемент Canvas HTML5 может создавать исключительные пиксели в разных веб-браузерах, в зависимости от системы, в которой он был выполнен.

Это происходит по нескольким причинам: на уровне формата изображения — веб-браузеры используют разные механизмы обработки изображений, параметры экспорта, уровень сжатия, итоговые изображения могут иметь разные хэши, даже если они идеальны по пикселям; на уровне растрового изображения — операционные системы используют разные алгоритмы и настройки для сглаживания и субпиксельного рендеринга. Мы не знаем всех причин, но уже собрали более тысячи уникальных подписей.

person Oriol    schedule 28.10.2014
comment
Благодарю вас! Очень интересное понимание! - person SNag; 28.10.2014
comment
Я видел разные результаты на двух почти идентичных компьютерах с Windows 8 (на одном работает Chrome, на другом — последняя версия Opera [на основе Chromium]). - person o01; 02.12.2015