3

範囲 (0.0、100.0) に約 1000 個の浮動小数点値があり、これらの値を色 (RGB) にマップしたいと考えています。これまでに行ったことは、1000 色 (RGB) 値でカラーマップを作成し、フロート値を使用してカラーマップにインデックスを付け、RGB 値を取得することです。

しかし、問題は、float 値を int にキャストしてからカラーマップのインデックスとして使用するため、精度が低下していることです。この float から rgb への変換を行う最良の方法は何ですか?

編集:

color color_list[100];
float float_values[1000]
for(i = 0 to 999)
{
   int colormap_idx = float_values[i];  // Note that the float is converted into an int
   color current_color = color_list[colormap_idx];
}
4

2 に答える 2

3

The total number of RGB values you can have is 256^3. It would be nice if you could utilize all of them, but sometimes it can be hard to come up with a nice intuitive mapping. Since there are a total possible of 256^4 floats (more than possible RGB values) you will lose precision no matter what you do, but you can still do much, much better than what you currently.

I don't know exactly what you are doing with the pre-defined color map, but consider defining only a few intermediate colors that correspond to a few intermediate floating values and interpolating each input floating point value. In the code below, fsample and csample are your corresponding points. For example:

fsample[0] = 0.0   -> csample[0] = (0, 0, 0)
fsample[1] = 0.25  -> csample[1] = (0, 0, 100)
fsample[2] = 0.5   -> csample[2] = (0, 170, 170)
fsample[3] = 0.75  -> csample[3] = (170, 170, 0)
fsample[4] = 1.0   -> csample[4] = (255, 255, 255)

This will allow you to cover a lot more ground in RGB space with floats, allowing a higher precision conversion, while still giving you some power to flexibly define intermediate colors. This is a fairly common method to convert grayscale to color.

There are a few optimizations and error checks you can apply to this code, but I left it unoptimized for the sake of clarity:

int N = float_values.size();
color colormap[N];
for(i = 0 to N)
{
    colormap[i] = RGBFromFloat(float_values[i], fsample, csample, num_samples);
}



color RGBFromFloat(float in, float fsample[], float csample[], num_samples)
{
    color out;

    // find the interval that the input 'in' lies in
    // this is a simple search on an ordered array...
    // consider replacing with a better algorithm for a large number of samples
    for(i = 0 to num_samples-1)
    {
        if(fsample[i] =< in && in < fsample[i+1])
        {
             out = interpolate(fsample[i], fsample[i+1], csample[i], csample[i+1], in);    
             break;
        }
    }
    return color;
}

color interpolate(float flow, float fhigh, color clow, color chigh, float in)
{
    float t = (in-flow)/(fhigh-flow);
    return clow*(1 - t) + chigh*t
}
于 2013-08-24T02:38:23.337 に答える
1

これが最善の方法であるかどうかはわかりませんが(最適性の基準が提供されていないため)、「精度が失われている」ということは、一度 int に変換すると、最大 100 の異なる色の組み合わせしかないことを意味します。次に、これを行うことができます:

// this code is C99

#define MAX_FLOAT_VAL 100.0
#define N_COLORS 2000
#define N_FLOAT_SAMPLES 1000

color color_list[N_COLORS];
float float_values[N_FLOAT_SAMPLES];

// the following loop must be placed in some function
for( int i = 0; i < N_FLOAT_SAMPLES; i++ )
{
    // the following assignment will map 
    // linearly a float in the range [0 ... MAX_FLOAT_VAL]
    // into an int in the range [0 ... (N_COLORS-1)]
    int colormap_idx = (float_values[i] / MAX_FLOAT_VAL) * (N_COLORS - 1);
    color current_color = color_list[colormap_idx];
    // ... do something with current_color ...
}

もちろんcolor_list、適切なアルゴリズムを使用してエントリを生成する必要があります (手作業で行うことはお勧めしません :-)。colormap_idx1 次元空間 ( の値) を 3 次元空間 (考えられるすべての RGB トリプルのセット)にマッピングしようとするため、より多くの「自由度」が必要になるため、これはまったく別の問題です。

PS:あなたが持っていると思われる要件は、マンデルブロ集合のグラフィック表現のようなフラクタルを色付けするために必要な計算を思い出させます。

お役に立てれば。

于 2013-08-24T01:31:29.390 に答える