HAL llamada a un método de flujo Análisis OpenCV
Hay algunos en OpenCV llamada HAL (Hardware de aceleración Layer) para lograr, y parece ver el hardware nombre asociado, de hecho, no todos pueden entenderse como más rápido que la versión convencional de la OCV suficiente. En este artículo se tiene que hacer es encontrar o cortado en sus procesos de implementación, las llamadas de función para obtener a través de toda la lógica. Esta será resize
, y GaussianBlur
dos funciones para analizar.
cambio de tamaño
En primer lugar localizar el módulo de imgproc imgproc.hpp archivo, que encontrar CV_EXPORTS_W void resize( InputArray src, OutputArray dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR );
métodos. Porque todos estamos referencia en el archivo de cabecera para su uso cuando fuera usado, que es una función de los archivos de cabecera es que utilizamos la función de importación. El OCV se dan cuenta que habrá una gran cantidad de ramas, es difícil de determinar, por lo que llegamos a es más conveniente de la entrada. Luego salta a la implementación de la función, si no soporta IDE, en una lata correspondiente resize.cpp misma función declaración de la función se realiza correspondiente a la función de búsqueda, de la siguiente manera:
void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
double inv_scale_x, double inv_scale_y, int interpolation )
{
CV_INSTRUMENT_REGION();
Size ssize = _src.size();
CV_Assert( !ssize.empty() );
if( dsize.empty() )
{
CV_Assert(inv_scale_x > 0); CV_Assert(inv_scale_y > 0);
dsize = Size(saturate_cast<int>(ssize.width*inv_scale_x),
saturate_cast<int>(ssize.height*inv_scale_y));
CV_Assert( !dsize.empty() );
}
else
{
inv_scale_x = (double)dsize.width/ssize.width;
inv_scale_y = (double)dsize.height/ssize.height;
CV_Assert(inv_scale_x > 0); CV_Assert(inv_scale_y > 0);
}
if (interpolation == INTER_LINEAR_EXACT && (_src.depth() == CV_32F || _src.depth() == CV_64F))
interpolation = INTER_LINEAR; // If depth isn't supported fallback to generic resize
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat() && _src.cols() > 10 && _src.rows() > 10,
ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation))
Mat src = _src.getMat();
_dst.create(dsize, src.type());
Mat dst = _dst.getMat();
if (dsize == ssize)
{
// Source and destination are of same size. Use simple copy.
src.copyTo(dst);
return;
}
hal::resize(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, inv_scale_x, inv_scale_y, interpolation);
}
Vemos que la realización función hace tres cosas:
- verificación de los parámetros
- Detectar si el soporte OpenCL o habilitar
- Utilizar el espacio de la función de cambio de tamaño para lograr hal
Hal saltar a lograr, que también se encuentra resize.cpp , parte del código:
namespace hal {
void resize(int src_type,
const uchar * src_data, size_t src_step, int src_width, int src_height,
uchar * dst_data, size_t dst_step, int dst_width, int dst_height,
double inv_scale_x, double inv_scale_y, int interpolation)
{
CV_INSTRUMENT_REGION();
CV_Assert((dst_width > 0 && dst_height > 0) || (inv_scale_x > 0 && inv_scale_y > 0));
if (inv_scale_x < DBL_EPSILON || inv_scale_y < DBL_EPSILON)
{
inv_scale_x = static_cast<double>(dst_width) / src_width;
inv_scale_y = static_cast<double>(dst_height) / src_height;
}
CALL_HAL(resize, cv_hal_resize, src_type, src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, inv_scale_x, inv_scale_y, interpolation);
//剩下部分代码是常规实现
Entonces vemos aquí tienen CALL_HAL
como una macro, saltar a su realización, que se encuentra hal_replacement.hpp ,
#define CALL_HAL(name, fun, ...) \
int res = __CV_EXPAND(fun(__VA_ARGS__)); \
if (res == CV_HAL_ERROR_OK) \
return; \
else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) \
CV_Error_(cv::Error::StsInternal, \
("HAL implementation " CVAUX_STR(name) " ==> " CVAUX_STR(fun) " returned %d (0x%08x)", res, res));
Podemos ver que en realidad se llama a la fun
función, si se devuelve la función CV_HAL_ERROR_OK
, será return
, obviamente, hal::resize
también vuelve, de lo contrario, las llamadas CV_Error_
, este no es el final del programa y hacer que la función anormal o como directa por terminada la función entera, más adelante entrar en detalles. De todos modos, el resultado es que usted va a hal::resize
continuar hacia abajo por debajo de la implementación convencional, y no sólo en esta macro return
.
Luego hal_replacement.hpp encontramos cv_hal_resize
define como
#define cv_hal_resize hal_ni_resize
A continuación, seguir buscando la hal_ni_resize
realización de
inline int hal_ni_resize(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, uchar *dst_data, size_t dst_step, int dst_width, int dst_height, double inv_scale_x, double inv_scale_y, int interpolation) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
Aquí, nos encontramos con que la función para volver directamente CV_HAL_ERROR_NOT_IMPLEMENTED
, de acuerdo con el análisis anterior, hal::resize
continuar hacia abajo. Por lo tanto, para lograr hal es ¿cómo es que cortar?
Hemos encontrado que, hal_replacement.hpp de CALL_HAL
la macro tiene una #include "custom_hal.hpp"
buena extraña, no incluir generalmente al principio de cosas? A continuación nos fijamos en este custom_hal.cpp , se encontró sólo una frase #include "carotene/tegra_hal.hpp"
, seguimos rastrear. Dado que las funciones analizadas anteriormente es hal_ni_resize
directamente la Búsqueda hal_ni_resize
, en vano. Luego tenemos la Búsqueda cv_hal_resize
, encontrado:
#undef cv_hal_resize
#define cv_hal_resize TEGRA_RESIZE
De repente sensación muy rápida, conseguir a través, y hasta aquí para cv_hal_resize
dar undef cabo, sabemos hal_replacement.hpp es #define cv_hal_resize hal_ni_resize
, y la ubicación del archivo desde el punto de vista, esto no def def ser, entonces redefinido TEGRA_RESIZE
, encontrar, hallazgo su definición:
#define TEGRA_RESIZE(src_type, src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, inv_scale_x, inv_scale_y, interpolation) \
( \
interpolation == CV_HAL_INTER_LINEAR ? \
CV_MAT_DEPTH(src_type) == CV_8U && CAROTENE_NS::isResizeLinearOpenCVSupported(CAROTENE_NS::Size2D(src_width, src_height), CAROTENE_NS::Size2D(dst_width, dst_height), ((src_type >> CV_CN_SHIFT) + 1)) && \
inv_scale_x > 0 && inv_scale_y > 0 && \
(dst_width - 0.5)/inv_scale_x - 0.5 < src_width && (dst_height - 0.5)/inv_scale_y - 0.5 < src_height && \
(dst_width + 0.5)/inv_scale_x + 0.5 >= src_width && (dst_height + 0.5)/inv_scale_y + 0.5 >= src_height && \
std::abs(dst_width / inv_scale_x - src_width) < 0.1 && std::abs(dst_height / inv_scale_y - src_height) < 0.1 ? \
CAROTENE_NS::resizeLinearOpenCV(CAROTENE_NS::Size2D(src_width, src_height), CAROTENE_NS::Size2D(dst_width, dst_height), \
src_data, src_step, dst_data, dst_step, 1.0/inv_scale_x, 1.0/inv_scale_y, ((src_type >> CV_CN_SHIFT) + 1)), \
CV_HAL_ERROR_OK : CV_HAL_ERROR_NOT_IMPLEMENTED : \
interpolation == CV_HAL_INTER_AREA ? \
CV_MAT_DEPTH(src_type) == CV_8U && CAROTENE_NS::isResizeAreaSupported(1.0/inv_scale_x, 1.0/inv_scale_y, ((src_type >> CV_CN_SHIFT) + 1)) && \
std::abs(dst_width / inv_scale_x - src_width) < 0.1 && std::abs(dst_height / inv_scale_y - src_height) < 0.1 ? \
CAROTENE_NS::resizeAreaOpenCV(CAROTENE_NS::Size2D(src_width, src_height), CAROTENE_NS::Size2D(dst_width, dst_height), \
src_data, src_step, dst_data, dst_step, 1.0/inv_scale_x, 1.0/inv_scale_y, ((src_type >> CV_CN_SHIFT) + 1)), \
CV_HAL_ERROR_OK : CV_HAL_ERROR_NOT_IMPLEMENTED : \
/*nearest neighbour interpolation disabled due to rounding accuracy issues*/ \
/*interpolation == CV_HAL_INTER_NEAREST ? \
(src_type == CV_8UC1 || src_type == CV_8SC1) && CAROTENE_NS::isResizeNearestNeighborSupported(CAROTENE_NS::Size2D(src_width, src_height), 1) ? \
CAROTENE_NS::resizeNearestNeighbor(CAROTENE_NS::Size2D(src_width, src_height), CAROTENE_NS::Size2D(dst_width, dst_height), \
src_data, src_step, dst_data, dst_step, 1.0/inv_scale_x, 1.0/inv_scale_y, 1), \
CV_HAL_ERROR_OK : \
(src_type == CV_8UC3 || src_type == CV_8SC3) && CAROTENE_NS::isResizeNearestNeighborSupported(CAROTENE_NS::Size2D(src_width, src_height), 3) ? \
CAROTENE_NS::resizeNearestNeighbor(CAROTENE_NS::Size2D(src_width, src_height), CAROTENE_NS::Size2D(dst_width, dst_height), \
src_data, src_step, dst_data, dst_step, 1.0/inv_scale_x, 1.0/inv_scale_y, 3), \
CV_HAL_ERROR_OK : \
(src_type == CV_8UC4 || src_type == CV_8SC4 || src_type == CV_16UC2 || src_type == CV_16SC2 || src_type == CV_32SC1) && \
CAROTENE_NS::isResizeNearestNeighborSupported(CAROTENE_NS::Size2D(src_width, src_height), 4) ? \
CAROTENE_NS::resizeNearestNeighbor(CAROTENE_NS::Size2D(src_width, src_height), CAROTENE_NS::Size2D(dst_width, dst_height), \
src_data, src_step, dst_data, dst_step, 1.0/inv_scale_x, 1.0/inv_scale_y, 4), \
CV_HAL_ERROR_OK : CV_HAL_ERROR_NOT_IMPLEMENTED :*/ \
CV_HAL_ERROR_NOT_IMPLEMENTED \
)
Esta definición de la macro, probablemente, hacer lo siguiente:
- Si la interpolación bilineal para el tipo de datos CV_8U y tamaño, y los canales de cumplir con ciertos requisitos, entonces
resizeLinearOpenCV
ir a cambiar el tamaño de verdad, y vuelveCV_HAL_ERROR_OK
, la interpolación bilineal no cumple con estas condiciones no son compatibles con el retornoCV_HAL_ERROR_NOT_IMPLEMENTED
, también lo hará tomarhal::resize
conciencia común - Si la interpolación ÁREA, la interpolación bilineal y la situación es similar
- Otro método de interpolación no es compatible actualmente. Pero desde el punto de vista de estos comentarios de código, los planes deben ser apoyados, pero ahora no sólo hacen un trabajo bueno.
Esta macro definiciones utilizadas observaron con poca frecuencia que el operador de coma para alcanzarCV_HAL_ERROR_OK
el valor de retorno, vuelve operador coma el valor de su extremo derecho.
Entonces podemos saltar aresizeLinearOpenCV
, yresizeAreaOpenCV
para realizar un seguimiento real de implementación rápida de.
Se puede encontrar, es que la clave para cortar la UNDEF y definir las operaciones.
Desenfoque gaussiano
Del mismo modo, en smooth.cpp que se encuentra en la cv_hal_gaussianBlur
aplicación del método, encontramos macro hal cv_hal_gaussianBlur
, y luego a la tegra_hal.hpp
de la Búsqueda cv_hal_gaussianBlur
y no se encontraron resultados. Esto demuestra hal rápido desenfoque gaussiano versión sin correspondiente. A continuación, busque la biblioteca caroteno ha relacionado desenfoque gaussiano código, parece que no debe tenerse en cuenta? Nos éxito el registro escribiendo demostración y el código fuente de una manera, encontramos que estas funciones no se dan cuenta que se llama, es en CALL_HAL
una macro para volver allí en CV_HAL_ERROR_NOT_IMPLEMENTED
el. Estas implementaciones deben ser lo suficientemente bueno, así que no se cortó en ella, espere lentamente por ella.