openwrt 编译opencv

前言

最近要在openwrt上用到opencv,就想着如何去编译opencv。
发现openwrt在make menuconfig的时候没有opencv的选项。有两种办法编译。

  1. 在编译openwrt的时候,勾选交叉编译工具,最后自己去交叉编译opencv,最后自己导入到路由器中。(这样有个缺点,固件烧写的时候就不会打包进去。当然也有解决办法,编译好后,利用package的makefile-install,把东西打包进去,教程在本地笔记,过阵子上传)
  2. 利用package的方式导入,在makefile里面解决下载,编译,安装等问题。这个就比较好用点,opencv没有代理的话,速度也很感人。还有就是想用它编程,需要遵循openwrt的package包的规则。当然也有解决办法,就直接把include文件和lib文件给拷贝出来。

编译

这边着重说第二种方法。第一种实在太烦了,之前编过其他开发板的,一堆错误。得慢慢改。

准备工作

  1. 到源码目录的 package/libs 目录下,新建一个opencv目录,里面新建一个Makefile
cd package/libs
mkdir opencv
cd opencv
touch Makefile
  1. Makefile内容如下
# 
# Copyright (C) 2013-2014 wrtnode.com
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

include $(TOPDIR)/rules.mk

PKG_NAME:=opencv
PKG_VERSION:=3.0.0
PKG_RELEASE:=1

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).zip
PKG_SOURCE_URL:=http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/$(PKG_VERSION)/
PKG_MD5SUM:=09004c275d8092cbdf5b61675cecd399

PKG_LICENSE:=BSD-3-Clause
PKG_LICENSE_FILES:=LICENSE

include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk


define Package/opencv/Default/description
 OpenCV (Open Source Computer Vision Library) is an open source computer
 vision and machine learning software library. OpenCV was built to provide 
 a common infrastructure for computer vision applications and to accelerate 
 the use of machine perception in the commercial products. Being a 
 BSD-licensed product, OpenCV makes it easy for businesses to utilize 
 and modify the code.
endef

define Package/opencv
  SECTION:=libs
  CATEGORY:=Libraries
  TITLE:=OpenCV
  URL:=http://opencv.org/
  MAINTAINER:=WRTnode Team <pub@wrtnode.com>
  DEPENDS:=+libpthread +librt +libstdcpp +zlib +libjpeg 
endef


PKG_INSTALL:=1

CMAKE_OPTIONS += -DBUILD_opencv_gpu:BOOL=OFF \
	 -DWITH_1394:BOOL=OFF -DBUILD_opencv_stitching:BOOL=OFF \
	 -DBUILD_opencv_superres:BOOL=OFF -DBUILD_opencv_ts:BOOL=OFF 

define Build/InstallDev
	$(INSTALL_DIR) $(1)/usr/include
	$(CP) $(PKG_INSTALL_DIR)/usr/include/opencv $(1)/usr/include/
	$(CP) $(PKG_INSTALL_DIR)/usr/include/opencv2 $(1)/usr/include/
	$(INSTALL_DIR) $(1)/usr/lib
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libopencv* $(1)/usr/lib/
endef

define Package/opencv/install
	$(INSTALL_DIR) $(1)/usr/lib
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libopencv* $(1)/usr/lib/

endef

$(eval $(call BuildPackage,opencv))

编译

  1. 之前如果编译过openwrt,直接make menuconfig
    opencv的路径就在 iib -> opencv,勾上保存。
  2. 如果没有编译过的参考https://blog.csdn.net/weixin_43152585/article/details/112715789
  3. 最后执行 make V=99(opencv这种鬼东西是不会让你这么顺利通过的,出现错误再改)

解决编译出错问题

每个人遇到的可能不太一样,我把我编译遇到的问题记录一下。问题太多了,索性直接在source insight新建工程。有些是我凭感觉改的,或者是实在不知道怎么改了,能让他能编译过就行了。我会标注一下。

pp:44,
                 from /root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/hal/opencv_hal_pch_dephelp.cxx:1:
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/hal/include/opencv2/hal/intrin_cpp.hpp: In function 'cv::v_reg<_Tp, n> cv::operator~(const cv::v_reg<_Tp, n>&)':
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/hal/include/opencv2/hal/intrin_cpp.hpp:176:5: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
     for( int i = 0; i < n; i++ )
     ^~~
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/hal/include/opencv2/hal/intrin_cpp.hpp:178:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
         return c;
         ^~~~~~
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/hal/include/opencv2/hal/intrin_cpp.hpp: In function 'void cv::v_load_halves(const _Tp*, const _Tp*)':
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/hal/include/opencv2/hal/intrin_cpp.hpp:452:12: error: return-statement with a value, in function returning 'void' [-fpermissive]
     return c;
            ^
