MATLAB против C++ против OpenCV - imresize

У меня есть следующий код MATLAB, который я хочу перенести в C++

Предполагать Gr 2d матрица и 1/newscale == 0.5

Gr = imresize(Gr, 1 / newScale);

в документации MATLAB:

B = imresize (A, scale) возвращает изображение B, масштаб которого умножен на размер A. Входное изображение A может быть оттенками серого, RGB или двоичным изображением. Если масштаб составляет от 0 до 1,0, B меньше, чем A. Если масштаб больше 1,0, B больше, чем A.

Так что это означает, что я получу 2D-матрицу == matrix_width/2 и matrix_height/2
Как рассчитать значения? По умолчанию в соответствии с документами приходят из кубической интерполяции для ближайшего 4X4.

Я не могу найти пример кода для C++, который делает то же самое. Можете ли вы предоставить ссылку на такой код?

Я также нашел эту функцию OpenCV,resize,

Это делает так же, как MATLAB?

2 ответа

Решение

Да, просто знайте, что MATLAB imresize сглаживание включено по умолчанию:

imresize(A,scale,'bilinear')

против того, что вы получите с cv::resize(), который не имеет сглаживания:

imresize(A,scale,'bilinear','AntiAliasing',false)

И, как упоминал Амро, по умолчанию в MATLAB bicubic, так что обязательно уточняйте.

Bilinear

Никаких модификаций кода не требуется для получения результатов сопоставления с билинейной интерполяцией.

Пример фрагмента OpenCV:

cv::Mat src(4, 4, CV_32F);
for (int i = 0; i < 16; ++i)
    src.at<float>(i) = i;

std::cout << src << std::endl;

cv::Mat dst;
cv::resize(src, dst, Size(0, 0), 0.5, 0.5, INTER_LINEAR);

std::cout << dst << std::endl;

Выход (OpenCV)

[0, 1, 2, 3;
  4, 5, 6, 7;
  8, 9, 10, 11;
  12, 13, 14, 15]

[2.5, 4.5;
  10.5, 12.5]

MATLAB

>> M = reshape(0:15,4,4).';
>> imresize(M,0.5,'bilinear','AntiAliasing',true)
ans =
                     3.125                     4.875
                    10.125                    11.875
>> imresize(M,0.5,'bilinear','AntiAliasing',false)
ans =
                       2.5                       4.5
                      10.5                      12.5

Обратите внимание, что результаты совпадают с отключенным сглаживанием.

Бикубическая разница

Однако между 'bicubic' а также INTER_CUBIC, результаты разные из-за схемы взвешивания! Смотрите здесь для деталей о математической разнице. Вопрос в interpolateCubic() функция, которая вычисляет коэффициенты кубического интерполанта, где постоянная a = -0.75 используется, а не a = -0.5 как в MATLAB. Однако, если вы редактируете imgwarp.cpp и измените код:

static inline void interpolateCubic( float x, float* coeffs )
{
    const float A = -0.75f;
    ...

чтобы:

static inline void interpolateCubic( float x, float* coeffs )
{
    const float A = -0.50f;
    ...

и пересобрать OpenCV (совет: отключите CUDA и модуль gpu на короткое время компиляции), тогда вы получите те же результаты:

MATLAB

>> imresize(M,0.5,'bicubic','AntiAliasing',false)
ans =
                    2.1875                    4.3125
                   10.6875                   12.8125

OpenCV

[0, 1, 2, 3;
  4, 5, 6, 7;
  8, 9, 10, 11;
  12, 13, 14, 15]
[2.1875, 4.3125;
  10.6875, 12.8125]

Подробнее о куб. ЗДЕСЬ.

В OpenCV вызов будет:

cv::Mat dst;
cv::resize(src, dst, Size(0,0), 0.5, 0.5, INTER_CUBIC);

Тогда вам, возможно, придется сделать некоторое сглаживание / размытие, чтобы эмулировать сглаживание, которое MATLAB также выполняет по умолчанию (см. Ответ @chappjc)

Другие вопросы по тегам