在Ubuntu上编译安装OpenCV3

 

目录

背景

安装依赖包

安装ffmpeg

编译安装opencv3

理想情况

错误处理

复制头文件

修改头文件

修改OpenCV文件

修改文件方法

更好的解决方法——换OpenCV版本

3.4.1版本的OpenCV及OpenCV_contrib

下载xfeatures2d源文件

修改OpenCV文件

编译与安装

配置

检验

结语


背景

记录一下我前一阵子在Ubuntu18.04 64位上安装OpenCV3的过程,运气背的话挺繁琐的,仅供参考

安装依赖包

root@sundata:/etc/apt/sources.list.d# apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libx264-dev libx265-dev
root@sundata:/etc/apt/sources.list.d# apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev ffmpeg libavformat-dev libavcodec-dev libswresample-dev libswscale-dev libavutil-dev libsdl1.2-dev yasm

安装ffmpeg

root@sundata:/data/szc# git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
root@sundata:/data/szc# cd ffmpeg/
root@sundata:/data/szc/ffmpeg# ./configure   --enable-shared  --prefix=/usr/local/ffmpeg  --enable-gpl --enable-libx264  --enable-libx265
root@sundata:/data/szc/ffmpeg# make && make install

如果编译时报错:V4L2_PIX_FMT_JPEG undeclared here,那么就修改libavdevice/v4l2-common.h文件,注释掉#include <linux/videodev2.h>周围的宏判断

// #if HAVE_SYS_VIDEOIO_H
// #include <sys/videoio.h>
// #else
// #if HAVE_ASM_TYPES_H
// #include <asm/types.h>
// #endif
#include <linux/videodev2.h>
// #endif

测试一下

root@sundata:/data/szc/ffmpeg# ldd ffmpeg
    linux-vdso.so.1 (0x00007ffd3fbb1000)
    libavdevice.so.58 => not found
    libavfilter.so.7 => not found
    libavformat.so.58 => not found
    libavcodec.so.58 => not found
    libpostproc.so.55 => not found
    libswresample.so.3 => not found
    libswscale.so.5 => not found
    libavutil.so.56 => not found
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7bf1a84000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f7bf1865000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7bf1474000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f7bf2068000)

root@sundata:/data/szc/ffmpeg# ffmpeg -version
ffmpeg version 3.4.8-0ubuntu0.2 Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04)
configuration: --prefix=/usr --extra-version=0ubuntu0.2 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
libavutil      55. 78.100 / 55. 78.100
libavcodec     57.107.100 / 57.107.100
libavformat    57. 83.100 / 57. 83.100
libavdevice    57. 10.100 / 57. 10.100
libavfilter     6.107.100 /  6.107.100
libavresample   3.  7.  0 /  3.  7.  0
libswscale      4.  8.100 /  4.  8.100
libswresample   2.  9.100 /  2.  9.100
libpostproc    54.  7.100 / 54.  7.100

编译安装opencv3

理想情况

原本安装的是3.0.0。首先下载源码包 https://github.com/opencv/opencv/archive/3.0.0.zip,上传到服务器,解压之。进入其目录,创建build文件夹并进入,执行编译脚本
(base) root@ubuntu:/home/szc/opencv/opencv-3.0.0/build# cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..

如果一切正常,会成功并且当前目录下会有Makefile文件

然后执行安装命令会一切顺利
(base) root@ubuntu:/home/szc/opencv/opencv-3.0.0/build# make -j6 && make install

以上过程在我的虚拟机上一切正常,完成后的截图如下所示

 

错误处理

但是我在服务器上就报了一堆错误,我尝试解决的过程如下:

复制头文件