make[5]: *** [modules/hal/CMakeFiles/opencv

解决方法

1.for 循环加括号消除警告
2.return c注释了

/root/share/newifi/source/staging_dir/toolchain-mipsel_24kc_gcc-8.4.0_musl/lib/gcc/mipsel-openwrt-linux-musl/8.4.0/../../../../mipsel-openwrt-linux-musl/bin/ld: /root/share/newifi/source/staging_dir/toolchain-mipsel_24kc_gcc-8.4.0_musl/lib/gcc/mipsel-openwrt-linux-musl/8.4.0/../../../../mipsel-openwrt-linux-musl/lib/crt1.o: in function `_start_c':
/root/share/newifi/source/build_dir/toolchain-mipsel_24kc_gcc-8.4.0_musl/musl-1.1.24/crt/crt1.c:18: undefined reference to `main'
/root/share/newifi/source/staging_dir/toolchain-mipsel_24kc_gcc-8.4.0_musl/lib/gcc/mipsel-openwrt-linux-musl/8.4.0/../../../../mipsel-openwrt-linux-musl/bin/ld: /root/share/newifi/source/build_dir/toolchain-mipsel_24kc_gcc-8.4.0_musl/musl-1.1.24/crt/crt1.c:18: undefined reference to `main'
collect2: error: ld returned 1 exit status
make[5]: *** [modules/hal/CMakeFiles/pch_Generate_opencv_hal.dir/build.make:83: modules/hal/precomp.hpp.gch/opencv_hal_Release.gch] Error 1

解决方法

1.Makefile加上-D ENABLE_PRECOMPILED_HEADERS=OFF \

/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/core/src/parallel_pthreads.cpp:248:48: error: 'PTHREAD_RECURSIVE_MUTEX_INITIALIZER' was not declared in this scope
 #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/core/src/parallel_pthreads.cpp:248:48: note: in definition of macro 'PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP'
 #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/core/src/parallel_pthreads.cpp:248:48: note: suggested alternative: 'PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP'
 #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/core/src/parallel_pthreads.cpp:248:48: note: in definition of macro 'PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP'
 #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make[5]: *** [modules/core/CMakeFiles/opencv_core.dir/build.make:538: modules/core/CMakeFiles/opencv_core.dir/src/parallel_pthreads.cpp.o] Error 1
1. #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP {{{0}}}


[ 75%] Building CXX object modules/videoio/CMakeFiles/opencv_videoio.dir/src/cap_ffmpeg.cpp.o
In file included from /root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/videoio/src/cap_ffmpeg.cpp:45:
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/videoio/src/cap_ffmpeg_impl.hpp: In member function 'void CvCapture_FFMPEG::close()':
/root/share/newifi/source/build_dir/target-mipsel_24kc_musl/opencv-3.0.0/modules/videoio/src/cap_ffmpeg_impl.hpp:317:9: error: 'avcodec_free_frame' was not declared in this scope
         avcodec_free_frame(&picture);

解决方法
1.ffmpeg可能接口变动了,ffmpeg源码中找了个差不多名字的弄上去void av_frame_free(AVFrame **frame);
这里是懒得改了,应该要区分版本号的。眼前能过就行了,不管这么多。

然后又跳了一堆ffmpeg的问题。老问题

1.avcodec_alloc_frame替换成av_frame_alloc
2.有几个像素格式的宏定义。我下载了源码,看到在pixfmt.h中,一开始以为头文件引用问题
后面才发现名字改了,然后source insight搜索的出来,没发现。
全部改成了AV_xxxxxxx,一个一个慢慢改把,(用notepad++替换)
2.1 用AV_PIX_FMT替换PIX_FMT
2.2 用AVPixelFormat替换PixelFormat
2.3 用AV_CODEC_FLAG_GLOBAL_HEADER替换CODEC_FLAG_GLOBAL_HEADER
2.4 用AVFMT_NOFILE替换AVFMT_RAWPICTURE

最后剩下一个问题:

我路由器只有30M,编出opencv,几十M。没办法,路由器看来不适合跑opencv。
上一篇:利用openwrt编译添加zabbix_proxy3.4.10


下一篇:Linux环境下为bpi r2编译openwrt