web-dev-qa-db-ja.com

RGBからHueを取得する最速の数式

0〜255の範囲の赤、緑、青の値が指定されている場合、色相値だけを取得するための最速の計算はどれですか。この式は、640 x 480画像のすべてのピクセルで30 fps(1秒あたり920万回)で使用されるため、少しずつ速度を最適化できます。

私は他の式を見ましたが、それらが関与するステップの数に満足していません。組み込みのライブラリ関数ではなく、実際の数式を探しています。

22
user3161533
  1. RGB値を0〜1の範囲に変換します。これは、8ビットの色深度で値を255で除算することで実行できます(r、g、b-は指定された値です)。

     R = r/255 = 0.09 
     G = g/255 = 0.38 
     B = b/255 = 0.46
  2. R、G、Bの最小値と最大値を見つけます。

  3. どのRGBカラーチャネルが最大値であるかによって異なります。 3つの異なる式は次のとおりです。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度であるためです。

記事全体 です。

29
Umriyaev

ウムリヤエフの答えに加えて:

色相のみが必要な場合、0〜255の範囲の色を255で分割する必要はありません。

E.xの結果。 (green - blue) / (max - min)は、すべての範囲で同じになります(もちろん、色が同じ範囲にある限り)。

Hueを取得するJavaの例:

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);
}

編集:最小値と最大値が同じ場合にチェックを追加しました。この場合、残りの計算は不要であり、0による除算を避けるためです(コメントを参照)

編集:修正Javaエラー

18
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は、現在の一般的な解像度に比べてそれほど大きくありません。考えられるすべてのソリューションとベンチマークを試す必要があります。命令サイクルが固定されておらず、キャッシュコヒーレンシなどのパフォーマンスに影響を与える他の多くの要因があるため、多くのステップを含むアルゴリズムは必ずしも短いものより遅くなるとは限りません。

上記のUmriyaevアルゴリズムでは、255による除算を1.0/255による乗算に置き換えることができます。これにより、少し許容できるエラーでパフォーマンスが向上します。

Cでは、ベクトル化してさらに改善できます。ハードウェアアクセラレーションを使用することもできます。

C#およびJavaでは、多くのオプションはありません。C#で安全でないコードを実行できます。Monoを使用している場合は、SSEを既にサポートしているベクタータイプを使用できます。 Java JNIを介してネイティブコードを実行できます

0
phuclv