当前位置: 首页 > news >正文

Linux下编译并打包MNN项目迁移至其他设备

1. 构建项目结构

该项目是利用MNN框架对MTCNN网络进行推理,实现对目标的实时检测

运行环境:Linux

相关库:opencv,MNN 

先给出项目的总体结构,如下:

mtcnn_mnn/
├── include/
│   ├── opencv2/              # OpenCV 的头文件
│   ├── MNN/                  # MNN 的头文件
│   └── mtcnn.h               # 项目内部的头文件
├── lib/
│   ├── libopencv_core.so     # OpenCV 的动态库
│   ├── libopencv_imgproc.so
│   ├── libopencv_highgui.so
│   ├── libopencv_videoio.so
│   ├── libopencv_imgcodecs.so
│   └── libMNN.so             # MNN 的动态库
├── src/                      # 项目源文件
│   ├── main.cpp
│   └── mtcnn.cpp
├── Makefile
└── detection                 # 生成的可执行文件

    接下来我们将逐一进行构建

    如果需要将项目迁移到其他 Linux 设备上运行,必须确保以下内容被正确迁移:

    (1) 头文件

    ① OpenCV 的头文件

    路径:/home/opencv-4.10.0/build_shared/include/opencv4/opencv2/

    需要复制整个 opencv2 文件夹到项目的 include/ 目录下:

    cp -r /home/opencv-4.10.0/build_shared/include/opencv4/opencv2 ./include/

    ② MNN 的头文件

    路径:/home/MNN/build_shared/include/MNN/

    需要复制整个 MNN 文件夹到项目的 include/ 目录下:

    cp -r /home/MNN/build_shared/include/MNN ./include/

    ③ 项目内部头文件

    确保项目的 include/ 目录中的头文件已经存在。

    (2) 动态库文件

    ① OpenCV 的动态库

    路径:/home/opencv-4.10.0/build_shared/lib/

    需要复制以下文件到项目的 lib/ 目录下:

    mkdir -p ./lib
    cp /home/opencv-4.10.0/build_shared/lib/libopencv_core.so* ./lib/
    cp /home/opencv-4.10.0/build_shared/lib/libopencv_imgproc.so* ./lib/
    cp /home/opencv-4.10.0/build_shared/lib/libopencv_highgui.so* ./lib/
    cp /home/opencv-4.10.0/build_shared/lib/libopencv_videoio.so* ./lib/
    cp /home/opencv-4.10.0/build_shared/lib/libopencv_imgcodecs.so* ./lib/

    ② MNN 的动态库

    路径:/home/MNN/build_shared/lib/

    需要复制以下文件到项目的 lib/ 目录下:

    cp /home/MNN/build_shared/lib/libMNN.so* ./lib/

    2. 编写Makefile文件(动态链接库版本)

    makefile 文件如下:

    # 编译器
    CXX = g++# 编译选项
    CXXFLAGS = -Wall -I./include -O2# OpenCV 的头文件和库文件路径
    OPENCV_INCLUDE_DIR = /home/mtcnn_mnn/include
    OPENCV_LIB_DIR = /home/mtcnn_mnn/lib# MNN 的头文件和库文件路径
    MNN_CFLAGS = -I/home/mtcnn_mnn/include  
    MNN_LIBS = -L/home/mtcnn_mnn/lib -lMNN  # 目标可执行文件名
    TARGET = detection# 源文件目录
    SRCDIR = src# 头文件目录
    INCDIR = include# 链接库路径
    OPENCV_LIBS = -L$(OPENCV_LIB_DIR) -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs# 找到所有源文件
    SOURCES := $(wildcard $(SRCDIR)/*.cpp)# 生成目标文件列表
    OBJECTS := $(patsubst $(SRCDIR)/%.cpp, %.o, $(SOURCES))# 默认目标
    all: $(TARGET)# 链接目标文件生成可执行文件
    $(TARGET): $(OBJECTS)$(CXX) $(CXXFLAGS) $^ -o $@ $(OPENCV_LIBS) $(MNN_LIBS) -lpthread -ldl -lgomp -Wl,-rpath,'$$ORIGIN/lib' # 设置动态库的运行时搜索路径为当前目录下的 lib 文件夹# 规则:从源文件生成目标文件
    %.o: $(SRCDIR)/%.cpp$(CXX) $(CXXFLAGS) \-I$(OPENCV_INCLUDE_DIR) \-I$(INCDIR) \$(MNN_CFLAGS) \-c $< -o $@# 清理生成的文件
    clean:rm -f $(OBJECTS) $(TARGET).PHONY: all clean

    关键语句说明:

    ① 使用动态库

    • 配置 OpenCV 和 MNN 的动态库:
      OPENCV_LIBS = -L$(OPENCV_LIB_DIR) -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs
      MNN_LIBS = -L$(MNN_LIB_DIR) -lMNN
    • -L 指定动态库的路径。
    • -l 指定动态库的名称(去掉 lib 前缀和 .so 后缀)。

    ② 设置动态库的运行时路径

    • 添加 -Wl,-rpath,'$$ORIGIN/lib' 选项,告诉运行时加载器在当前目录的 lib/ 文件夹中查找动态库。
    • $$ORIGIN 是一个特殊的变量,表示可执行文件所在的目录。

    3. 编译工程

    构建完所有项目所需的文件后,开始编译工程

    make

    4. 在新设备上运行

    将整个项目文件夹拷贝到新设备。

    确保新设备上有以下依赖项:

    libstdc++.so(通常预装在大多数 Linux 系统中)。

    libpthread.solibdl.so 等系统库(通常也预装)。

    在新设备上运行可执行文件:

    ./detection

    常见运行问题如下:

    ① 权限问题

    -bash: ./detection: Permission denied

     首先查看 detection 文件的权限

    ls -l detection

    如果显示如下:

    -rw-rw-r-- 1 root root 67256  4月 26 14:39 detection

     说明缺少执行权限,因此需要增加执行权限,运行以下命令:

    chmod +x detection

    再次查看 detection 文件的权限,变更为:

    -rwxrwxr-x 1 root root 67256  4月 26 14:39 detection

    再次运行可执行文件:

    ./detection

    ② 动态库路径设置问题

    如果出现类似以下错误

    ./detection: error while loading shared libraries: libopencv_imgcodecs.so.410: cannot open shared object file: No such file or directory

    首先查看工程下的 lib 中是否有该文件

    ls -l /home/mtcnn_mnn/lib/libopencv_imgcodecs.so.410

     如果输出如下,说明文件存在,那就是运行时动态库路径未设置

    -rw-rw-r-- 1 root root 2238336  4月 26 15:03 /home/mtcnn_mnn/lib/libopencv_imgcodecs.so.410

    使用 LD_LIBRARY_PATH 环境变量

    在运行程序之前,设置 LD_LIBRARY_PATH 环境变量,指向包含动态库的目录:

    export LD_LIBRARY_PATH=/home/mtcnn_mnn/lib:$LD_LIBRARY_PATH 

    如果你希望永久设置该变量,可以将其添加到 ~/.bashrc~/.bash_profile 文件中:

    echo 'export LD_LIBRARY_PATH=/home/mtcnn_mnn/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
    source ~/.bashrc

    ③ 动态库缺失问题

    如果出现类似以下错误

    ./detection: error while loading shared libraries: libdc1394.so.22: cannot open shared object file: No such file or directory

    同样,首先查看工程下的 lib 中是否有该文件

    ls -l /home/mtcnn_mnn/lib/libdc1394.so.22

     如果输出如下,说明文件不存在

    ls: cannot access '/home/mtcnn_mnn/lib/libdc1394.so.22': No such file or directory

    运行以下命令,检查动态库是否正确加载:

    ldd ./detection

    如果出现如下情况:

    libopencv_imgcodecs.so.410 => /home/mtcnn_mnn/lib/libopencv_imgcodecs.so.410 (0x00007f6287a00000)
    libdc1394.so.22 => not found
    libavcodec.so.58 => /lib/x86_64-linux-gnu/libavcodec.so.58 (0x00007f6286400000)
    libavformat.so.58 => /lib/x86_64-linux-gnu/libavformat.so.58 (0x00007f6286000000)
    libavutil.so.56 => /lib/x86_64-linux-gnu/libavutil.so.56 (0x00007f6285c00000)
    libswscale.so.5 => /lib/x86_64-linux-gnu/libswscale.so.5 (0x00007f6288d62000)
    libmvec.so.1 => /lib/x86_64-linux-gnu/libmvec.so.1 (0x00007f6288c65000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f628bbd0000)
    libopenblas.so.0 => /lib/x86_64-linux-gnu/libopenblas.so.0 (0x00007f62837b0000)
    libgfortran.so.5 => /lib/x86_64-linux-gnu/libgfortran.so.5 (0x00007f6283400000)
    libatlas.so.3 => /lib/x86_64-linux-gnu/libatlas.so.3 (0x00007f6283000000)
    libjpeg.so.8 => /lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007f628897f000)
    libwebp.so.6 => not found
    libpng16.so.16 => /lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f628acd8000)

    说明存在未加载成功的动态库

    libdc1394.so.22 => not found
    libwebp.so.6 => not found
    

    此时需要回到最初编译成功的机器上寻找在新设备上缺失的动态库

    ls -l /usr/lib/x86_64-linux-gnu/libdc1394.so*

    输出以下内容:

    lrwxrwxrwx 1 root root     19 Sep 12  2019 /usr/lib/x86_64-linux-gnu/libdc1394.so -> libdc1394.so.22.2.1
    lrwxrwxrwx 1 root root     19 Sep 12  2019 /usr/lib/x86_64-linux-gnu/libdc1394.so.22 -> libdc1394.so.22.2.1
    -rw-r--r-- 1 root root 225328 Sep 12  2019 /usr/lib/x86_64-linux-gnu/libdc1394.so.22.2.1
    

    缺失的是 libdc1394.so.22,该文件为一个符号链接,它指向 libdc1394.so.22.2.1,因此要同时复制这两个文件到工程的lib文件下

    cp /usr/lib/x86_64-linux-gnu/libdc1394.so.22 ./lib/
    cp /usr/lib/x86_64-linux-gnu/libdc1394.so.22.2.1 ./lib/

    对于缺失的 libwebp.so.6 文件,重复以上操作即可。

    最后将完整的工程文件拷贝到新机器上,再次检查动态库是否正确加载:

    ldd ./detection

     输出应显示所有动态库都已找到。


    5. 注意事项

    (1) 确保动态库版本一致

    如果新设备上的系统库与旧设备不一致,可能会导致运行时错误。建议使用相同版本的 OpenCV 和 MNN 库。

    (2) 权限问题

    确保动态库文件具有正确的权限:

    chmod +x ./lib/*.so

    http://www.mrgr.cn/news/100310.html

    相关文章:

  • Qt ModbusSlave多线程实践总结
  • AAAI2016论文 UCO: A Unified Cybersecurity Ontology
  • 刚体运动 (位置向量 - 旋转矩阵) 笔记 1.1~1.3 (台大机器人学-林沛群)
  • 云原生--核心组件-容器篇-3-Docker核心之-镜像
  • C++ 同步原语
  • Swift与iOS内存管理机制深度剖析
  • 前端职业发展:如何规划前端工程师的成长路径?
  • 泰迪杯实战案例学习资料:生产线的故障自动识别和人员配置优化
  • 深度学习驱动下的字符识别:挑战与创新
  • 【股票系统】使用docker本地构建ai-hedge-fund项目,模拟大师炒股进行分析。人工智能的对冲基金的开源项目
  • 来自 Bisheng 关于微调的内容总结
  • 【Java并发】【原子类】适合初学体质的原子类入门
  • QT6 源(52)篇二:存储 c 语言字符串的类 QByteArray 的使用举例,
  • Win7 SSL证书问题
  • 如何打包python程序为可执行文件
  • Netmiko 源码解析
  • 精益数据分析(29/126):深入剖析电子商务商业模式
  • 【C++11】右值引用和移动语义:万字总结
  • 论人际关系发展的阶段
  • 毕业项目-Web入侵检测系统