Глядя на следующий код
Blue = channel[0];
Green = channel[1];
Red = channel[2];
Mat G = (Green + Blue) / 2;
где красный, зеленый и синий — каналы изображения. Там, где сумма зеленого и синего нечетна, иногда она делает раунд, а иногда «исправление». Например, для зеленого пикселя со значением 120 и синего 45 значение G равно 82 (так что оно занимает целую часть 82,5). В то время как в другом случае, когда Грин равен 106, а Синий — 33, я получаю значение 70 для этого элемента G (так что он делает раунд, потому что (33 + 106) / 2 = 69,5).
Какая операция?
OpenCV использует режим округления «от половины до четного». Если дробь равна 0,5, она округляется до ближайшего четного целого числа. Вот почему 82,5 округляется до 82 и 69,5 до 70.
Это различие произошло для реализации cvRound
в исходном коде opencv. Часть этого скопирована с GitHub ниже с добавленными комментариями.
int cvRound( float value )
{
double intpart, fractpart;
fractpart = modf(value, &intpart);
//for +ve numbers, when fraction is 0.5, odd numbers are rounded up
//and even numbers are rounded down
//and vice versa for -ve numbers
if ((fabs(fractpart) != 0.5) || ((((int)intpart) % 2) != 0))
return (int)(value + (value >= 0 ? 0.5 : -0.5));
else
return (int)intpart;
}
Я написал небольшой пример и отладил, чтобы увидеть, что вызывается взвешенное добавление матриц saturate_cast
( ссылка на сайт ) в коде opencv, который вызывается inturn cvRound
, Вы можете увидеть это на github ( ссылка на сайт ).
Если вы хотите получить число с плавающей запятой, вам нужно использовать:
Mat G = (Green + Blue) / 2.0;
Просто с помощью:
Mat G = (Green + Blue) / 2;
Использует целочисленное деление, и поскольку в целом числе нет десятичных точек, оно усекается.