我有一个函数来计算给定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);
}
}发布于 2020-02-20 09:17:16
我不知道为什么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。
https://stackoverflow.com/questions/60314086
复制相似问题