Grayscale to Red-Green-Blue (MATLAB Jet) color scale

后端 未结 7 1863
囚心锁ツ
囚心锁ツ 2020-12-12 15:21

I was given a data set that is essentially an image, however each pixel in the image is represented as a value from -1 to 1 inclusive. I am writing an application that need

7条回答
  •  清歌不尽
    2020-12-12 15:47

    The other answers treat the interpolation as a piecewise linear function. This can be simplified by using a clamped triangular basis function for interpolation. We need a clamp function that maps its input to the closed unit interval:

    clamp(x)=max(0, min(x, 1))

    And a basis function for interpolation:

    N(t) = clamp(1.5 - |2t|)

    Then the color becomes:

    r = N(t - 0.5), g = N(t), b = N(t + 0.5)

    Plotting this from -1 to 1 gives:

    Which is the same as provided in this answer. Using an efficient clamp implementation:

    double clamp(double v)
    {
      const double t = v < 0 ? 0 : v;
      return t > 1.0 ? 1.0 : t;
    }
    

    and ensuring your value t is in [-1, 1], then jet color is simply:

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

    As shown in the above link on implementing clamp, the compiler may optimize out branches. The compiler may also use intrinsics to set the sign bit for std::abs eliminating another branch.

    "Hot-to-Cold"

    A similar treatment can be used for the "hot-to-cold" color mapping. In this case the basis and color functions are:

    N(t) = clamp(2 - |2t|)

    r(t)=N(t-1), g(t) = N(t), b(t) = N(t+1)

    And the hot-to-cold plot for [-1, 1]:

    OpenGL Shader Program

    Eliminating explicit branches makes this approach efficient for implementing as an OpenGL shader program. GLSL provides built-in functions for both abs and clamp that operate on 3D vectors. Vectorizing the color calculation and preferring built-in functions over branching can provide significant performance gains. Below is an implementation in GLSL that returns the RGB jet color as a vec3. Note that the basis function was modified such that t must lie in [0,1] rather than the range used in the other examples.

    vec3 jet(float t)
    {
      return clamp(vec3(1.5) - abs(4.0 * vec3(t) + vec3(-3, -2, -1)), vec3(0), vec3(1));
    }
    

提交回复
热议问题