前言
最近要在openwrt上用到opencv,就想着如何去编译opencv。
发现openwrt在make menuconfig的时候没有opencv的选项。有两种办法编译。
- 在编译openwrt的时候,勾选交叉编译工具,最后自己去交叉编译opencv,最后自己导入到路由器中。(这样有个缺点,固件烧写的时候就不会打包进去。当然也有解决办法,编译好后,利用package的makefile-install,把东西打包进去,教程在本地笔记,过阵子上传)
- 利用package的方式导入,在makefile里面解决下载,编译,安装等问题。这个就比较好用点,opencv没有代理的话,速度也很感人。还有就是想用它编程,需要遵循openwrt的package包的规则。当然也有解决办法,就直接把include文件和lib文件给拷贝出来。
编译
这边着重说第二种方法。第一种实在太烦了,之前编过其他开发板的,一堆错误。得慢慢改。
准备工作
- 到源码目录的 package/libs 目录下,新建一个opencv目录,里面新建一个Makefile
cd package/libs
mkdir opencv
cd opencv
touch Makefile
- 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))
编译
- 之前如果编译过openwrt,直接make menuconfig
opencv的路径就在 iib -> opencv,勾上保存。 - 如果没有编译过的参考https://blog.csdn.net/weixin_43152585/article/details/112715789
- 最后执行 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。