Почему целочисленное изображение содержит дополнительную строку и столбец нулей?
Я изучаю, как использовать интегральные изображения с использованием opencv с Java API, и я создал тест, который отображает изображение в градациях серого до использования интегрального изображения и после его использования. изображение в градациях серого составляет 10 x 10, и когда я преобразовал его в целочисленное изображение, я нашел его 11 x 11 с дополнительными рядами нулей и дополнительным столбцом нулей, как показано ниже в выходных данных.
пожалуйста, дайте мне знать, почему целочисленное изображение содержит дополнительную строку и столбец нулей?
Код:
public static void main(String[] args) {
MatFactory matFactory = new MatFactory();
FilePathUtils.addInputPath(path_Obj);
Mat bgrMat = matFactory.newMat(FilePathUtils.getInputFileFullPathList().get(0));
Mat gsImg = SysUtils.rgbToGrayScaleMat(bgrMat);
Log.D(TAG, "MainClas", "gsImg.dump(): " + gsImg.dump());
Mat integralMat = new Mat();
Imgproc.integral(gsImg, integralMat, CvType.CV_32F);
Log.D(TAG, "MainClas", "sumMat.dump(): " + integralMat.dump());
}
OutPut:
1: Debug: MainClass -> MainClas: gsImg.dump(): [2, 1, 7, 5, 1, 11, 2, 7, 9, 11;
1, 2, 0, 0, 3, 20, 17, 5, 7, 8;
4, 8, 0, 2, 6, 30, 31, 5, 2, 2;
39, 43, 47, 44, 38, 62, 60, 37, 37, 39;
27, 29, 52, 52, 47, 75, 67, 59, 58, 63;
25, 21, 49, 51, 51, 78, 64, 66, 76, 80;
40, 36, 50, 46, 41, 56, 42, 45, 47, 49;
13, 17, 20, 15, 9, 20, 15, 19, 12, 11;
17, 13, 8, 5, 4, 7, 13, 20, 17, 17;
2, 4, 7, 9, 8, 6, 6, 7, 7, 8]
2: Debug: MainClass -> MainClas: sumMat.dump(): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 2, 3, 10, 15, 16, 27, 29, 36, 45, 56;
0, 3, 6, 13, 18, 22, 53, 72, 84, 100, 119;
0, 7, 18, 25, 32, 42, 103, 153, 170, 188, 209;
0, 46, 100, 154, 205, 253, 376, 486, 540, 595, 655;
0, 73, 156, 262, 365, 460, 658, 835, 948, 1061, 1184;
0, 98, 202, 357, 511, 657, 933, 1174, 1353, 1542, 1745;
0, 138, 278, 483, 683, 870, 1202, 1485, 1709, 1945, 2197;
0, 151, 308, 533, 748, 944, 1296, 1594, 1837, 2085, 2348;
0, 168, 338, 571, 791, 991, 1350, 1661, 1924, 2189, 2469;
0, 170, 344, 584, 813, 1021, 1386, 1703, 1973, 2245, 2533]
2 ответа
Есть 2 причины.
Первый из них чисто математический. Скажем, у вас есть ряд из 3 чисел (пикселей). Сколько возможных совокупных сумм он генерирует? ответ 4. Вы можете взять сумму 0 первых пикселей, 1 пикселя, 2 пикселей или всех 3 пикселей. Количество разных сумм составляет 4: (0,1,2,3). 4 - это точно 3+1. Эквивалентное изображение шириной 10 даст 11 сум для каждой строки, а размер 10x10 даст 11x11 сум.
Вторая причина заключается в простоте программирования. Интегральное изображение используется для вычисления суммы любого возможного прямоугольника на изображении всего за 4 действия (сумма 2 углов минус 2 других угла). Расстояние между углами в точности равно размеру прямоугольника, который вы хотите сложить. Например, если ваш прямоугольник имеет ширину 5 пикселей, вы получаете доступ к интегральному изображению по индексам im[i][j]
а также im[i][j+5]
, Однако, если ваш прямоугольник покрывает всю ширину или высоту изображения, это может привести к тому, что индекс выйдет из массива на 1. Именно поэтому целое изображение сохраняется в размере, который на 1x1 больше, чем изображение
Примечание: можно сохранить целостное изображение в массиве того же размера, что и изображение. Но тогда доступ к массиву будет намного медленнее, потому что нужно будет проверить индексы вне пределов. Доступ к интегральному изображению по индексу [-1] должен быть обнаружен и производить сумму 0, а доступ по индексу> ширина автоматически возвращает сумму всей ширины.
OpenCV реализовал большие интегральные изображения в основном из-за соображений скорости. Вычисление суммы прямоугольника требует только 4 + или - операции и 4 указателя на привязку. Не нужно проверять, что указатели попадают внутрь изображения, если у запрошенного прямоугольника есть правильные координаты внутри изображения
Существуют архитектуры, позволяющие получить доступ к массиву за пределами (по недопустимым индексам). Например, графические шейдеры. На этих архитектурах интегральное изображение может быть реализовано по-разному (размер NxN вместо N+1xN+1 или даже как пирамида сумм)
Можете ли вы вручную удалить лишний столбец из встроенного изображения в openCV?
Я настоятельно не рекомендую делать это! openCV имеет встроенный код для доступа к встроенному изображению определенным образом. Если вы удалите первый столбец, вы, вероятно, вызовете непредсказуемые вычисления.
Более того - как я объяснил, эта дополнительная строка и столбец увеличивают время выполнения в 10 раз быстрее (поскольку сложение и вычитание выполняются ЦП намного быстрее, чем условия if())
Обратите внимание, что целостное изображение - это совершенно другое представление исходного изображения. Он имеет не только другой размер (N+1)x(N+1), но и разную глубину. Ваше исходное изображение может быть в градациях серого (хранить один байт на пиксель), в то время как для интегрального изображения обычно требуется 4 байта на пиксель (поскольку для суммирования многих пикселей требуется значительно большее число). Так что в любом случае целостное изображение займет ~4 раза больше памяти, чем исходное изображение. Вы не можете разместить целое изображение в исходном изображении из-за разницы в BPP (бит на пиксель), так зачем беспокоиться о разной ширине и высоте
Это предполагаемое поведение. Обратите внимание, что интегральное изображение sum(X,Y)
в OpenCV определяется как ( см. документацию здесь) сумма пикселей исходного изображения с индексами LESS THAN, sum_(x < X, y < Y)
не меньше или равны таковым у интегрального изображения. таким образом sum(0,0)
например, будет сумма нулевых пикселей, определенная равной 0. Также итоговое итоговое изображение имеет на одну строку больше столбца и столбца, чем оригинал.
Причина этого заключается в том, что это облегчает вычисление сумм и т. Д. По блокам изображения и обрабатывает их единообразно, когда они включают верхнюю и / или левую границы.