【问题标题】:How does the formula of conversion HSV to RGB work?将 HSV 转换为 RGB 的公式是如何工作的?
【发布时间】:2020-11-28 03:13:49
【问题描述】:

首先,代码可以工作,但我想了解它是如何工作的(每一行)。

这是我的插值代码:

void colortemp(float temp, FILE* tempfile)
{
    //float temp_min = -138.0;
    //float temp_max = -37.0;
    //float color_min = 240.0;
    //float color_max = 0;

    if(temp < 135.0f)
    {
        temp = 135.0f;
    }
    /*
    if(temp > 310.0f)
    {
        temp = 310.0f;
    }*/
    float a = ( 0.0f - 240.0f) / ( 310.0f - 135.0f);
    float b = 240.0f - (a * 135.0f);
    float h = (temp * a ) + b;

    float S = 1.0f, V = 1.0f; //HSV
    float P, Q, T, fract;

    unsigned char pix[3];

    (h == 360.0f)?(h = 0.0f):(h /= 60.0f); --> WHY DIVIDE BY 60, NO MODULO ?
    fract = h - floor(h);

    P = (V*(1. - S))*255;
    Q = (V*(1. - S*fract))*255;
    T = (V*(1. - S*(1. - fract)))*255;

    V*=255;
    S*=255;

    if (0. <= h && h < 1.) //WHY WE USE BETWEEN TWO VALUES AND NOT EQUALS TO 1 FOR EXAMPLE
    {
            pix[0] = (int)V;
            pix[1] = (int)T;
            pix[2] = (int)P;
    }

    else if (1. <= h && h < 2.)
    {
            pix[0] = (int)Q;
            pix[1] = (int)V;
            pix[2] = (int)P;
    }

    else if (2. <= h && h < 3.)
    {
            pix[0] = (int)P;
            pix[1] = (int)V;
            pix[2] = (int)T;
    }

    else if (3. <= h && h < 4.)
    {
            pix[0] = (int)P;
            pix[1] = (int)Q;
            pix[2] = (int)V;
    }

    else if (4. <= h && h < 5.)
    {
            pix[0] = (int)T;
            pix[1] = (int)P;
            pix[2] = (int)V;
    }

    else if (5. <= h && h < 6.)
    {
            pix[0] = (int)V;
            pix[1] = (int)P;
            pix[2] = (int)Q;
    }

    else
    {
            pix[0] = 153;
            pix[1] = 20;
            pix[2] = 0;
    }

    fwrite(pix,1,3,tempfile);
}

我从posted on Stack Overflow 的人那里获取了代码并对其进行了编辑。但我不明白代码中的所有内容。

此外,在维基百科中(它是法语,t 是色调的 h)它是不同的,因为我们做模 6,我们看看我们是否等于 1、2、3 等,而不是如果我们在 1 之间或 2 例如。

如果我们查看 Wikipedia 中的算法,没有任何解释,所以我不知道它是如何工作的......

我们有色调,变量 h,我们将色调除以 60...为什么除以 60?

在维基百科的算法中,我们有一个变量 hi,我们在这里做一个模 6,为什么?

在我的代码中,发布它的人只是:fract = h - floor(h) 而不是fract = h - (floor(h) mod 6)

如果我们继续,我们会看到 3 个变量(在 Wikipedia 的算法中)l、m 和 n。这些是临时变量,但我们如何找到可以为我们提供这些变量结果的公式?

最后在我的代码中,如果我们介于两个值之间,则找到 RGB,并且在算法中找到它是否等于该值。为什么会有区别?

代码有效,但正如您所见,我对 HSV 到 RGB 转换背后的数学知识了解甚少。如果有人可以解释一下。

【问题讨论】:

  • 你除以 60 是为了将整个圆圈分成六个案例,由 if else 分别解决。您几乎不想将浮点数与相等性进行比较

标签: c++ math colors rgb hsv


【解决方案1】:

HSV 中的 h 是 0-359 度的角度。 HSV 到 RGB 转换根据 h 所在的 60 度扇区定义为 6 个单独的部分:h 在 0-59 之间是一种方式,h 在 60-119 之间是另一种方式,h 在 120-179 之间它被定义为第三种方式,依此类推。

因此,该过程的第一步是找出我们所在的扇区。一种方法是将 h 除以 60,得到的值介于 0 和 6(不包括)之间。取那个数字的 floor 会得到一个整数 0-5,它告诉你扇区。

如果 h 不在 0-359 之间,那你如何确定扇区呢?维基百科文章考虑到了这一点:这是您需要模运算符的地方。 c++ 程序不处理这种情况:它假定 h 已经在正确的范围内。

如果我们继续,我们会看到 3 个变量(在 Wikipedia 的算法中)l、m 和 n。这些是临时变量,但我们如何找到可以为我们提供这些变量结果的公式?

这是一个三线性插值,您可以从以下规则推导出:

  • value=0 应该是黑色
  • saturation=0 应该给出灰色:所有颜色分量都等于“值”
  • saturation=1 应该给出“完全饱和”的颜色。完全饱和的颜色是指最高 RGB 分量等于“值”的颜色
  • 色调应在两个颜色分量之间进行插值,而第三个是常数

为了更好地理解,请尝试以 HSV h=0 s=1 v=1 中的红色为例,看看更改每个组件 h s 和 v 如何影响结果。

最后在我的代码中,如果我们介于两个值之间,则找到 RGB,并且在算法中找到它是否等于该值。为什么会有区别?

这是因为 c++ 程序在步骤 1 中没有费心使用 floor 函数。h 不是整数 0-5,而是小数 0-6(不包括)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 2011-01-24
    • 1970-01-01
    • 2010-09-26
    • 2011-04-05
    • 2010-12-14
    相关资源
    最近更新 更多