opencv-mobile (迷你版opencv库)在 milkv-duo 上的移植和应用

TL;DR

编译打包好的zip包,拿来吧!

  1. 打开网站 GitHub - nihui/opencv-mobile: The minimal opencv for Android, iOS, ARM Linux, Windows, Linux, MacOS, WebAssembly
  2. 下载 opencv-mobile-4.8.0-milkv-duo.zip 解压
  3. cmake -DOpenCV_DIR=<解压目录>/lib/cmake/opencv4 + find_package(OpenCV) + target_link_libraries(your-program ${OpenCV_LIBS})

opencv-mobile

opencv-mobile 通过调整编译参数,删减部分opencv源码,来最小化编译的 opencv 库

  • 提供了 opencv 常用的功能,如读写图片,处理,矩阵操作等等
  • 版本与上游同步,无第三方依赖

在绝大多数情况下,以 1/10 的体积无痛替换官方 opencv,尤其适合对体积有特殊要求的移动端和嵌入式环境

相较于平头哥社区修改版 opencv,opencv-mobile 能直接享受上游的 RVV 优化,更原汁原味,也更轻量方便些

为 milkv-duo 编译 opencv-mobile

milkv-duo 小板子的硬件资源十分稀缺

  • 准备交叉编译工具链,比方说解压到 /home/nihui/osd/host-tools 这个目录后面要设置为环境变量
  • 下载最新opencv源码包
  • 下载opencv-mobile的编译配置和补丁

依据opencv-mobile的编译步骤,设置工具链目录环境变量,修改highgui模块,打补丁,配合 riscv64-unknown-linux-musl.toolchain.cmake

export RISCV_ROOT_PATH=/home/nihui/osd/host-tools/gcc/riscv64-linux-musl-x86_64

git clone https://github.com/nihui/opencv-mobile.git
cd opencv-mobile

wget -q https://github.com/opencv/opencv/archive/4.8.0.zip
unzip -q opencv-4.8.0.zip
cd opencv-4.8.0

truncate -s 0 cmake/OpenCVFindLibsGrfmt.cmake
rm -rf modules/gapi
patch -p1 -i ../opencv-4.8.0-no-rtti.patch
patch -p1 -i ../opencv-4.8.0-no-zlib.patch
patch -p1 -i ../opencv-4.8.0-link-openmp.patch
rm -rf modules/highgui
cp -r ../highgui modules/

mkdir build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../../toolchains/riscv64-unknown-linux-musl.toolchain.cmake -DCMAKE_C_FLAGS="-fno-rtti -fno-exceptions" -DCMAKE_CXX_FLAGS="-fno-rtti -fno-exceptions" -DCMAKE_INSTALL_PREFIX=install -DCMAKE_BUILD_TYPE=Release `cat ../../opencv4_cmake_options.txt` -DBUILD_opencv_world=OFF -DOPENCV_DISABLE_FILESYSTEM_SUPPORT=ON ..
make -j4
make install

经过一番编译,opencv-mobile 已经在 opencv-mobile/build/install 里面准备好了

特别提一下,编译过程中会看到 cmake 成功检查并开启了 riscv vector 支持,这对 milkv-duo 芯片是有加速效果的

-- Performing Test HAVE_CPU_RVV_SUPPORT (check file: cmake/checks/cpu_rvv.cpp)
-- Performing Test HAVE_CPU_RVV_SUPPORT - Success

opencv-mobile 附带的 toolchains/riscv64-unknown-linux-musl.toolchain.cmake 全局开启了 c906 内核相关的编译参数,并设置为 c906 优化,这些参数会自动应用在 opencv-mobile 所有模块的编译中,提供最佳性能

-- General configuration for OpenCV 4.8.0 =====================================
--   Version control:               v18-dirty
--
--   Platform:
--     Timestamp:                   2023-08-30T09:37:40Z
--     Host:                        Linux 6.4.12-200.fc38.x86_64 x86_64
--     Target:                      Linux riscv64
--     CMake:                       3.27.3
--     CMake generator:             Unix Makefiles
--     CMake build tool:            /usr/bin/gmake
--     Configuration:               Release
--
--   CPU/HW features:
--     Baseline:                    RVV
--       requested:                 DETECT
--
--   C/C++:
--     Built as dynamic libs?:      NO
--     C++ standard:                11
--     C++ Compiler:                /home/nihui/osd/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-g++  (ver 10.2.0)
--     C++ flags (Release):         -march=rv64gcv0p7_zfh_xtheadc -mabi=lp64d -mtune=c906   -fsigned-char -W -Wall -Wreturn-type -Wnon-virtual-dtor -Waddress -Wsequence-point -Wformat -Wformat-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -fvisibility-inlines-hidden -fopenmp -O3 -DNDEBUG  -DNDEBUG
--     C++ flags (Debug):           -march=rv64gcv0p7_zfh_xtheadc -mabi=lp64d -mtune=c906   -fsigned-char -W -Wall -Wreturn-type -Wnon-virtual-dtor -Waddress -Wsequence-point -Wformat -Wformat-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -fvisibility-inlines-hidden -fopenmp -g  -O0 -DDEBUG -D_DEBUG
--     C Compiler:                  /home/nihui/osd/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-gcc
--     C flags (Release):           -march=rv64gcv0p7_zfh_xtheadc -mabi=lp64d -mtune=c906   -fsigned-char -W -Wall -Wreturn-type -Waddress -Wsequence-point -Wformat -Wformat-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -fopenmp -O3 -DNDEBUG  -DNDEBUG
--     C flags (Debug):             -march=rv64gcv0p7_zfh_xtheadc -mabi=lp64d -mtune=c906   -fsigned-char -W -Wall -Wreturn-type -Waddress -Wsequence-point -Wformat -Wformat-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -fopenmp -g  -O0 -DDEBUG -D_DEBUG
--     Linker flags (Release):      -Wl,--gc-sections -Wl,--as-needed -Wl,--no-undefined
--     Linker flags (Debug):        -Wl,--gc-sections -Wl,--as-needed -Wl,--no-undefined
--     ccache:                      NO
--     Precompiled headers:         NO
--     Filesystem support is disabled
--     Extra dependencies:          /home/nihui/osd/host-tools/gcc/riscv64-linux-musl-x86_64/riscv64-unknown-linux-musl/lib64v0p7_xthead/lp64d/libgomp.so /home/nihui/osd/host-tools/gcc/riscv64-linux-musl-x86_64/sysroot/usr/lib64v0p7_xthead/lp64d/libpthread.a /home/nihui/osd/host-tools/gcc/riscv64-linux-musl-x86_64/riscv64-unknown-linux-musl/lib64v0p7_xthead/lp64d/libatomic.so dl m pthread rt
--     3rdparty dependencies:
--
--   OpenCV modules:
--     To be built:                 core features2d highgui imgproc photo video
--     Disabled:                    calib3d dnn flann imgcodecs ml objdetect stitching videoio world
--     Disabled by dependency:      -
--     Unavailable:                 java python2 python3 ts
--     Applications:                -
--     Documentation:               NO
--     Non-free algorithms:         NO
--
--   GUI:
--
--   Media I/O:
--     ZLib:                        build (ver )
--
--   Video I/O:
--     DC1394:                      NO
--
--   Parallel framework:            OpenMP
--
--   Other third-party libraries:
--     Lapack:                      NO
--     Custom HAL:                  NO
--
--   Python (for build):            /usr/bin/python2.7
--
--   Install to:                    /home/nihui/dev/opencv-mobile/opencv-4.8.0/build/install
-- -----------------------------------------------------------------

