【问题标题】:RGB to HIS giving NaN for certain RGB valuesRGB 到 HIS 为某些 RGB 值提供 NaN
【发布时间】:2020-06-04 10:24:06
【问题描述】:

我有一个函数可以计算给定 rgb 值的色调。对于某些值,acos 返回 NaN,因为该参数略大于 1。这段代码遵循我在网上找到的大多数公式,但我不知道为什么会弹出 NaN。

例子是

40 28 28
40 28 28
40 28 28
49 25 25
46 34 34
40 28 28
42 24 24
42 24 24
40 22 22
40 22 22
#include <math.h>

double hue(unsigned char r, unsigned char g, unsigned char b) {
  double rn = (double) r / (r + g + b);
  double gn = (double) g / (r + g + b);
  double bn = (double) b / (r + g + b);

  if (rn == gn && gn == bn) {
    return 0;
  }

  double h = acos((rn - gn + rn - bn) / (2.0 * sqrt((rn - gn) * (rn - gn) + (rn - bn) * (gn - bn))));

  // issue with the argument of acos being just slightly bigger than 1. Approximate to 0
  if (isnan(h)) {
    h = 0;
  }

  if (b > g) {
    return (2 * M_PI - h) * (180.0 / M_PI);
  } else {
    return h * (180.0 / M_PI);
  }
}

【问题讨论】:

    标签: c nan


    【解决方案1】:

    我不明白为什么会出现 NaN

    答案就在你的问题中:

    因为参数比1略大


    在这种情况下正确的问题是:

    我应该如何确保acos 的参数不大于1?

    为此,您需要分析您的公式并查看问题出在哪里。 sqrt 和部门有可能在起作用。

    最简单的技巧(可能对您的应用程序不利)是首先验证参数是否大于 1,如果是,则将其截断为 1。


    请注意,您在计算 rn、gn、bn 时会失去额外的精度。 sqrt 的参数最好计算为:

    a = (r-g)*(r-g)+(r-b)*(g-b);
    b = (r+g+b)*(r+g+b);
    argument = a/b;
    

    试试看会发生什么。


    还有顺序

    // issue with the argument of acos being just slightly bigger than 1. Approximate to 0
    if (isnan(h)) {
        h = 0;
    }
    

    应该在调用acos之前使用,并使用acos的(预先计算的)参数而不是计算的h。

    【讨论】:

    • 最终将参数截断为 1。我认为没有办法解决浮点问题。
    • “修复”可能是不可能的,但通过最小化错误来改善结果(有时)是可能的。
    猜你喜欢
    • 2012-02-14
    • 2012-11-15
    • 2016-02-17
    • 1970-01-01
    • 2021-10-29
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    相关资源
    最近更新 更多