MATLAB vs C ++ vs OpenCV – imresize

Tengo el siguiente código MATLAB que quiero transportar a C ++

Supongamos que Gr es 2d matrix y 1/newscale == 0.5

 Gr = imresize(Gr, 1 / newScale); 

en la documentación de MATLAB :

B = Imresize (A, scale) devuelve la imagen B que es una escala multiplicada por el tamaño de A. La imagen de entrada A puede ser una escala de grises, RGB o una imagen binaria. Si la escala está entre 0 y 1.0, B es menor que A. Si la escala es mayor que 1.0, B es mayor que A.

Esto significa que obtendré una matriz 2D == matriz_ ancho / 2 y matriz_alto / 2
¿Cómo calculo los valores? El valor predeterminado según los documentos proviene de la interpolación cúbica para el 4X4 más cercano.

No puedo encontrar un código de muestra para C ++ que haga lo mismo. ¿Puede proporcionar un enlace a dicho código?

También encontré esta función de OpenCV, resize .

¿Hace lo mismo que el de MATLAB?

Sí, solo tenga en cuenta que MATLAB’s imresize tiene anti-aliasing habilitado por defecto :

 imresize(A,scale,'bilinear') 

frente a lo que obtendrías con cv::resize() , que no tiene anti-aliasing:

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

Y como mencionó Amro, el valor predeterminado en MATLAB es bicubic , así que asegúrese de especificar.

Bilinear

No es necesario modificar el código para obtener resultados que coincidan con la interpolación bilineal.

Ejemplo de fragmento de OpenCV:

 cv::Mat src(4, 4, CV_32F); for (int i = 0; i < 16; ++i) src.at(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; 

Salida (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 

Tenga en cuenta que los resultados son los mismos con anti-aliasing desactivado.

Diferencia bicúbica

Sin embargo, entre 'bicubic' INTER_CUBIC 'bicubic' e INTER_CUBIC , ¡los resultados son diferentes a causa del esquema de ponderación! Vea aquí para detalles sobre la diferencia matemática. El problema está en la función interpolateCubic() que calcula los coeficientes del interpolador cúbico, donde se usa una constante de a = -0.75 lugar de a = -0.5 como en MATLAB. Sin embargo, si edita imgwarp.cpp y cambia el código:

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

a:

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

y reconstruir OpenCV (consejo: deshabilitar CUDA y el módulo gpu para un tiempo de comstackción corto), entonces obtienes los mismos resultados:

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] 

Más acerca de cubic AQUÍ .

En OpenCV, la llamada sería:

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

Es posible que deba suavizar / difuminar para emular el suavizado que MATLAB también realiza de manera predeterminada (consulte la respuesta de @chappjc )