使用指南
算子注册
- 获取OpenCV源码。
- 解压OpenCV安装包。
tar -xvf opencv-4.9.0.tar.gz
- 注册kml_conv核心算子。
- opencv/3rdparty 目录下新增名为`kconv`的文件夹。
cd your_path_to_opencv/opencv-4.9.0/3rdparty mkdir -p kconv
- 拷贝头文件及相应依赖库至opencv/3rdparty/kconv文件夹下。
- 拷贝conv头文件。
cp cv.h your_path_to_opencv/opencv-4.9.0/3rdparty/kconv
- 拷贝CONV、BLAS、FFT依赖库。
cp libkconv_ext.so your_path_to_opencv/opencv-4.9.0/3rdparty/Kunpeng cp libkblas.so your_path_to_opencv/opencv-4.9.0/3rdparty/Kunpeng cp libkfftf.so your_path_to_opencv/opencv-4.9.0/3rdparty/Kunpeng cp libkffth.so your_path_to_opencv/opencv-4.9.0/3rdparty/Kunpeng
- 拷贝conv头文件。
- opencv/3rdparty/Kunpeng文件夹下新增头文件与源文件。
- 新增头文件kml_cv.hpp。
#ifndef KML_CV_HPP #define KML_CV_HPP #include <opencv2/core/base.hpp> #include "cv.h" #endif
- 新增源文件kml_cv.cpp。
#include "kml_cv.hpp"
- 新增头文件kml_cv.hpp。
- opencv/3rdparty/kconv文件夹下新增CMakeLists.txt。
project(kml_conv_ext CXX) add_library(kml_conv_ext STATIC kml_cv.cpp) target_link_libraries(kml_conv_ext ${CMAKE_CURRENT_SOURCE_DIR}/libkconv.so ${CMAKE_CURRENT_SOURCE_DIR}/libkblas_armv9s_v2403.so ${CMAKE_CURRENT_SOURCE_DIR}/libkfftf.so ${CMAKE_CURRENT_SOURCE_DIR}/libkffth.so) set(KAIL_HAL_VERSION "0.0.1" PARENT_SCOPE) set(KAIL_HAL_LIBRARIES "kml_conv_ext" PARENT_SCOPE) set(KAIL_HAL_HEADERS "kml_conv_ext.hpp" PARENT_SCOPE) set(KAIL_HAL_INCLUDE_DIRS "${CMAKE_BINARY_DIR}" PARENT_SCOPE) set_target_properties(kml_conv_ext PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(kml_conv_ext PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH}) if(NOT BUILD_SHARED_LIBS) ocv_install_target(kail_dnn_ext EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) endif() set(OPENCV_SRC_DIR "${CMAKE_SOURCE_DIR}") target_include_directories(kml_conv_ext PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${OPENCV_SRC_DIR}/modules/core/include) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/kml_cv.hpp" "${CMAKE_BINARY_DIR}/kml_cv.hpp" COPYONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cv.h" "${CMAKE_BINARY_DIR}/cv.h" COPYONLY) set_target_properties(${KML_LIBRARIES} PROPERTIES OUTPUT_NAME ${KML_LIBRARIES} DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" COMPILE_PDB_NAME ${KML_LIBRARIES} COMPILE_PDB_NAME_DEBUG "${KML_LIBRARIES}${OPENCV_DEBUG_POSTFIX}" ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} )
- 注册KML_CONV高性能filter2D核心算子。修改opencv-4.9.0/CMakeLists.txt 第965-995行。
set(OpenCV_HAL "kml_conv_ext") foreach(hal ${OpenCV_HAL}) if(hal STREQUAL "carotene") if(";${CPU_BASELINE_FINAL};" MATCHES ";NEON;") add_subdirectory(3rdparty/carotene/hal) ocv_hal_register(CAROTENE_HAL_LIBRARIES CAROTENE_HAL_HEADERS CAROTENE_HAL_INCLUDE_DIRS) if( NOT DEFINED CAROTENE_NEON_ARCH) set(CAROTENE_NEON_MSG "Auto detected") elseif( CAROTENE_NEON_ARCH GREATER 7) set(CAROTENE_NEON_MSG "Force ARMv8+") else() set(CAROTENE_NEON_MSG "Force ARMv7") endif() list(APPEND OpenCV_USED_HAL "carotene (ver ${CAROTENE_HAL_VERSION}, ${CAROTENE_NEON_MSG})") else() message(STATUS "Carotene: NEON is not available, disabling carotene...") endif() elseif(hal STREQUAL "openvx") add_subdirectory(3rdparty/openvx) ocv_hal_register(OPENVX_HAL_LIBRARIES OPENVX_HAL_HEADERS OPENVX_HAL_INCLUDE_DIRS) list(APPEND OpenCV_USED_HAL "openvx (ver ${OPENVX_HAL_VERSION})") elseif(hal STREQUAL "kml_conv_ext") add_subdirectory(3rdparty/kconv) ocv_hal_register(KAIL_HAL_LIBRARIES KML_HEADERS KML_INCLUDE_DIRS) list(APPEND OpenCV_USED_HAL "kml_conv_ext (ver ${KML_VERSION})") else() ocv_debug_message(STATUS "OpenCV HAL: ${hal} ...") ocv_clear_vars(OpenCV_HAL_LIBRARIES OpenCV_HAL_HEADERS OpenCV_HAL_INCLUDE_DIRS) find_package(${hal} NO_MODULE QUIET) if(${hal}_FOUND) ocv_hal_register(OpenCV_HAL_LIBRARIES OpenCV_HAL_HEADERS OpenCV_HAL_INCLUDE_DIRS) list(APPEND OpenCV_USED_HAL "${hal} (ver ${${hal}_VERSION})") endif() endif()
- opencv/3rdparty 目录下新增名为`kconv`的文件夹。
- 编译安装OpenCV。
cd your_path_to_opencv/opencv-4.9.0 mkdir -p build cd build cmake .. -DWITH_ADE=OFF -DCMAKE_INSTALL_PREFIX=your_path_to_install_opencv # cmake到build文件夹下 make -j make install # 安装到your_path_to_install_opencv中
OpenCV filter2D接口定义
完成上述KML_CONV filter2D算子注册后,用户可直接调用OpenCV filter2D接口完成滤波计算。
OpenCV filter2D使用指南:
https://docs.opencv.org/4.9.0/d4/d86/group__imgproc__filter.html
C++ interface:
void cv::filter2D( InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor = Point(-1,-1), double delta = 0, int borderType = BORDER_DEFAULT)
参数列表:
参数名 |
类型 |
描述 |
输入/输出 |
---|---|---|---|
src |
InputArray |
输入图像 |
输入 |
dst |
OutputArray |
输出图像 |
输出 |
int |
ddepth |
输出图像的深度 |
输入 |
kernel |
InputArray |
卷积核 |
输入 |
anchor |
Point |
卷积核锚点,表示滤波起始点在卷积核中的相对位置 默认值为为Point(-1,-1),表示滤波起始点位于卷积核中心 |
输入 |
delta |
0 |
偏置值,默认值为0 |
输入 |
int |
borderType |
边界填充类型,支持以下入参: BORDER_CONSTANT BORDER_REPLICATE BORDER_REFLECT BORDER_REFLECT_101 BORDER_REFLECT101 BORDER_DEFAULT(默认值) BORDER_ISOLATED |
输入 |
完成上述KML_CONV算子注册后的OpenCV 将新增对CV_16F图像深度filter2D计算的功能支持。下表是OpenCV filter2D接口所支持的输入图像深度、输出图像深度组合。
输入图像深度 |
输出图像深度 |
---|---|
CV_8U |
-1/CV_16S/CV_32F/CV_64F (输出图像深度值为-1时,表示输出图像深度与输入图像深度相同) |
CV_16U/CV_16S |
-1/CV_32F/CV_64F |
CV_32F |
-1/CV_32F |
CV_64F |
-1/CV_64F |
CV_16F |
-1/CV_16F |
当输入图像深度与输出图像深度均为CV_32F或CV_16F时,将调用KAIL_DNN高性能算子实现完成滤波计算。其他情况下,将调用OpenCV自身算子实现完成滤波计算。
依赖
#include <opencv2/imgproc/imgproc.hpp>
示例
C++ interface:
cv::Mat src = (cv::Mat_<float>(6, 6) << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36); cv::Mat kernel = (cv::Mat_<float>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); cv::Mat dst; cv::filter2D(src, dst, -1, kernel, cv::Point(-1, -1), 0, cv::BORDER_CONSTANT); /* * dst = [-4, -2, 0, 2, 4, 13; * 13, 8, 9, 10, 11, 25; * 25, 14, 15, 16, 17, 37; * 37, 20, 21, 22, 23, 49; * 49, 26, 27, 28, 29, 61; * 98, 70, 72, 74, 76, 115] */