Почему этот "фактор сокращения" делает "+ div/2",

Итак, я прохожу через "OpenCV 2 Computer Vision Application Programming Cookbook" Роберта Лаганиера. Вокруг страницы 42 речь идет об алгоритме сокращения изображения. Я понимаю алгоритм (я думаю), но я не понимаю, почему именно одна часть была введена. Думаю, я знаю, почему, но если я ошибаюсь, я бы исправился. Я собираюсь скопировать и вставить немного здесь:

"Цветные изображения состоят из трехканальных пикселей. Каждый из этих каналов соответствует значению интенсивности одного из трех основных цветов (красный, зеленый, синий). Поскольку каждое из этих значений является 8-битным беззнаковым char, общее количество цветов - 256x256x256, что больше 16 миллионов цветов. Следовательно, чтобы уменьшить сложность анализа, иногда полезно уменьшить количество цветов в изображении. Один простой способ достичь этой цели - просто подразделить пространство RGB в кубы одинаковых размеров. Например, если вы уменьшите количество цвета в каждом измерении на 8, то вы получите 32x32x32 цветов. Каждый цвет в исходном изображении затем назначается новое значение цвета в уменьшенном цветом изображении, которое соответствует значение в центре куба, к которому он принадлежит. Следовательно простой алгоритм сокращения цвета прост. Если N - сокращение фактор, то для каждого пикселя в изображении и для каждого канала этого пиксель, разделите значение на N (целочисленное деление, поэтому напоминание потерян). Затем умножьте результат на N, это даст вам кратное N только ниже значения входного пикселя. Просто добавьте N/2, и вы получить центральное положение интервала между двумя смежными кратные N. Если вы повторите этот процесс для каждого 8-битного канала значение, то вы получите в общей сложности 256/N x 256/N x 256/N возможных значения цвета. Как это сделать... Подпись нашего сокращения цвета функция будет выглядеть следующим образом: void colorReduce (cv:: Mat & image, int DIV = 64); Пользователь предоставляет изображение и уменьшение на канал фактор. Здесь обработка выполняется на месте, то есть пиксель значения входного изображения изменяются функцией. См. Там больше... раздел этого рецепта для более общей функции подпись с входными и выходными аргументами. Обработка просто сделанный путем создания двойного цикла, который охватывает все значения пикселей:"

void colorReduce(cv::Mat &image, int div=64) {
 int nl= image.rows; // number of lines
 // total number of elements per line
 int nc= image.cols * image.channels();
 for (int j=0; j<nl; j++)="" {="" get="" the="" address="" of="" row="" j="" uchar*="" data="image.ptr<uchar">(j);
 for (int i=0; i</nl;>
<p>Итак, я понимаю, как я уменьшаю значение 0: 255 пикселей на сумму div. Затем я теряю все остальное. Затем, умножая его на сумму div снова, мы масштабируем его обратно, чтобы сохранить его в диапазоне от 0: 255. <span> Почему мы затем добавляем (div/2) обратно в ответ?</span> Единственная причина, по которой я могу думать, это то, что это приведет к округлению округленных значений и некоторому округлению. Если вы не используете его, все ваши значения округляются вниз. Таким образом, он дает "лучшее" среднее значение?</p> <p>Не знаю, так что вы, ребята/девочки, думаете?</p>
2 ответа

Это делается для того, чтобы дать среднее значение границ квантования, а не пол его. Например, для N = 32 все данные от 0 до 31 будут давать 16 вместо 0.

Пожалуйста, проверьте следующее изображение или мой excel file.


Самый простой способ проиллюстрировать это - использовать пример.

Для простоты предположим, что мы обрабатываем один канал изображения. Есть 256 различных цветов, от 0 до 255. Мы также будем использовать N = 64 в нашем примере.

Используя эти числа, мы уменьшим количество цветов от 256 до 256/64 = 4. Давайте нарисуем график нашего цветового пространства:

|......|......|......|......| 
0 63 127 191 255

Пунктирная линия представляет наше цветовое пространство, исходящее от 0 до 255. Мы разделили этот интервал на 4 части, а разбиения представлены вертикальными линиями.

Чтобы уменьшить все 256 цветов до 4 цветов, мы собираемся разделить каждый цвет на 64 (потеря остатка), а затем снова умножить его на 64. Посмотрим, как это получится:

[0 , 63 ] / 64 * 64 = 0
[64 , 127] / 64 * 64 = 64
[128, 191] / 64 * 64 = 128
[192, 255] / 64 * 64 = 192

Как вы можете видеть, все цвета первой части стали 0, все цвета со второй части стали 64, третья часть 128, четвертая часть 192. Таким образом, наше цветовое пространство выглядит следующим образом:

|......|......|......|......| 
0 63 127 191 255
|______/|_____/|_____/|_____/ 
| | | |
0 64 128 192

Но это не очень полезно. Вы можете видеть, что все наши цвета наклонены слева от интервалов. Было бы более полезно, если бы они находились в середине интервалов. И поэтому мы добавляем 64/2 = 32 к значениям. Добавление половины длины интервала смещает цвета в центр интервалов. Это также то, что он говорит в книге: "Просто добавьте N/2 и вы получите центральное положение интервала между двумя соседними кратными N."

Итак, давайте добавим 32 к нашим значениям и посмотрим, как все выглядит:

[0 , 63 ] / 64 * 64 + 32 = 32
[64 , 127] / 64 * 64 + 32 = 96
[128, 191] / 64 * 64 + 32 = 160
[192, 255] / 64 * 64 + 32 = 224

И этот интервал выглядит так:

|......|......|......|......| 
0 63 127 191 255
\______/\_____/\_____/\_____/ 
 | | | |
 32 96 160 224

Это намного лучшее уменьшение цвета. Алгоритм уменьшил наше цветовое пространство от 256 до 4 цветов, и эти цвета находятся в середине интервалов, которые они уменьшают.

licensed under cc by-sa 3.0 with attribution.