使用 opencv-mobile milkv-duo 优化版实现图片缩放

opencv-mobile 附带了一个示例项目,演示如何使用 opencv-mobile 实现加载图片,缩放,并保存图片

关键代码

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

int main()
{
    cv::Mat bgr = cv::imread("in.jpg", 1);
    cv::resize(bgr, bgr, cv::Size(200, 200));
    cv::imwrite("out.jpg", bgr);
    return 0;
}

cmake工程关键代码

project(opencv-mobile-test)
cmake_minimum_required(VERSION 3.5)

# opencv4 requires c++11
set(CMAKE_CXX_STANDARD 11)

# set OpenCV_DIR to where OpenCVConfig.cmake resides
find_package(OpenCV REQUIRED)

add_executable(opencv-mobile-test main.cpp)
target_link_libraries(opencv-mobile-test ${OpenCV_LIBS})

编译过程

export RISCV_ROOT_PATH=/home/nihui/osd/host-tools/gcc/riscv64-linux-musl-x86_64

cd opencv-mobile/test

mkdir build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../../toolchains/riscv64-unknown-linux-musl.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DOpenCV_DIR=/home/nihui/dev/opencv-mobile/opencv-4.8.0/build/install/lib/cmake/opencv4 ..
make

(可选) 编译出来的二进制可以用交叉编译工具链中的 strip 进一步瘦身

/home/nihui/osd/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-strip opencv-mobile-test

刷好最新的 milkv-duo 镜像,usb连接电脑,确认可以ssh后

复制 opencv-mobile-test 和一张测试图片 in.jpg 到 root@192.168.42.1:/root/

此时在 ssh shell 中执行会报错 libgomp.so.1 找不到

[root@milkv]~# ./opencv-mobile-test
Error loading shared library libgomp.so.1: No such file or directory (needed by ./opencv-mobile-test)
Error relocating ./opencv-mobile-test: GOMP_loop_nonmonotonic_dynamic_start: symbol not found
Error relocating ./opencv-mobile-test: omp_get_thread_num: symbol not found
Error relocating ./opencv-mobile-test: omp_set_dynamic: symbol not found
Error relocating ./opencv-mobile-test: GOMP_parallel: symbol not found
Error relocating ./opencv-mobile-test: GOMP_loop_nonmonotonic_dynamic_next: symbol not found
Error relocating ./opencv-mobile-test: GOMP_loop_end_nowait: symbol not found
Error relocating ./opencv-mobile-test: omp_get_max_threads: symbol not found
Error relocating ./opencv-mobile-test: GOMP_loop_nonmonotonic_dynamic_start: symbol not found
Error relocating ./opencv-mobile-test: omp_get_thread_num: symbol not found
Error relocating ./opencv-mobile-test: omp_set_dynamic: symbol not found
Error relocating ./opencv-mobile-test: GOMP_parallel: symbol not found
Error relocating ./opencv-mobile-test: GOMP_loop_nonmonotonic_dynamic_next: symbol not found
Error relocating ./opencv-mobile-test: GOMP_loop_end_nowait: symbol not found
Error relocating ./opencv-mobile-test: omp_get_max_threads: symbol not found

从工具链里找到 /home/nihui/osd/host-tools/gcc/riscv64-linux-musl-x86_64/sysroot/lib64v0p7_xthead/lp64d/libgomp.so.1.0.0 复制并更改文件名到 root@192.168.42.1:/root/libgomp.so.1,然后再加上 LD_LIBRARY_PATH 执行,程序正常结束退出

[root@milkv]~# LD_LIBRARY_PATH=. ./opencv-mobile-test

如果遇到 Killed 错误,说明图片分辨率太大,超出了 milkv-duo 内存可承受范围,换个小一些的图片就正常了

图片

最后,如果觉得有用请star和转发 :stuck_out_tongue:

3 Likes

非常好文章 :heart: 爱来自SOPHGO
@Lilp