基本的に画像であるデータセットが与えられましたが、画像の各ピクセルは-1から1までの値として表されます。これらの-1から1のグレースケール値を取得し、MATLAB「Jet」カラースケール(赤-緑-青のカラーグラデーション)の関連RGB値にマップする必要があるアプリケーションを作成しています。
リニア値(-1から1など)を取得し、このスケールにマッピングする方法を誰かが知っている場合、私は興味があります。私は実際にこれにMATLABを使用していないことに注意してください(またはすることもできません)、グレースケール値を取得してJetグラデーションに配置するだけです。
ありがとう、アダム
これがあなたが探しているものであることを願っています:
double interpolate( double val, double y0, double x0, double y1, double x1 ) {
return (val-x0)*(y1-y0)/(x1-x0) + y0;
}
double blue( double grayscale ) {
if ( grayscale < -0.33 ) return 1.0;
else if ( grayscale < 0.33 ) return interpolate( grayscale, 1.0, -0.33, 0.0, 0.33 );
else return 0.0;
}
double green( double grayscale ) {
if ( grayscale < -1.0 ) return 0.0; // unexpected grayscale value
if ( grayscale < -0.33 ) return interpolate( grayscale, 0.0, -1.0, 1.0, -0.33 );
else if ( grayscale < 0.33 ) return 1.0;
else if ( grayscale <= 1.0 ) return interpolate( grayscale, 1.0, 0.33, 0.0, 1.0 );
else return 1.0; // unexpected grayscale value
}
double red( double grayscale ) {
if ( grayscale < -0.33 ) return 0.0;
else if ( grayscale < 0.33 ) return interpolate( grayscale, 0.0, -0.33, 1.0, 0.33 );
else return 1.0;
}
この縮尺がリンクした画像と100%同じかどうかはわかりませんが、非常によく似ているはずです。
[〜#〜] update [〜#〜]見つかったMatLabのJetパレットの説明に従ってコードを書き換えました ここ
double interpolate( double val, double y0, double x0, double y1, double x1 ) {
return (val-x0)*(y1-y0)/(x1-x0) + y0;
}
double base( double val ) {
if ( val <= -0.75 ) return 0;
else if ( val <= -0.25 ) return interpolate( val, 0.0, -0.75, 1.0, -0.25 );
else if ( val <= 0.25 ) return 1.0;
else if ( val <= 0.75 ) return interpolate( val, 1.0, 0.25, 0.0, 0.75 );
else return 0.0;
}
double red( double gray ) {
return base( gray - 0.5 );
}
double green( double gray ) {
return base( gray );
}
double blue( double gray ) {
return base( gray + 0.5 );
}
次の関数( Paul Bourke -Colour Ramping for Data Visualisation
):
/*
Return a RGB colour value given a scalar v in the range [vmin,vmax]
In this case each colour component ranges from 0 (no contribution) to
1 (fully saturated), modifications for other ranges is trivial.
The colour is clipped at the end of the scales if v is outside
the range [vmin,vmax]
*/
typedef struct {
double r,g,b;
} COLOUR;
COLOUR GetColour(double v,double vmin,double vmax)
{
COLOUR c = {1.0,1.0,1.0}; // white
double dv;
if (v < vmin)
v = vmin;
if (v > vmax)
v = vmax;
dv = vmax - vmin;
if (v < (vmin + 0.25 * dv)) {
c.r = 0;
c.g = 4 * (v - vmin) / dv;
} else if (v < (vmin + 0.5 * dv)) {
c.r = 0;
c.b = 1 + 4 * (vmin + 0.25 * dv - v) / dv;
} else if (v < (vmin + 0.75 * dv)) {
c.r = 4 * (v - vmin - 0.5 * dv) / dv;
c.b = 0;
} else {
c.g = 1 + 4 * (vmin + 0.75 * dv - v) / dv;
c.b = 0;
}
return(c);
}
あなたの場合、それを使用して範囲[-1,1]
を次のように色付けします(CコードからMATLAB関数に変換するのは簡単です):
c = GetColour(v,-1.0,1.0);
これにより、次の「ホットからコールド」カラーランプが生成されます。
基本的に、RGBカラーキューブの端から端までの青から赤への移動(シアン、緑、黄色を通過)を表し、このパスに沿って値を補間します。
これは、MATLABで使用される「Jet」カラーマップとは少し異なります。これは、私が知る限り、次のパスを通過します。
#00007F: dark blue
#0000FF: blue
#007FFF: Azure
#00FFFF: cyan
#7FFF7F: light green
#FFFF00: yellow
#FF7F00: orange
#FF0000: red
#7F0000: dark red
以下は、MATLABで行った比較です。
%# values
num = 64;
v = linspace(-1,1,num);
%# colormaps
clr1 = jet(num);
clr2 = zeros(num,3);
for i=1:num
clr2(i,:) = GetColour(v(i), v(1), v(end));
end
次に、以下を使用して両方をプロットします。
figure
subplot(4,1,1), imagesc(v), colormap(clr), axis off
subplot(4,1,2:4), h = plot(v,clr); axis tight
set(h, {'Color'},{'r';'g';'b'}, 'LineWidth',3)
これで、上記のCコードを変更し、提案されたストップポイントを使用して、ジェットカラーマップに似たものを実現できます(上記のプロットからわかるように、すべてR、G、Bチャネルで線形補間を使用します)...
他の答えは、補間を区分的線形関数として扱います。これは、補間にクランプされた三角基底関数を使用することにより簡素化できます。入力を閉じた単位間隔にマッピングするクランプ関数が必要です。
補間の基底関数:
その後、色は次のようになります。
これを-1から1にプロットすると、次のようになります。
これは、 この回答 で提供されているものと同じです。 効率的なクランプ実装を使用する :
double clamp(double v)
{
const double t = v < 0 ? 0 : v;
return t > 1.0 ? 1.0 : t;
}
値tが[-1、1]にあることを確認すると、ジェットの色は次のようになります。
double red = clamp(1.5 - std::abs(2.0 * t - 1.0));
double green = clamp(1.5 - std::abs(2.0 * t));
double blue = clamp(1.5 - std::abs(2.0 * t + 1.0));
clamp
の実装に関する上記のリンクに示されているように、コンパイラはブランチを最適化できます。コンパイラは、組み込み関数を使用してstd::abs
の符号ビットを設定し、別の分岐を削除することもできます。
同様の処理は、「ホットツーコールド」カラーマッピングに使用できます。この場合、基底関数と色関数は次のとおりです。
[-1、1]のホットツーコールドプロット:
明示的なブランチを削除すると、このアプローチはOpenGLシェーダープログラムとして実装するのに効率的です。 GLSLは、3Dベクトルで動作するabs
とclamp
の両方に組み込み関数を提供します。色の計算をベクトル化し、分岐よりも組み込み関数を優先すると、パフォーマンスが大幅に向上します。以下は、vec3
としてRGBジェットカラーを返すGLSLの実装です。基底関数は、tが他の例で使用されている範囲ではなく[0,1]になければならないように変更されていることに注意してください。
vec3 jet(float t)
{
return clamp(vec3(1.5) - abs(4.0 * vec3(t) + vec3(-3, -2, -1)), vec3(0), vec3(1));
}
HSLシステムの色相値があり、彩度と明度が暗黙的であるようです。インターネットでHSLからRGBへの変換を検索すると、多くの説明やコードなどが見つかります(ここに 1つのリンク があります)
ただし、特定のケースでは、すべての色の彩度を1に、明度を0.5にデフォルト設定すると仮定します。 RGB値を取得するために使用できる式は次のとおりです。
すべてのピクセルを想像すると、h
はデータから読み取った値です。
hue = (h+1.0)/2; // This is to make it in range [0, 1]
temp[3] = {hue+1.0/3, hue, hue-1.0/3};
if (temp[0] > 1.0)
temp[0] -= 1.0;
if (temp[2] < 0.0)
temp[2] += 1.0;
float RGB[3];
for (int i = 0; i < 3; ++i)
{
if (temp[i]*6.0 < 1.0)
RGB[i] = 6.0f*temp[i];
else if (temp[i]*2.0 < 1.0)
RGB[i] = 1;
else if (temp[i]*3.0 < 2.0)
RGB[i] = ((2.0/3.0)-temp[i])*6.0f;
else
RGB[i] = 0;
}
そして、RGB
のRGB値はすべて[0、1]の範囲にあります。元の変換はより複雑であることに注意してください。saturation = 1およびlightness = 0.5の値に基づいて単純化しました。
なぜこの式?こちらをご覧ください wikipedia entry