使用指南
KML_CONV只提供filter2D的核心算子实现,用户需按使用指南将核心算子注册进开源OpenCV,并调用开源OpenCV filter2d接口完成滤波计算。
算子注册
- 获取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.so ${CMAKE_CURRENT_SOURCE_DIR}/libkfftf.so ${CMAKE_CURRENT_SOURCE_DIR}/libkffth.so) set(KML_HAL_VERSION "0.0.1" PARENT_SCOPE) set(KML_HAL_LIBRARIES "kml_conv_ext" PARENT_SCOPE) set(KML_HAL_HEADERS "kml_conv_ext.hpp" PARENT_SCOPE) set(KML_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") ... 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(KML_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时,将调用KML_CONV高性能算子实现完成滤波计算。其他情况下,将调用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]
     */