由于编译时会报很多头文件找不到的错误,因此要安装一些第三方库,再把一些头文件复制到/usr/local/include目录下
root@sundata:/data/szc/opencv/opencv-3.0.0/build# apt-get install libpt-dev apcalc-dev linux-oracle-headers-4.15.0-1054 
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp -r /usr/include/x86_64-linux-gnu/libavformat /usr/include
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /usr/include/calc/cmath.h /usr/local/include/
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /usr/include/c++/v1/* /usr/local/include
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /snap/gnome-3-34-1804/36/usr/include/c++/6/cmath /usr/local/include
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /usr/src/linux-oracle-headers-4.15.0-1054/include/uapi/linux/videodev2.h /usr/local/include/linux/
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /usr/include/ptlib/videoio.h /usr/local/include/sys/
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /usr/include/ptbuildopts.h /usr/local/include
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp -r /usr/include/ptlib /usr/local/include
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /usr/include/ptlib.h /usr/local/include
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /snap/gnome-3-34-1804/36/usr/include/c++/6/bits/cpp_type_traits.h /usr/local/include/bits
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp -r /usr/src/linux-hwe-5.4-headers-5.4.0-48/include/linux/* /usr/local/include/linux/
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp -r /usr/src/linux-hwe-5.4-headers-5.4.0-48/include/uapi /usr/local/include
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /snap/gnome-3-34-1804/36/usr/lib/gcc/x86_64-linux-gnu/6/include/stdbool.h /usr/local/include
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /usr/local/include/c++/6/ext/atomicity.h /usr/local/include/ext/

注意libpjproject-dev似乎和libpt-dev是互斥的,因此要把后者的相关文件复制到/usr/local/include目录后,再安装后者

root@sundata:/data/szc/opencv/opencv-3.0.0/build# apt-get install libpjproject-dev
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /usr/include/pjmedia/videodev.h /usr/local/include/linux/
root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp -r /usr/include/pj* /usr/local/include

修改头文件

还得修改一些文件:

1)、/usr/include/bits/cpp_type_traits.h,在extern "C++" { 上下加上#pragma once和宏判断
#pragma once
#ifdef __cplusplus
extern "C++" {
.....

} // extern "C++"
#endif

....

2)、/usr/local/include/wchar.h,开头某行加上wchar_t的宏定义

....
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif


#define int32 wchar_t


#include_next <wchar.h>
....

3)、/usr/local/include/ptlib/unix/ptlib/contain.h,加上头文件

#include <wchar.h>
4)、如果报错未知类型extern "C++"、namespace、class、_LIBCPP_BEGIN_NAMESPACE_STD等,解决方法只有修改/usr/local/include目录下报错的文件:
  • 未知类型extern "C++":修改type_traits、cmath,用#ifdef __cplusplus .... #endif包裹住extern "C++" {}
  • 未知类型using namespace std:修改ptlib/unix/ptlib/contain.h,用#ifdef __cplusplus .... #endif包裹住using namespace std;
  •  未知类型_LIBCPP_BEGIN_NAMESPACE_STD:修改atomic、cctype、cstring、cstddef、cstdio、cstdint、iosfwd、ios、iterator、cstdlib、cwctype、cwchar、memory、stdexcept、tuple、typeinfo、type_traits、utility、__tuple、__debug、__bsd_locale_fallbacks.h、cstdarg、__locale、ostream、iostream、iomanip、map文件,用#ifdef __cplusplus.... #endif包裹住_LIBCPP_BEGIN_NAMESPACE_STD ..... _LIBCPP_END_NAMESPACE_STD,其中atomic还要引入头文件#include <stdbool.h>,以及注释掉#error <atomic> is not implemented;stdexcept文件是从第一个_LIBCPP_BEGIN_NAMESPACE_STD,一直包裹到最后一个_LIBCPP_END_NAMESPACE_STD,基本就到了文件末尾了
  • 未知类型 namespace std:修改__nullptr、exception、initializer_list、typeinfo文件,用#ifdef __cplusplus .... #endif包裹住所有的namespace std {}
  •  #include_next <stddef.h>找不到stddef.h文件,修改cstddef文件,把#include_next <stddef.h>改成#include <stddef.h>
  • 未知类型_LIBCPP_PUSH_MACROS:修改__string、__bit_reference、__mutex_base、__threading_support、__split_buffer、__tree、string_view、string、streambuf、algorithm、memory、limits、locale、bitset、mutex、chrono、ratio、istream、sstream、vector、list文件:用#ifdef __cplusplus .... #endif包裹住_LIBCPP_PUSH_MACROS和_LIBCPP_BEGIN_NAMESPACE_STD ..... _LIBCPP_POP_MACROS
5)、 还有一些文件要单独修改:
  • new文件:
  1.  用#ifdef __cplusplus .... #endif包裹住#if !defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME) ....#endif // !_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME之间的内容
  2. 用#ifdef __cplusplus .... #endif包裹住_LIBCPP_BEGIN_NAMESPACE_STD ..... _LIBCPP_END_NAMESPACE_STD
  • __functional_base文件:用#ifdef __cplusplus .... #endif包裹住_LIBCPP_BEGIN_NAMESPACE_STD ..... _LIBCPP_END_NAMESPACE_STD和constexpr
  • ext/atomicity.h文件: 用#ifdef __cplusplus .... #endif包裹住namespace
  • ptlib/目录:要改的文件很多,可以直接从我的网盘下载改好的:链接:https://pan.baidu.com/s/1guHSn6iVRGyrw8enXead5Q,提取码:hsw3
  • sys/videoio.h文件: 用#ifdef __cplusplus .... #endif包裹住class PColourConverter;  ...... class PVideoFont : public PObject两个类之间的内容
  • class:修改__debug文件,用#ifdef __cplusplus .... #endif包裹住class _LIBCPP_EXCEPTION_ABI __libcpp_debug_exception;

修改OpenCV文件

下面这些文件都是在opencv3.0.0的目录下

1)、modules/cudev/include/opencv2/cudev/common.hpp,加上头文件
#include <cuda_fp16.h>

2)、cmake/FindCUDA.cmake

首先:
  find_cuda_helper_libs(nppi)

改为

  find_cuda_helper_libs(nppial)
  find_cuda_helper_libs(nppicc)
  find_cuda_helper_libs(nppicom)
  find_cuda_helper_libs(nppidei)
  find_cuda_helper_libs(nppif)
  find_cuda_helper_libs(nppig)
  find_cuda_helper_libs(nppim)
  find_cuda_helper_libs(nppist)
  find_cuda_helper_libs(nppisu)
  find_cuda_helper_libs(nppitc)

而后:

  set(CUDA_npp_LIBRARY "${CUDA_nppc_LIBRARY};${CUDA_nppi_LIBRARY};${CUDA_npps_LIBRARY}")

改为

  set(CUDA_npp_LIBRARY "${CUDA_nppc_LIBRARY};${CUDA_nppial_LIBRARY};${CUDA_nppicc_LIBRARY};${CUDA_nppicom_LIBRARY};${CUDA_nppidei_LIBRARY};${CUDA_nppif_LIBRARY};${CUDA_nppig_LIBRARY};${CUDA_nppim_LIBRARY};${CUDA_nppist_LIBRARY};${CUDA_nppisu_LIBRARY};${CUDA_nppitc_LIBRARY};${CUDA_npps_LIBRARY}")

最后:

  unset(CUDA_nppi_LIBRARY CACHE)

改为

  unset(CUDA_nppial_LIBRARY CACHE)
  unset(CUDA_nppicc_LIBRARY CACHE)
  unset(CUDA_nppicom_LIBRARY CACHE)
  unset(CUDA_nppidei_LIBRARY CACHE)
  unset(CUDA_nppif_LIBRARY CACHE)
  unset(CUDA_nppig_LIBRARY CACHE)
  unset(CUDA_nppim_LIBRARY CACHE)
  unset(CUDA_nppist_LIBRARY CACHE)
  unset(CUDA_nppisu_LIBRARY CACHE)
  unset(CUDA_nppitc_LIBRARY CACHE)

3)、cmake/OpenCVDetectCUDA.cmake

  if(CUDA_GENERATION STREQUAL "Fermi")
    set(__cuda_arch_bin "2.0 2.1(2.0)")
  elseif(CUDA_GENERATION STREQUAL "Kepler")
    if(${CUDA_VERSION} VERSION_LESS "5.0")
      set(__cuda_arch_bin "3.0")
  else()
      set(__cuda_arch_bin "3.0 3.5")
  endif()

改为

  if(CUDA_GENERATION STREQUAL "Kepler")
    set(__cuda_arch_bin "3.0 3.5 3.7")
  elseif(CUDA_GENERATION STREQUAL "Maxwell")
    set(__cuda_arch_bin "5.0 5.2")

4)、cmake/OpenCVFindLibsVideo.cmake

首先:
    
CHECK_INCLUDE_FILE(ffmpeg/avformat.h HAVE_FFMPEG_FFMPEG)
改为
    
CHECK_INCLUDE_FILE(libavformat/avformat.h HAVE_FFMPEG_FFMPEG)
其次:
      
if(EXISTS /usr/include/ffmpeg/libavformat/avformat.h OR HAVE_FFMPEG_SWSCALE)
改为
     
if(EXISTS /usr/local/include/libavformat/avformat.h OR HAVE_FFMPEG_SWSCALE)
5)、把cmake/OpenCVDetectCXXCompiler.cmake文件替换成下面的内容(对应报错CMake match cannot parse the expression *100+)
# ----------------------------------------------------------------------------
# Detect Microsoft compiler:
# ----------------------------------------------------------------------------
if(CMAKE_CL_64)
    set(MSVC64 1)
endif()

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  set(CMAKE_COMPILER_IS_GNUCXX 1)
  set(CMAKE_COMPILER_IS_CLANGCXX 1)
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
  set(CMAKE_COMPILER_IS_GNUCC 1)
  set(CMAKE_COMPILER_IS_CLANGCC 1)
endif()
if("${CMAKE_CXX_COMPILER};${CMAKE_C_COMPILER}" MATCHES "ccache")
  set(CMAKE_COMPILER_IS_CCACHE 1)
endif()

# ----------------------------------------------------------------------------
# Detect Intel ICC compiler -- for -fPIC in 3rdparty ( UNIX ONLY ):
#  see  include/opencv/cxtypes.h file for related   ICC & CV_ICC defines.
# NOTE: The system needs to determine if the '-fPIC' option needs to be added
#  for the 3rdparty static libs being compiled.  The CMakeLists.txt files
#  in 3rdparty use the CV_ICC definition being set here to determine if
#  the -fPIC flag should be used.
# ----------------------------------------------------------------------------
if(UNIX)
  if  (__ICL)
    set(CV_ICC   __ICL)
  elseif(__ICC)
    set(CV_ICC   __ICC)
  elseif(__ECL)
    set(CV_ICC   __ECL)
  elseif(__ECC)
    set(CV_ICC   __ECC)
  elseif(__INTEL_COMPILER)
    set(CV_ICC   __INTEL_COMPILER)
  elseif(CMAKE_C_COMPILER MATCHES "icc")
    set(CV_ICC   icc_matches_c_compiler)
  endif()
endif()

if(MSVC AND CMAKE_C_COMPILER MATCHES "icc|icl")
  set(CV_ICC   __INTEL_COMPILER_FOR_WINDOWS)
endif()

# ----------------------------------------------------------------------------
# Detect GNU version:
# ----------------------------------------------------------------------------
if(CMAKE_COMPILER_IS_CLANGCXX)
  set(CMAKE_GCC_REGEX_VERSION "4.2.1")
  set(CMAKE_OPENCV_GCC_VERSION_MAJOR 4)
  set(CMAKE_OPENCV_GCC_VERSION_MINOR 2)
  set(CMAKE_OPENCV_GCC_VERSION 42)
  set(CMAKE_OPENCV_GCC_VERSION_NUM 402)

  execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} -v
                  ERROR_VARIABLE CMAKE_OPENCV_CLANG_VERSION_FULL
                  ERROR_STRIP_TRAILING_WHITESPACE)

  string(REGEX MATCH "version.*$" CMAKE_OPENCV_CLANG_VERSION_FULL "${CMAKE_OPENCV_CLANG_VERSION_FULL}")
  string(REGEX MATCH "[0-9]+\\.[0-9]+" CMAKE_CLANG_REGEX_VERSION "${CMAKE_OPENCV_CLANG_VERSION_FULL}")

elseif(CMAKE_COMPILER_IS_GNUCXX)
  execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} -dumpversion
                OUTPUT_VARIABLE CMAKE_OPENCV_GCC_VERSION_FULL
                OUTPUT_STRIP_TRAILING_WHITESPACE)

  execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} -v
                ERROR_VARIABLE CMAKE_OPENCV_GCC_INFO_FULL
                OUTPUT_STRIP_TRAILING_WHITESPACE)

  # Typical output in CMAKE_OPENCV_GCC_VERSION_FULL: "c+//0 (whatever) 4.2.3 (...)"
  # Look for the version number, major.minor.build
  string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}")
  if(NOT CMAKE_GCC_REGEX_VERSION)#major.minor
    string(REGEX MATCH "[0-9]+\\.[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}")
  endif()

  if(CMAKE_GCC_REGEX_VERSION)
    # Split the parts:
    string(REGEX MATCHALL "[0-9]+" CMAKE_OPENCV_GCC_VERSIONS "${CMAKE_GCC_REGEX_VERSION}")

    list(GET CMAKE_OPENCV_GCC_VERSIONS 0 CMAKE_OPENCV_GCC_VERSION_MAJOR)
    list(GET CMAKE_OPENCV_GCC_VERSIONS 1 CMAKE_OPENCV_GCC_VERSION_MINOR)
  else()#compiler returned just the major version number
    string(REGEX MATCH "[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}")
    if(NOT CMAKE_GCC_REGEX_VERSION)#compiler did not return anything reasonable
      set(CMAKE_GCC_REGEX_VERSION "0")
      message(WARNING "GCC version not detected!")
    endif()
    set(CMAKE_OPENCV_GCC_VERSION_MAJOR ${CMAKE_GCC_REGEX_VERSION})
    set(CMAKE_OPENCV_GCC_VERSION_MINOR 0)
  endif()

  set(CMAKE_OPENCV_GCC_VERSION ${CMAKE_OPENCV_GCC_VERSION_MAJOR}${CMAKE_OPENCV_GCC_VERSION_MINOR})
  math(EXPR CMAKE_OPENCV_GCC_VERSION_NUM "${CMAKE_OPENCV_GCC_VERSION_MAJOR}*100 + ${CMAKE_OPENCV_GCC_VERSION_MINOR}")
  message(STATUS "Detected version of GNU GCC: ${CMAKE_OPENCV_GCC_VERSION} (${CMAKE_OPENCV_GCC_VERSION_NUM})")

  if(WIN32)
    execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpmachine
              OUTPUT_VARIABLE OPENCV_GCC_TARGET_MACHINE
              OUTPUT_STRIP_TRAILING_WHITESPACE)
    if(OPENCV_GCC_TARGET_MACHINE MATCHES "amd64|x86_64|AMD64")
      set(MINGW64 1)
    endif()
  endif()
endif()

if(MSVC64 OR MINGW64)
  set(X86_64 1)
elseif(MINGW OR (MSVC AND NOT CMAKE_CROSSCOMPILING))
  set(X86 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
  set(X86_64 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|AMD64.*")
  set(X86 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)")
  set(ARM 1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)")
  set(AARCH64 1)
endif()

# Workaround for 32-bit operating systems on 64-bit x86_64 processor
if(X86_64 AND CMAKE_SIZEOF_VOID_P EQUAL 4 AND NOT FORCE_X86_64)
  message(STATUS "sizeof(void) = 4 on x86 / x86_64 processor. Assume 32-bit compilation mode (X86=1)")
  unset(X86_64)
  set(X86 1)
endif()

# Similar code exists in OpenCVConfig.cmake
if(NOT DEFINED OpenCV_STATIC)
  # look for global setting
  if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS)
    set(OpenCV_STATIC OFF)
  else()
    set(OpenCV_STATIC ON)
  endif()
endif()

if(MSVC)
  if(CMAKE_CL_64)
    set(OpenCV_ARCH x64)
  elseif((CMAKE_GENERATOR MATCHES "ARM") OR ("${arch_hint}" STREQUAL "ARM") OR (CMAKE_VS_EFFECTIVE_PLATFORMS MATCHES "ARM|arm"))
    # see Modules/CmakeGenericSystem.cmake
    set(OpenCV_ARCH ARM)
  else()
    set(OpenCV_ARCH x86)
  endif()
  if(MSVC_VERSION EQUAL 1400)
    set(OpenCV_RUNTIME vc8)
  elseif(MSVC_VERSION EQUAL 1500)
    set(OpenCV_RUNTIME vc9)
  elseif(MSVC_VERSION EQUAL 1600)
    set(OpenCV_RUNTIME vc10)
  elseif(MSVC_VERSION EQUAL 1700)
    set(OpenCV_RUNTIME vc11)
  elseif(MSVC_VERSION EQUAL 1800)
    set(OpenCV_RUNTIME vc12)
  elseif(MSVC_VERSION EQUAL 1900)
    set(OpenCV_RUNTIME vc14)
  elseif(MSVC_VERSION EQUAL 1910)
    set(OpenCV_RUNTIME vc15)
  endif()
elseif(MINGW)
  set(OpenCV_RUNTIME mingw)

  if(MINGW64)
    set(OpenCV_ARCH x64)
  else()
    set(OpenCV_ARCH x86)
  endif()
endif()

6)、如果报错Requested modules not available: vtkRenderingOpenGL,就修改/cmake/OpenCVDetectVTK.cmake文件,把

find_package(VTK QUIET COMPONENTS vtkRenderingOpenGL vtkInteractionStyle vtkRenderingLOD vtkIOPLY vtkFiltersTexture vtkRenderingFreeType vtkIOExport NO_MODULE)

改成

find_package(VTK QUIET COMPONENTS vtkRenderingOpenGL2 vtkInteractionStyle vtkRenderingLOD vtkIOPLY vtkFiltersTexture vtkRenderingFreeType vtkIOExport NO_MODULE)

7)、如果报错unsupported gpu architecture compute_20,由于我的cuda为10.0,就要先修改cmake/OpenCVDetectCUDA.cmake文件,在设置_generations后面加上Pascal

set(_generations "Fermi" "Kepler" "Pascal")

然后在对CUDA_GENERATION的判断分支里假设Pascal对应的计算能力(6.0和6.1)

  if(CUDA_GENERATION STREQUAL "Kepler")
    set(__cuda_arch_bin "3.0 3.5 3.7")
  elseif(CUDA_GENERATION STREQUAL "Maxwell")
    set(__cuda_arch_bin "5.0 5.2")
  elseif(CUDA_GENERATION STREQUAL "Pascal")
    set(__cuda_arch_bin "6.0 6.1")

最后cmake编译时指定CUDA架构

-D CUDA_GENERATION=Pascal

修改文件方法

最后说一下这些问题的解决思路:

1)、某头文件找不到(比如bits/cpp_type_traits.h),首先locate一下这个文件在哪里
root@sundata:/home/sundata# locate bits/cpp_type_traits.h
/snap/gnome-3-34-1804/36/usr/include/c++/6/bits/cpp_type_traits.h
/usr/include/c++/3.4/bits/cpp_type_traits.h
/usr/include/c++/5/bits/cpp_type_traits.h
/usr/include/c++/7/bits/cpp_type_traits.h
/usr/local/include/c++/6/bits/cpp_type_traits.h

然后找一个复制到/usr/local/include目录下(这里找不到的是bits/cpp_type_traits.h,因此要复制到/usr/local/include/bits目录下)

root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /snap/gnome-3-34-1804/36/usr/include/c++/6/bits/cpp_type_traits.h /usr/local/include/bits

如果在本地找不到,就说明我们得通过安装第三方库的方式添加此文件了(比如sys/videoio.h)。首先用apt-file(没有就用apt-get安装)查一下此头文件包含在哪个第三方库和安装后所在的路径

root@sundata:/home/sundata# apt-file search videoio.h
libopencv-videoio-dev: /usr/include/opencv2/videoio.hpp
libopencv-videoio-dev: /usr/include/opencv2/videoio/videoio.hpp
libpt-dev: /usr/include/ptlib/videoio.h
opencv-doc: /usr/share/doc/opencv-doc/html/dd/de7/group__videoio.html
opencv-doc: /usr/share/doc/opencv-doc/html/df/d2c/tutorial_table_of_content_videoio.html

我们选的肯定是头文件,那么只有libpt-dev能选。我们用apt-get安装后,把此文件从安装后所在的路径复制到/usr/local/include下即可(因为是找不到sys/videoio.h,所以得复制到usr/local/include/sys/目录下)

root@sundata:/data/szc/opencv/opencv-3.0.0/build# cp /usr/include/ptlib/videoio.h /usr/local/include/sys/

2)、某字段找不到、定义前已经使用

网上搜,查一下这个字段在哪个文件里,然后locate一下这个文件在系统中的位置,查看内容后复制一个有这个字段的,或者复制后对其进行修改。
比如wchar_t,网上找了半天发现此字段在wchar.h头文件里,就用上面的方法把wchar.h复制到/usr/loca/include目录下,但发现不好使,因为wchar.h里面也没有wchar_t。于是我又看了看系统里别的wchar.h(路径为/snap/gnome-3-34-1804/36/usr/include/x86_64-linux-gnu/bits/wchar.h),发现有这么一段话
/* The fallback definitions, for when __WCHAR_MAX__ or __WCHAR_MIN__
   are not defined, give the right value and type as long as both int
   and wchar_t are 32-bit types.  Adding L'\0' to a constant value
   ensures that the type is correct; it is necessary to use (L'\0' +
   0) rather than just L'\0' so that the type in C++ is the promoted
   version of wchar_t rather than the distinct wchar_t type itself.
   Because wchar_t in preprocessor #if expressions is treated as
   intmax_t or uintmax_t, the expression (L'\0' - 1) would have the
   wrong value for WCHAR_MAX in such expressions and so cannot be used
   to define __WCHAR_MAX in the unsigned case.  */

