Раунд OpenCv после разделения

Глядя на следующий код

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).

Какая операция?

1

Решение

OpenCV использует режим округления «от половины до четного». Если дробь равна 0,5, она округляется до ближайшего четного целого числа. Вот почему 82,5 округляется до 82 и 69,5 до 70.

5

Другие решения

Это различие произошло для реализации 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 ( ссылка на сайт ).

1

Если вы хотите получить число с плавающей запятой, вам нужно использовать:

Mat G = (Green + Blue) / 2.0;

Просто с помощью:

Mat G = (Green + Blue) / 2;

Использует целочисленное деление, и поскольку в целом числе нет десятичных точек, оно усекается.

0