c - RGB 到 HIS 为某些 RGB 值提供 NaN
问题描述
我有一个函数可以计算给定 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);
}
}
解决方案
我不明白为什么 NaN 会弹出
答案就在您的问题中:
因为参数略大于 1
在这种情况下,正确的问题是:
我应该如何确保参数
acos
不大于 1?
为此,您需要分析您的公式并查看问题出在哪里。和分工有可能sqrt
发挥作用。
最简单的 hack(可能对您的应用程序不利)是首先验证参数是否大于 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
。
推荐阅读
- jquery - 选中更改类复选框
- asp.net-mvc - 如何将下拉列表绑定到类型列表
使用实体框架 - android-emulator - 使用 API 级别 25 和 Android wifi 在模拟器上无法访问互联网
- python - python - 如何使用numpy for python仅获取数组中的奇数并将它们平方?
- python - ConfigParser.setdefault() 的使用
- android - 我可以从具有已知别名的密码(我不知道)受保护的密钥库中获取密钥吗
- visual-studio - SSRS 报告 - 报告服务 RDLC
- asp.net-core - 在 ASP.NET Core 中的电子邮件确认令牌过期后删除用户
- javascript - react-widget 组件未正确呈现
- python - 无法在 Pycharm 窗口中运行 .Robot 文件