里面说,如果__WCHAR_MAX__或__WCHAR_MIN__没定义,只要wchar_t和int都是32位的类型,就会对__WCHAR_MAX__或__WCHAR_MIN__进行正确赋值,而且在升级后的C++版本中wchar_t没有被明确定义。那么我只好帮它定义wchar_t了,32位嘛,于是就有了修改头文件中的第二部分的修改

3)、unknown type name 'class'类:
像这些找不到的都是class、namespace、template等C++关键字,而编译打印出来的信息明明能找到我配置的g++。因此我也想不明白为何它一直用c去编译c++代码,这样肯定得报错。因此我的解决方法就是用#ifdef __cplusplus .... #endif包裹住报错关键字定义的内容,这个宏判断的意思就是判断当前编译器用的是是否是c++编译器g++,如果是的话,才执行宏判断里面的内容,否则就不执行
4)、其他
别的就直接上网搜

更好的解决方法——换OpenCV版本

如果发生这些莫名其妙的错误,最好的解决方法其实是升级OpenCV:如果上面那些方法都不行,或者出了无法解决的错误(我的是用10.0的CUDA编译3.0.0的OpenCV,不兼容),可以更新opencv的版本。下面这些操作都是在没有进行上面的修改下进行的,也就是从头开始(编译安装ffmpeg之后)

