【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地址,需要注意。其他地方都很好理解。如果不理解,请在评论区讨论。
c 复制代码
      TARGET_C_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-gcc
      TARGET_CXX_COMPILER=${TOOLCHAIN_ROOT}/bin/${TARGET_CPU_ARCH}-g++
c 复制代码
#!/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

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

c 复制代码
make install

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

参考

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

3使用

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

shell 复制代码
  |-- ${OPENCV_DIR}
  |   |-- include
  |   |   |-- opencv2
  |   |-- lib
  |   |   |-- libxxx

CMake

c 复制代码
# 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()
c 复制代码
#include <iostream>
#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;
}

sh脚本

bash 复制代码
#!/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

检查

利用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 

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

移植ARM端执行

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

参考

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

相关推荐
小熙智菏——Sunspot1 小时前
Linux系统性能优化技巧
linux·运维·性能优化
@haihi2 小时前
什么是ARM
arm开发
极客代码2 小时前
【Linux】内核驱动模块
linux·内核·内核模块·unix·驱动
EEE1even2 小时前
Linux服务器驱动安装
linux·运维·服务器
钰爱&2 小时前
【操作系统】Linux之网络编程(TCP)(头歌作业)
linux·网络·tcp/ip
xiaozhiwise3 小时前
Linux syscall
linux
我们的五年3 小时前
【MySQL课程学习】:MySQL安装,MySQL如何登录和退出?MySQL的简单配置
linux·服务器·数据库·学习·mysql·adb
行码棋3 小时前
Linux无sudo权限将zsh作为默认shell
linux·服务器
Lanthanesthai.3 小时前
Ubuntu20.04安装ROS1
linux·ubuntu
只怕自己不够好3 小时前
《全面解析图像平滑处理:多种滤波方法及应用实例》
图像处理·python·opencv