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

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

<ol> <li><p>преобразовать значения rgb в диапазон 0-1, это можно сделать, разделив значение на 255 для 8-битной глубины цвета (r, g, b - заданные значения):<pre> r = r/255 = 0,09 g = g/255 = 0,38 b = b/255 = 0,46</pre></p></li> <li><p>найти минимальное и максимальное значения r, g и b.</p></li> <li>в зависимости от того, какой цветовой канал rgb является максимальным значением. три разные формулы: <code> 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)</code></li> </ol><p>полученное значение оттенка необходимо умножить на 60, чтобы преобразовать его в градусы на цветовом круге. если hue становится отрицательным, вам нужно добавить 360 к, потому что круг имеет 360 градусов.</p><p>вот <a href="http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/">полная статья</a> .</p>

<p>в дополнение к ответу умрияева:</p><p>если требуется только оттенок, то нет необходимости делить цвета в диапазоне 0–255 на 255.</p><p>результат e.x. <code>(green - blue) / (max - min)</code> будет одинаковым для любого диапазона (конечно, если цвета находятся в одном диапазоне).</p><p>вот пример java для получения hue:</p><pre class="lang-java prettyprint-override"><code>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); } </code></pre><p>правка: добавлена проверка, если min и max одинаковы, так как в этом случае остальные вычисления не нужны, и чтобы избежать деления на 0 (см. комментарии)</p><p>правка: исправлена ошибка java</p>

<pre class="lang-js prettyprint-override"><code>// 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); } </code></pre>

<p>вы должны указать, какой язык вам нужен. c #, java и c очень разные языки и могут работать на разных платформах</p><p>640x480 не очень большой по сравнению с текущими распространенными разрешениями. вы должны попробовать все возможные решения и тесты. алгоритм, который имеет много шагов, не обязательно медленнее, чем более короткий, потому что цикл инструкций не является фиксированным, и есть много других факторов, влияющих на производительность, таких как когерентность кэша.</p><p>для упомянутого выше алгоритма умрияева вы можете заменить деление на 255 умножением на <code>1.0/255</code>, что улучшит производительность с немного допустимой ошибкой.</p><p>в c вы можете сделать векторизацию, чтобы улучшить ее еще больше. вы также можете использовать аппаратное ускорение.</p><p>в c # и java у вас не так много вариантов. вы можете запустить небезопасный код в c # или, если вы используете mono, вы можете использовать векторный тип, который уже поддерживает sse. в java вы можете запустить нативный код через jni</p>