• 【OpenCV(3)】linux arm aarch 是 opencv 交叉编译与使用


    1、直接找github 别人编译好的

    测试很多,找到一个可用的。

    https://github.com/dog-qiuqiu/libopencv

    它用了超级模块!
    OpenCV的world模块也称为超级模块(super-module),它结合了用户选择的所有其它模块。在编译OpenCV库时,有需要勾选BUILD_opencv_world模块,其作用是将所有模块的库文件合并成一个大的库文件,方便在链接时候的操作。

    这样就不用自主编译了。但是已经自主编译了一个,还是记录下吧。

    2、自主编译

    找了很多github的编译好的文件,都没法用。还是自己编译吧。

    opencv的交叉编译工具链在…/opencv3.4.16/platforms/linux 路径下,linux文件夹下是一些.cmake文件,对应不同的移植对象,本人需要在NVIDIA的Xavier部署模型,所以选择aarch64-gnu.toolchain.cmake 工具链。在opencv3.4.16目录下,编写build.sh文件,然后执行./build.sh --mlu-arch=SD5223C --cpu-arch=aarch64。 具体的buld.sh 这样写

    这个脚本只有2个地方需要修改:

    • 如果你的交叉编译器的地址修改,第53行 TOOLCHAIN_ROOT="/tmp/aarch64--glibc--stable-2020.08-1"
    • TARGET_C_COMPILERTARGET_CXX_COMPILER地址,需要注意。其他地方都很好理解。如果不理解,请在评论区讨论。
          TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc
          TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-g++
    
    • 1
    • 2
    #!/bin/bash
    ################################################################################
    if [ $NEUWARE_HOME ] ;then
      echo "NEUWARE_HOME: ${NEUWARE_HOME} has been set."
    else
      export NEUWARE_HOME="/usr/local/neuware"
      echo "set NEUWARE_HOME: ${NEUWARE_HOME} by default."
    fi
    
    BUILD_DIR="build"
    rm -rf "$BUILD_DIR"
    mkdir -p "$BUILD_DIR"
    
    BUILD_MODE="release"
    MLU_ARCH=""
    TARGET_CPU_ARCH="x86_64-linux-gnu"
    TARGET_C_COMPILER="$(which gcc)"
    TARGET_CXX_COMPILER="$(which g++)"
    if [ $# != 0 ]; then
      while [ $# != 0 ]; do
        case "$1" in
          --cpu-arch=*)
              TMP_STRING=$1
              TARGET_CPU_ARCH=${TMP_STRING#*=};
              TARGET_CPU_ARCH=${TARGET_CPU_ARCH}-linux-gnu;
              shift
              ;;
          --mlu-arch=*)
              TMP_MLU_ARCH=${1}
              MLU_ARCH=${TMP_MLU_ARCH#*=}
              shift
              ;;
          -d | --debug)
              BUILD_MODE="debug"
              echo "-- Using debug mode."
              shift
              ;;
          -v | --verbose)
              BUILD_VERBOSE="VERBOSE=1"
              shift
              ;;
        esac
      done
    fi
    
    ## TOOLCHAIN_ROOT not exist, use default env
    if [ ! "${TOOLCHAIN_ROOT}" ]; then
      if [ "$TARGET_CPU_ARCH" == "aarch64-linux-gnu" ]; then
        if [ "$MLU_ARCH" == "SD5223" ]; then
          #TOOLCHAIN_ROOT="/tools/gcc/gcc-9/gcc-stable-9.3.0-2020.08-x86_64_aarch4-linux-gnu"
          TOOLCHAIN_ROOT="/tools/gcc/gcc-9/gcc-stable-9.3.0-2020.08-x86_64_aarch4-linux-gnu"
        else
          TOOLCHAIN_ROOT="/tmp/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu"
        fi
        echo "Using default TOOLCHAIN_ROOT=${TOOLCHAIN_ROOT}"
        if [ -f ${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc ]; then
          TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc
          TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-g++
        else
          TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/aarch64-linux-gcc
          TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/aarch64-linux-g++
        fi
      fi
    else
      echo "Using TOOLCHAIN_ROOT=${TOOLCHAIN_ROOT}"
      if [ "$TARGET_CPU_ARCH" == "aarch64-linux-gnu" ]; then
        if [ -f ${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc ]; then
          TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc
          TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-g++
        else
          TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/aarch64-linux-gcc
          TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/aarch64-linux-g++
        fi
      fi
    fi
    
    if [[ -f /proc/cpuinfo ]]; then
        MJOBS=$(grep -c processor /proc/cpuinfo)
    else
        MJOBS=4
    fi
    
    pushd ${BUILD_DIR}
      cmake -DCMAKE_BUILD_TYPE="${BUILD_MODE}" \
               -DTOOLCHAIN_ROOT="${TOOLCHAIN_ROOT}" \
               -DTARGET_CPU_ARCH="${TARGET_CPU_ARCH}" \
               -DCMAKE_C_COMPILER="${TARGET_C_COMPILER}" \
               -DCMAKE_CXX_COMPILER="${TARGET_CXX_COMPILER}" \
               -DMLU_ARCH="${MLU_ARCH}" \
               -DCMAKE_INSTALL_PREFIX=../aarch_64_install \
               -DCMAKE_TOOLCHAIN_FILE=../platforms/linux/aarch64-gnu.toolchain.cmake \
            ..
      make -j$MJOBS ${BUILD_VERBOSE}
    popd
    
    • 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
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    这个脚本还是很好用的,如果理解里面的知识点的话!!

    make install
    
    • 1

    编译结束后进入aarch_64_install文件夹,里面生成bin,include,lib,share四个文件夹。

    在这里插入图片描述

    参考

    https://zhuanlan.zhihu.com/p/381760569

    3使用

    可以直接通过指定export OPENCV_DIR=xxx指定依赖的opencv,默认需要的组织目录(aarch64架构下建议使用该种形式):

    
      |-- ${OPENCV_DIR}
      |   |-- include
      |   |   |-- opencv2
      |   |-- lib
      |   |   |-- libxxx
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    CMake

    # cmake file for samples
    cmake_minimum_required(VERSION 2.8)
    project(SAMPLES)
    set(CMAKE_CXX_STANDARD 11)  
    
    
    set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/bin")
    set(TOOLCHAIN_ROOT ${TOOLCHAIN_ROOT})
    set(TARGET_CPU_ARCH ${TARGET_CPU_ARCH})
    if(${TARGET_CPU_ARCH} MATCHES "aarch64-linux-gnu")
      include_directories(${TOOLCHAIN_ROOT}/aarch64-linux-gnu/include/c++/6.2.1/)
      include_directories(${TOOLCHAIN_ROOT}/aarch64-linux-gnu/include/c++/6.2.1/aarch64-linux-gnu/)
      include_directories(${TOOLCHAIN_ROOT}/aarch64-linux-gnu/)
    endif()
    
    ################################################################################
    # opencv lib
    ################################################################################
    
    
    if(NOT HAVE_OPENCV)
      if("$ENV{OPENCV_DIR}" STREQUAL "")
        find_package(OpenCV REQUIRED)
        set(HAVE_OPENCV true)
        message("find_package(OpenCV REQUIRED)   required.")
      else()
        message("find_package(OpenCV REQUIRED)   No!")
        include_directories("$ENV{OPENCV_DIR}/include")
        link_directories("$ENV{OPENCV_DIR}/lib")
    
        set(OpenCV_LIBS opencv_core opencv_imgproc opencv_highgui opencv_imgcodecs)
        set(HAVE_OPENCV true)
      endif()
    endif()
    
    
    if(NOT HAVE_OPENCV)
      message(FATAL_ERROR "Cannot find opencv which is required.")
    else()
      #message(${OpenCV_INCLUDE_DIRS})
      message("ok  required.")
    endif()
    include_directories( ${OpenCV_INCLUDE_DIRS} )
    
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wall -Werror -pthread")
    message(STATUS "Project: ${PROJECT_SOURCE_DIR}" )
    message(STATUS "Project SOURCE dir: ${SAMPLES_SOURCE_DIR}" )
    message(STATUS "Project BINARY dir: ${PROJECT_BINARY_DIR}" )
    
    function(gensample sample_file)
      set(sample_root_name ${CMAKE_CURRENT_SOURCE_DIR}/${sample_file}.cpp)
      add_executable(sample_${sample_file} ${sample_root_name} )
      target_link_libraries(sample_${sample_file}  ${OpenCV_LIBS})
    endfunction()
    
    ################################################################################
    # Build Samples
    ################################################################################
    set(MLU_ARCH)
    
    if ("${MLU_ARCH}" MATCHES "SD5223")
      gensample(OpenCVTest)
    else()
      gensample(OpenCVTest)
    endif()
    
    
    
    • 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
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    #include 
    #include "opencv2/core.hpp"
    #include "opencv2/imgcodecs.hpp"
    #include "opencv2/imgproc.hpp"
    #include "opencv2/highgui/highgui.hpp"
     
     
    int main()
    {
        cv::Mat srcImage = cv::imread("1.jpg");
        cv::Mat img;
        cv::cvtColor(srcImage, img, cv::COLOR_BGR2RGB);
        //cv::imwrite("resize_input.jpg", srcImage);
        cv::imwrite("resize_input.jpg", img);
        //cv::Mat img;
        cv::cvtColor(srcImage, img, cv::COLOR_BGR2RGB);
        cv::imshow("源图像",srcImage);
        cv::waitKey(0);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    sh脚本

    #!/bin/bash
    ################################################################################
    export OPENCV_DIR=/mnt/ef2301-sdk-0.10.0/board/develop_workspace/inference/OpenCV3.0.0-master/arm-obj_rel
    
    
    if [ $NEUWARE_HOME ] ;then
      echo "NEUWARE_HOME: ${NEUWARE_HOME} has been set."
    else
      export NEUWARE_HOME="/usr/local/neuware"
      echo "set NEUWARE_HOME: ${NEUWARE_HOME} by default."
    fi
    
    
    
    BUILD_DIR="build"
    rm -rf "$BUILD_DIR"
    mkdir -p "$BUILD_DIR"
    
    BUILD_MODE="release"
    MLU_ARCH=""
    TARGET_CPU_ARCH="x86_64-linux-gnu"
    TARGET_C_COMPILER="$(which gcc)"
    TARGET_CXX_COMPILER="$(which g++)"
    if [ $# != 0 ]; then
      while [ $# != 0 ]; do
        case "$1" in
          --cpu-arch=*)
              TMP_STRING=$1
              TARGET_CPU_ARCH=${TMP_STRING#*=};
              TARGET_CPU_ARCH=${TARGET_CPU_ARCH}-linux-gnu;
              shift
              ;;
          --mlu-arch=*)
              TMP_MLU_ARCH=${1}
              MLU_ARCH=${TMP_MLU_ARCH#*=}
              shift
              ;;
          -d | --debug)
              BUILD_MODE="debug"
              echo "-- Using debug mode."
              shift
              ;;
          -v | --verbose)
              BUILD_VERBOSE="VERBOSE=1"
              shift
              ;;
        esac
      done
    fi
    
    ## TOOLCHAIN_ROOT not exist, use default env
    if [ ! "${TOOLCHAIN_ROOT}" ]; then
      if [ "$TARGET_CPU_ARCH" == "aarch64-linux-gnu" ]; then
        if [ "$MLU_ARCH" == "SD5223" ]; then
          #TOOLCHAIN_ROOT="/tools/gcc/gcc-9/gcc-stable-9.3.0-2020.08-x86_64_aarch4-linux-gnu"
          TOOLCHAIN_ROOT="/tools/gcc/gcc-9/gcc-stable-9.3.0-2020.08-x86_64_aarch4-linux-gnu"
        else
          TOOLCHAIN_ROOT="/tmp/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu"
        fi
        echo "Using default TOOLCHAIN_ROOT=${TOOLCHAIN_ROOT}"
        if [ -f ${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc ]; then
          TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc
          TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-g++
        else
          TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/aarch64-linux-gcc
          TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/aarch64-linux-g++
        fi
      fi
    else
      echo "Using TOOLCHAIN_ROOT=${TOOLCHAIN_ROOT}"
      if [ "$TARGET_CPU_ARCH" == "aarch64-linux-gnu" ]; then
        if [ -f ${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc ]; then
          TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc
          TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-g++
        else
          TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/aarch64-linux-gcc
          TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/aarch64-linux-g++
        fi
      fi
    fi
    
    if [[ -f /proc/cpuinfo ]]; then
        MJOBS=$(grep -c processor /proc/cpuinfo)
    else
        MJOBS=4
    fi
    
    pushd ${BUILD_DIR}
      cmake -DCMAKE_BUILD_TYPE="${BUILD_MODE}" \
               -DTOOLCHAIN_ROOT="${TOOLCHAIN_ROOT}" \
               -DTARGET_CPU_ARCH="${TARGET_CPU_ARCH}" \
               -DCMAKE_C_COMPILER="${TARGET_C_COMPILER}" \
               -DCMAKE_CXX_COMPILER="${TARGET_CXX_COMPILER}" \
               -DMLU_ARCH="${MLU_ARCH}" \
            ..
      make -j$MJOBS ${BUILD_VERBOSE}
    popd
    
    
    • 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
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    检查

    利用file draw_image检查可执行文件格式是否支持arrch64

    draw_image: ELF 64-bit LSB shared object, ARM aarch64, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=42f4ae7c66a0875bc0d49e4195ff35aa08f15cbe, not stripped 
    
    • 1

    出现如上结果说明可执行文件支持ARM arrch64。

    移植ARM端执行

    将 aarch_64_install文件夹下的include和lib里的文件分别拷贝到ARM板的/usr/include 和/usr/lib下 然后打开终端执行可执行文件即可。

    参考

    https://blog.csdn.net/linxizi0622/article/details/128702048

  • 相关阅读:
    Web前端:JavaScript-->运算符*笔记
    百战c++(数据库2)
    【css-banner图片自适应】
    计算机网络——应用层网络应用模型、DNS系统、文件传输协议、电子邮件、万维网和HTTP协议
    Linux开发——Linux 文件系统简介(四)
    实现数组扁平化
    ChatGPT:怎么用Java调出来文件选择器,然后返回文件的位置和名称?Swing 组件和 AWT 组件:Java GUI 编程的不同之处
    JavaScript中的变量
    vscode 调试使用 make 编译的项目
    Web通用漏洞--sql注入
  • 原文地址:https://blog.csdn.net/djfjkj52/article/details/134288261