基于OpenHarmony下的OpenCV库的交叉编译与实施
基于OpenHarmony下的OpenCV库的交叉编译与实施
项目概要
开发环境
-
平台:Windows 11、WSL Ubuntu 22.04
-
IDE :Deveco Studio 5.0.3.910/6.0 (6.0下没有API12的模拟器)
-
SDK:OpenHarmony 5.0.0 API12 FULL-SDK
-
开发模板:Native C++
描述
将OpenCV集成到开发环境,并使用C++实现调用摄像头并进行人脸检测(仅检测人脸位置)
需支持路径加载、Base64格式加载等
交叉编译OpenCV
环境准备
-
使用Ubuntu 22.04环境(或使用Windows下的WSL Ubuntu工具)
-
# 更新并获取编译依赖 sudo apt update sudo apt install build-essential cmake git pkg-config sudo apt install libgtk-3-dev libavcodec-dev libavformat-dev libswscale-dev sudo apt install python3-dev python3-numpy -
# 获取 opencv源码 版本控制为 4.8.0 git clone https://github.com/opencv/opencv.git cd opencv git checkout 4.8.0 -
# 获取 含有Linux 可用的native 工具的SDK 并解压 wget https://repo.huaweicloud.com/openharmony/os/5.0.0-Release/ohos-sdk-windows_linux-public.tar.gz mkdir -p OpenHarmony5.0-Linux-SDK tar -xzf ohos-sdk-windows_linux-public.tar.gz -C OpenHarmony5.0-Linux-SDK --strip-components=1 # 此压缩包为功能拆分压缩的分模块集合 需要二次解压 native cd ~/OpenHarmony5.0-Linux-SDK unzip native-linux-x64-5.0.0.71-Release.zip -d native-sdk -
现在的文件目录如下
~/ ├── opencv/ ├── OpenHarmony5.0-Linux-SDK │ └── native-sdk | └──native | ├── llvm/ ← Clang 工具链(Linux ELF) | ├── sysroot/ ← 目标系统头文件和库 | └── build/ ← CMake 工具链文件所在(注意:在 native/ 内!) | └──………… └── ... -
# 1. 检查 clang 是否为 Linux ELF(非 .exe) file ~/OpenHarmony5.0-Linux-SDK/native-sdk/native/llvm/bin/clang # 应输出类似: # ...: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), ... # 2. 检查 sysroot ls ~/OpenHarmony5.0-Linux-SDK/native-sdk/native/sysroot/usr/include/stdio.h # 3. 检查 CMake 工具链文件 ls ~/OpenHarmony5.0-Linux-SDK/native-sdk/native/build/cmake/ohos.toolchain.cmake # 如果都存在且 clang 是 ELF 文件,说明 交叉编译环境没有问题 -
此时,所有的交叉编译工具已经准备完成。
开始编译
-
因为默认编译会编译arm64 所以需要建立x86_64的Cmake配置
nano ~/opencv/ohos-x86_64.toolchain.cmake # ohos-x86_64.toolchain.cmake set(CMAKE_SYSTEM_NAME OHOS) set(CMAKE_SYSTEM_PROCESSOR x86_64) # 指定 OpenHarmony SDK 路径 set(OHOS_SDK_ROOT "$ENV{HOME}/OpenHarmony5.0-Linux-SDK/native-sdk/native") # 指定编译器 set(CMAKE_C_COMPILER ${OHOS_SDK_ROOT}/llvm/bin/x86_64-unknown-linux-ohos-clang) set(CMAKE_CXX_COMPILER ${OHOS_SDK_ROOT}/llvm/bin/x86_64-unknown-linux-ohos-clang++) # 指定 sysroot set(CMAKE_SYSROOT ${OHOS_SDK_ROOT}/sysroot) # 必要的编译标志 set(CMAKE_C_FLAGS "--target=x86_64-unknown-linux-ohos --sysroot=${CMAKE_SYSROOT} -D__MUSL__" CACHE STRING "") set(CMAKE_CXX_FLAGS "--target=x86_64-unknown-linux-ohos --sysroot=${CMAKE_SYSROOT} -D__MUSL__" CACHE STRING "") # 链接器标志 set(CMAKE_SHARED_LINKER_FLAGS "--rtlib=compiler-rt -fuse-ld=lld -Wl,--no-undefined" CACHE STRING "") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" CACHE STRING "") # 禁用 rpath set(CMAKE_SKIP_RPATH TRUE) -
然后执行交叉编译 (x86_64)
cd ~/opencv/build-x86 rm -rf * # 功能根据需要开启 此处禁用了图像处理功能!! cmake \ -DCMAKE_TOOLCHAIN_FILE=~/opencv/ohos-x86_64.toolchain.cmake \ -DCMAKE_INSTALL_PREFIX=~/opencv-ohos-x86_64 \ -DBUILD_SHARED_LIBS=ON \ -DBUILD_opencv_apps=OFF \ -DBUILD_TESTS=OFF \ -DBUILD_PERF_TESTS=OFF \ -DBUILD_EXAMPLES=OFF \ -DWITH_OPENMP=OFF \ -DWITH_IPP=OFF \ -DWITH_TBB=OFF \ -DWITH_EIGEN=OFF \ -DWITH_V4L=OFF \ -DWITH_GSTREAMER=OFF \ -DWITH_FFMPEG=OFF \ -DWITH_GTK=OFF \ -DOPENCV_GENERATE_PKGCONFIG=OFF \ -DWITH_JPEG=OFF \ -DWITH_PNG=OFF \ -DWITH_TIFF=OFF \ -DWITH_WEBP=OFF \ .. make -j$(nproc) make install -
编译完成后,需要查看生成的动态链接库依赖是否正确(否则会导致仅core导入时正常,导入其他时Napi构建失败)
cd ~/opencv-ohos-x86_64/lib readelf -d libopencv_core.so | grep NEEDED # 依次查看所有so # 如果出现[../../lib/libopencv_*.so] 则说明依赖异常 -
依赖异常时需要进行修复 使用以下代码
# 列出所有 .so 文件 for so in *.so; do echo "Fixing $so..." # 将 ../../lib/libxxx.so 替换为 libxxx.so patchelf --replace-needed ../../lib/libopencv_*.so libopencv_core.so "$so" 2>/dev/null || true # 可继续添加其他模块... done # 修复后重新验证 直到不再出现[../../lib/libopencv_*.so]类似情况 -
此时,交叉编译已完成,结果保存至
cd opencv-ohos-x86_64
补充
arm32 交叉编译说明
mkdir -p ~/opencv/build-arm32
cd ~/opencv/build-arm32
rm -rf *
# 创建arm32工具链文件
nano ~/opencv/ohos-arm32.toolchain.cmake
# ohos-arm32.toolchain.cmake
set(CMAKE_SYSTEM_NAME OHOS)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(OHOS_SDK_ROOT "$ENV{HOME}/OpenHarmony5.0-Linux-SDK/native-sdk/native")
set(CMAKE_C_COMPILER ${OHOS_SDK_ROOT}/llvm/bin/armv7-unknown-linux-ohos-clang)
set(CMAKE_CXX_COMPILER ${OHOS_SDK_ROOT}/llvm/bin/armv7-unknown-linux-ohos-clang++)
set(CMAKE_SYSROOT ${OHOS_SDK_ROOT}/sysroot)
set(CMAKE_C_FLAGS "--target=armv7-unknown-linux-ohos --sysroot=${CMAKE_SYSROOT} -D__MUSL__ -march=armv7-a -mfloat-abi=softfp -mfpu=neon" CACHE STRING "")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "")
set(CMAKE_SHARED_LINKER_FLAGS "--rtlib=compiler-rt -fuse-ld=lld -Wl,--no-undefined" CACHE STRING "")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" CACHE STRING "")
set(CMAKE_SKIP_RPATH TRUE)
然后执行编译
# 功能根据需要开启 此处禁用了图像处理功能!!
cmake \
-DCMAKE_TOOLCHAIN_FILE=~/opencv/ohos-arm32.toolchain.cmake \
-DCMAKE_INSTALL_PREFIX=~/opencv-ohos-arm32 \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_opencv_apps=OFF \
-DBUILD_TESTS=OFF \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_EXAMPLES=OFF \
-DWITH_OPENMP=OFF \
-DWITH_IPP=OFF \
-DWITH_TBB=OFF \
-DWITH_EIGEN=OFF \
-DWITH_V4L=OFF \
-DWITH_GSTREAMER=OFF \
-DWITH_FFMPEG=OFF \
-DWITH_GTK=OFF \
-DOPENCV_GENERATE_PKGCONFIG=OFF \
-DWITH_JPEG=OFF \
-DWITH_PNG=OFF \
-DWITH_TIFF=OFF \
-DWITH_WEBP=OFF \
..
make -j$(nproc)
make install
arm64 交叉编译说明
cd ~/opencv/build
rm -rf * # 清理中断产生的残余文件
# 功能根据需要开启 此处禁用了图像处理功能!!
cmake \
-DCMAKE_TOOLCHAIN_FILE=~/OpenHarmony5.0-Linux-SDK/native-sdk/native/build/cmake/ohos.toolchain.cmake \
-DPLATFORM=aarch64-linux-ohos \
-DCMAKE_INSTALL_PREFIX=~/opencv-ohos-arm64 \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_opencv_apps=OFF \
-DBUILD_TESTS=OFF \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_EXAMPLES=OFF \
-DWITH_OPENMP=OFF \
-DWITH_IPP=OFF \
-DWITH_TBB=OFF \
-DWITH_EIGEN=OFF \
-DWITH_V4L=OFF \
-DWITH_GSTREAMER=OFF \
-DWITH_FFMPEG=OFF \
-DWITH_GTK=OFF \
-DOPENCV_GENERATE_PKGCONFIG=OFF \
-DWITH_JPEG=OFF \
-DWITH_PNG=OFF \
-DWITH_TIFF=OFF \
-DWITH_WEBP=OFF \
..
集成到开发环境
前提
目前已有文件夹 opencv-ohos-x86_64 结构如下
.
├── LICENSE
├── bin
│ └── setup_vars_opencv4.sh
├── include
│ └── opencv4
├── lib
│ ├── cmake
│ ├── libopencv_calib3d.so
│ ├── libopencv_core.so
│ ├── libopencv_dnn.so
│ ├── libopencv_features2d.so
│ ├── libopencv_flann.so
│ ├── libopencv_gapi.so
│ ├── libopencv_highgui.so
│ ├── libopencv_imgcodecs.so
│ ├── libopencv_imgproc.so
│ ├── libopencv_ml.so
│ ├── libopencv_objdetect.so
│ ├── libopencv_photo.so
│ ├── libopencv_stitching.so
│ ├── libopencv_video.so
│ └── libopencv_videoio.so
├── out.txt
└── share
├── licenses
└── opencv4
开始集成
-
在 windows 下 打开 Deveco Studio,新建Native C++ 项目 选择API 为12 在设置将 OpenHarmony SDK 设置为 OpenHarmony 5.0.0 API12 FULL-SDK (假设叫Demo)
-
在 Demo/entry/src/main/cpp 下 新建 opencvLib/x86_64 文件夹 将 opencv-ohos-x86_64 中的lib和include文件夹复制进去 (其他架构同理)
-
打开 Demo/entry/build-profile.json5 修改下面的片段
{ "apiType": "stageMode", "buildOption": { "externalNativeOptions": { "abiFilters": ["x86_64","arm64-v8a"], //添加这一行 "path": "./src/main/cpp/CMakeLists.txt", "arguments": "", "cppFlags": "", } }, …… } -
打开 Demo/entry/src/main/cpp/napi_init.cpp 上方引入
#include <opencv2/opencv.hpp> -
打开 Demo/entry/src/main/cpp/CMakeLists.txt 将里面的内容替换为以下内容
cmake_minimum_required(VERSION 3.5.0) project(ceui) if(DEFINED PACKAGE_FIND_FILE) include(${PACKAGE_FIND_FILE}) endif() # ============================== # Step 1: Check OHOS_ARCH # ============================== if(NOT DEFINED OHOS_ARCH OR "${OHOS_ARCH}" STREQUAL "") message("OHOS_ARCH is not defined! Please specify with -DOHOS_ARCH=<arch> (e.g., x86_64, arm64-v8a)") else() message("Using architecture: ${OHOS_ARCH}") endif() # ============================== # Step 2: Set OpenCV paths (keep your structure) # ============================== set(OPENCV_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/libs/opencvLib/${OHOS_ARCH}) message("Checking OpenCV root: ${OPENCV_ROOT}") if(NOT EXISTS ${OPENCV_ROOT}) message("ERROR: OpenCV root directory does not exist: ${OPENCV_ROOT}") else() message("OpenCV root found: ${OPENCV_ROOT}") endif() set(OPENCV_INCLUDE_DIR ${OPENCV_ROOT}/include/opencv4) message("Checking OpenCV headers: ${OPENCV_INCLUDE_DIR}") if(NOT EXISTS ${OPENCV_INCLUDE_DIR}) message("ERROR: OpenCV include directory missing: ${OPENCV_INCLUDE_DIR}") else() message("OpenCV headers found: ${OPENCV_INCLUDE_DIR}") endif() set(OPENCV_LIB_DIR ${OPENCV_ROOT}/lib) message("Checking OpenCV lib dir: ${OPENCV_LIB_DIR}") if(NOT EXISTS ${OPENCV_LIB_DIR}) message("ERROR: OpenCV lib directory missing: ${OPENCV_LIB_DIR}") else() message("OpenCV lib dir found: ${OPENCV_LIB_DIR}") endif() # ============================== # Step 3: Base64 headers (optional) # ============================== set(Base64_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/tool) if(EXISTS ${Base64_INCLUDE_DIR}) message("Base64 headers: ${Base64_INCLUDE_DIR}") else() message("⚠ Base64 include dir not found (optional): ${Base64_INCLUDE_DIR}") endif() # ============================== # Step 4: Include directories # ============================== include_directories(${OPENCV_INCLUDE_DIR}) include_directories(${Base64_INCLUDE_DIR}) message("Header search paths configured") # ============================== # Step 5: Define OpenCV modules # ============================== set(OPENCV_MODULES opencv_core opencv_imgproc opencv_calib3d opencv_dnn opencv_features2d opencv_flann opencv_gapi opencv_highgui opencv_imgcodecs opencv_ml opencv_objdetect opencv_photo opencv_stitching opencv_video opencv_videoio ) message("OpenCV modules to link: ${OPENCV_MODULES}") # ============================== # Step 6: Create main library # ============================== add_library(entry SHARED napi_init.cpp) message("Main library 'entry' created") # ============================== # Step 7: Prepare build output directory # ============================== message("CMAKE_LIBRARY_OUTPUT_DIRECTORY = ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") set(BUILD_LIB_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) file(MAKE_DIRECTORY ${BUILD_LIB_DIR}) message("Build lib directory ensured: ${BUILD_LIB_DIR}") # ============================== # Step 8: Copy .so files with proper build rules # ============================== foreach(module IN LISTS OPENCV_MODULES) set(SRC_SO "${OPENCV_LIB_DIR}/lib${module}.so") set(DST_SO "${BUILD_LIB_DIR}/lib${module}.so") message("Processing module: ${module}") message(" Source: ${SRC_SO}") message(" Destination: ${DST_SO}") if(NOT EXISTS ${SRC_SO}) message(" ERROR: Missing source .so file!") else() message(" Source .so exists") endif() # 创建复制规则(Ninja 可以调度) add_custom_command( OUTPUT ${DST_SO} COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SRC_SO}" "${DST_SO}" DEPENDS "${SRC_SO}" COMMENT "Copying ${module} to build directory" VERBATIM ) # 创建一个自定义目标来触发复制 add_custom_target(copy_${module}_so ALL DEPENDS ${DST_SO}) # 创建 IMPORTED 库(用于链接) add_library(${module} SHARED IMPORTED GLOBAL) set_target_properties(${module} PROPERTIES IMPORTED_LOCATION "${DST_SO}" IMPORTED_NO_SONAME TRUE ) # 确保在构建 entry 前完成复制 add_dependencies(entry copy_${module}_so) endforeach() # ============================== # Step 9: Link dependencies # ============================== target_link_libraries(entry PUBLIC ace_napi.z uv pthread z m ${OPENCV_MODULES} ) message("Linking completed for 'entry' with all OpenCV modules") # ============================== # Final message # ============================== message("Successfully configured OpenCV integration for entry library") -
然后清理项目 注意删除.cxx文件夹 重新构建即可启动 此时,已可以在napi_init.cpp使用OpenCV库进行代码编辑。
更多推荐


所有评论(0)