Color scale in range
The logic is mostly clear, but it's not obvious exactly how to change to one of the other scales.  There's also a case where calling the function wrongly (with vmin==vmax), you'll divide by zero.  Although that's a bug in the calling code, it may be preferable to take a defensive line on this, and just return the middle value.

I'd be inclined to split this into two three parts:


scale the input value to the range [0,1]
split into one of the sub-ranges [0,0.5) or [0.5,1]
interpolate linearly between the two colours


I'll start with the last of those.  Assuming that the input is between 0 and 1, we can interpolate quite easily:

cv::Scalar get_colour(double alpha, const cv::Scalar&amp; c0, const cv::Scalar&amp; c1)
{
    return (1-alpha) * c0  +  alpha * c1;
}


How do we get that value between 0 and 1?  Steps 1 and 2 look like

cv::Scalar get_colour(double v, double vmin, double vmax)
{
    // clamp value within range
    v = v &lt;= vmin ? vmin
        : v &gt;= vmax ? vmax
        : v;

    const double alpha = (vmax &lt;= vmin)
        ? 0.5                   // avoid divide by zero
        : (v - vmin) / (vmax - vmin);

    static const cv::Scalar blue{ 255, 0, 0 };
    static const cv::Scalar white{ 255, 255, 255 };
    static const cv::Scalar red{ 0, 0, 255 };

    if (alpha &lt; 0.5) {
        return get_colour(alpha * 2, blue, white);
    } else {
        return get_colour(alpha * 2 - 1, white, red);
    }
}


Here, we have used constants for the colours in both parts of the gradient, meaning that if we want to change to different colours, there's only one place that needs changing.

I hope it's apparent with this change that we could make the interpolation into an object, with the range and colours being member data.  Depending on your application, that may be easier to work with than free functions with lots of parameters.