RGB для HIS дает NaN для определенных значений RGB - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть функция, которая вычисляет оттенок для данного значения 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);
  }
}

1 Ответ

0 голосов
/ 20 февраля 2020

Я не могу понять, почему появляется 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.

...