it-swarm.com.ru

Самая быстрая формула, чтобы получить оттенок от RGB

Если вам даны значения красного, зеленого и синего в диапазоне от 0 до 255, каковы будут самые быстрые вычисления, чтобы получить только значение оттенка? Эта формула будет использоваться для каждого пикселя изображения 640x480 со скоростью 30 кадров в секунду (9,2 миллиона раз в секунду), так что помогает каждая небольшая часть оптимизации скорости.

Я видел другие формулы, но я не доволен тем, сколько шагов они включают. Я ищу фактическую формулу, а не встроенную библиотечную функцию.

20
user3161533
  1. Преобразовать значения RGB в диапазон 0-1, это можно сделать, разделив значение на 255 для 8-битной глубины цвета (r, g, b - заданные значения):

     R = r/255 = 0,09 
     G = g/255 = 0,38 
     B = b/255 = 0,46

  2. Найти минимальное и максимальное значения R, G и B.

  3. В зависимости от того, какой цветовой канал RGB является максимальным значением. Три разные формулы: If Red is max, then Hue = (G-B)/(max-min) If Green is max, then Hue = 2.0 + (B-R)/(max-min) If Blue is max, then Hue = 4.0 + (R-G)/(max-min)

Полученное значение оттенка необходимо умножить на 60, чтобы преобразовать его в градусы на цветовом круге. Если Hue становится отрицательным, вам нужно добавить 360 к, потому что круг имеет 360 градусов.

Вот полная статья .

23
Umriyaev

В дополнение к ответу Умрияева:

Если требуется только оттенок, то нет необходимости делить цвета в диапазоне 0–255 на 255.

Результат e.x. (green - blue) / (max - min) будет одинаковым для любого диапазона (конечно, если цвета находятся в одном диапазоне).

Вот пример Java для получения Hue:

public int getHue(int red, int green, int blue) {

    float min = Math.min(Math.min(red, green), blue);
    float max = Math.max(Math.max(red, green), blue);

    if (min == max) {
        return 0;
    }

    float hue = 0f;
    if (max == red) {
        hue = (green - blue) / (max - min);

    } else if (max == green) {
        hue = 2f + (blue - red) / (max - min);

    } else {
        hue = 4f + (red - green) / (max - min);
    }

    hue = hue * 60;
    if (hue < 0) hue = hue + 360;

    return Math.round(hue);
}

Правка: добавлена ​​проверка, если min и max одинаковы, так как в этом случае остальные вычисления не нужны, и чтобы избежать деления на 0 (см. Комментарии)

Правка: исправлена ​​ошибка Java

15
Zarokka
// convert rgb values to the range of 0-1
var h;
r /= 255, g /= 255, b /= 255;

// find min and max values out of r,g,b components
var max = Math.max(r, g, b), min = Math.min(r, g, b);

if(max == r){
    // if red is the predominent color
    h = (g-b)/(max-min);
}
else if(max == g){
    // if green is the predominent color
    h = 2 +(b-r)/(max-min);
}
else if(max == b){
    // if blue is the predominent color
    h = 4 + (r-g)/(max-min);
}

h = h*60; // find the sector of 60 degrees to which the color belongs
// https://www.pathofexile.com/forum/view-thread/1246208/page/45 - hsl color wheel

if(h > 0){
    // h is a positive angle in the color wheel
    return Math.floor(h);
}
else{
    // h is a negative angle.
    return Math.floor(360 -h);
}
2
DTNPerera

Вы должны указать, какой язык вам нужен. C #, Java и C очень разные языки и могут работать на разных платформах

640x480 не очень большой по сравнению с текущими распространенными разрешениями. Вы должны попробовать все возможные решения и тесты. Алгоритм, который имеет много шагов, не обязательно медленнее, чем более короткий, потому что цикл инструкций не является фиксированным, и есть много других факторов, влияющих на производительность, таких как когерентность кэша.

Для упомянутого выше алгоритма Умрияева вы можете заменить деление на 255 умножением на 1.0/255, что улучшит производительность с немного допустимой ошибкой.

В C вы можете сделать векторизацию, чтобы улучшить ее еще больше. Вы также можете использовать аппаратное ускорение.

В C # и Java у вас не так много вариантов. Вы можете запустить небезопасный код в C # или, если вы используете Mono, вы можете использовать векторный тип, который уже поддерживает SSE. В Java вы можете запустить нативный код через JNI

0
phuclv