MATLAB против C++ против OpenCV - imresize
У меня есть следующий код MATLAB, который я хочу перенести в C++
Предполагать Gr
2d матрица и 1/newscale == 0.5
Gr = imresize(Gr, 1 / newScale);
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)