3.4.1版本的OpenCV及OpenCV_contrib

我clone了3.4.1的OpenCV以及3.4.1的OpenCV_contrib

下载xfeatures2d源文件

下载一些文件(链接: https://pan.baidu.com/s/1oT36HtuRiYPEgNbgJvrOqg 提取码:gsg2),复制到opencv_contrib-3.4.1/modules/xfeatures2d/src目录下

修改OpenCV文件

1)、修改OpenCV-3.4.1根目录下的CMakeLists.txt文件,在576行加上
...
include_directories("modules")

# ----------------------------------------------------------------------------
#  Path for build/platform -specific headers
# ----------------------------------------------------------------------------
....

2)、修改文件opencv-3.4.1/modules/stitching目录下的CMakeLists.txt,加上一句话:

include_directories("/home/rtlab/szc/opencv-3.4.1/modules/features2d/include/")

编译与安装

再使用命令行编译安装

root@rtlab-computer:/home/rtlab/szc/opencv-3.4.1/build# make -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D ENABLE_PRECOMPILED_HEADERS=OFF -D CUDA_GENERATION=Pascal -D OPENCV_EXTRA_MODULES_PATH=/home/rtlab/szc/opencv_contrib-3.4.1/modules -D WITH_CUDA=ON -D WITH_OPENCL=ON ..
root@rtlab-computer:/home/rtlab/szc/opencv-3.4.1/build# make -j10 && make install

此时编译就很顺利

配置

安装完后,如果不能运行测试用例,就要进行一些环境变量的配置
1)、修改 /etc/ld.so.conf文件,加上一句话
include /usr/local/lib

2)、修改/etc/profile

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH

3)、使能

(base) root@ubuntu:/home/szc/opencv/opencv-3.0.0/build# ldconfig
(base) root@ubuntu:/home/szc/opencv/opencv-3.0.0/build# source /etc/profile

检验

root@ubuntu:/home/szc/opencv/opencv-3.0.0/build# pkg-config opencv --modversion

如果能正确输出版本号,就成功了

结语

在选择要编译安装的OpenCV版本时,最好查看github中cmake/OpenCVDetectCUDA.cmake文件里有没有包含自己的CUDA版本(比如计算能力为6.X的就是Pascal),这样可以少走很多弯路。另外OpenCV里面的一些测试用例由于没有数据,无法运行;另有一些因为种种原因也不能运行通过,但只要能正确输出版本号,应该就说明我们安装成功了。

猜你喜欢

转载自blog.csdn.net/qq_37475168/article/details/109894648