最近做了一个图像增强程序,用到了OpenCV。为了方便发布,我将代码使用Golang
+GoCV
重写,但是编译的时候发现比较麻烦,特别记录一下,以备后查。
本文对应版本如下:
- Ubuntu 18.04.5 LTS
- Golang 1.15.6
- OpenCV 4.5.0
- GoCV 0.2.5
1. Golang环境准备
1.1 安装Golang
下载对应的包,然后解压,设置PATH
路径即可,不多说了。
1.2 设置GOPATH
使用go get
下载的包将下载到$GOPATH
目录中。
这里设置成/home/ubuntu/.go
。不设置的话将自动设置成~/go
目录。
1cd /home/ubuntu/.go
2export GOPATH=/home/ubuntu/.go
1.3 下载GoCV源码
1# 设置代理翻墙,要不然下载不了
2git config --global http.proxy=http://127.0.0.1:12346
3git config --global https.proxy=http://127.0.0.1:12346
4export http_proxy=http://127.0.0.1:12346
5export https_proxy=http://127.0.0.1:12346
6go get -v -u -d gocv.io/x/gocv
2. 开始编译
在GoCV的源码中,有一个Makefile文件,使用该Makefile可以简化OpenCV的编译过程。我是以此文件为基础编译的。
2.1 安装依赖库
1# 切换到源码目录
2ubuntu@testserver:~$ cd $GOPATH/src/gocv.io/x/gocv
3# 安装依赖库
4ubuntu@testserver:~/.go/src/gocv.io/x/gocv$ make deps
5sudo apt-get -y update
6sudo apt-get -y install unzip wget build-essential cmake curl git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev
2.2 下载相关源码
下载OpenCV
相关源码。记得挂代理。
1ubuntu@testserver:~/.go/src/gocv.io/x/gocv$ make download
2rm -rf /tmp/opencv
3mkdir /tmp/opencv
4cd /tmp/opencv
5curl -Lo opencv.zip https://github.com/opencv/opencv/archive/4.5.0.zip
6unzip -q opencv.zip
7curl -Lo opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.5.0.zip
8unzip -q opencv_contrib.zip
9rm opencv.zip opencv_contrib.zip
10cd -
2.3 编译
在编译之前需要对Makefile
进行一些修改。因为FFMpeg
、GTK
、DC1394
这几个功能的依赖库特别复杂,要实现静态编译非常麻烦,可能需要自己手工裁减编译这几个库。因为目前程序没有用到窗口、视频等方面的功能,所以直接裁减掉这几个功能。
修改方法是修改$GOPATH/src/gocv.io/x/gocv/Makefile
这个文件。添加-D WITH_FFMPEG=OFF -D WITH_GTK=OFF -D WITH_1394=OFF -D WITH_TIFF=OFF
这几个参数到目标build
里面的cmake
命令中即可。
1# Build OpenCV.
2build:
3 cd $(TMP_DIR)opencv/opencv-$(OPENCV_VERSION)
4 mkdir build
5 cd build
6 rm -rf *
7 #cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -D OPENCV_EXTRA_MODULES_PATH=$(TMP_DIR)opencv/opencv_contrib-$(OPENCV_VERSION)/modules -D BUILD_DOCS=OFF -D BUILD_EXAMPLES=OFF -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_opencv_java=NO -D BUILD_opencv_python=NO -D BUILD_opencv_python2=NO -D BUILD_opencv_python3=NO -D WITH_JASPER=OFF -DOPENCV_GENERATE_PKGCONFIG=ON ..
8 cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -D OPENCV_EXTRA_MODULES_PATH=$(TMP_DIR)opencv/opencv_contrib-$(OPENCV_VERSION)/modules -D BUILD_DOCS=OFF -D BUILD_EXAMPLES=OFF -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_opencv_java=NO -D BUILD_opencv_python=NO -D BUILD_opencv_python2=NO -D BUILD_opencv_python3=NO -D WITH_JASPER=OFF -D WITH_FFMPEG=OFF -D WITH_GTK=OFF -D WITH_1394=OFF -DOPENCV_GENERATE_PKGCONFIG=ON ..
9 $(MAKE) -j $(shell nproc --all)
10 $(MAKE) preinstall
11 cd -
注意WITH_TIFF=OFF
这个参数也可以不添加,不过要修改后面提到的CGO_LDFLAGS
。具体看下面的介绍。
然后可以执行编译了。这个编译耗费时间会比较长。我这边花了20+分钟。
1# 默认方式编译,编译出来动态库。我不用这种方式。
2ubuntu@testserver:~/.go/src/gocv.io/x/gocv$ make build
3# 我要编译静态库,所以添加BUILD_SHARED_LIBS=OFF
4ubuntu@testserver:~/.go/src/gocv.io/x/gocv$ make build BUILD_SHARED_LIBS=OFF
漫长的等待。
2.4 安装
1# 将编译好的库安装到系统中
2ubuntu@testserver:~/.go/src/gocv.io/x/gocv$ make sudo_install
3cd /tmp/opencv/opencv-4.5.0/build
4sudo make install
5sudo ldconfig
6cd -
7[sudo] password for ubuntu:
2.5 编译Golang程序
直接编译是无法通过的,需要设置CGO_CPPFLAGS
, CGO_LDFLAGS
两个环境变量,然后使用go build -tags customenv
编译。
CGO_CPPFLAGS
这个环境变量用于指定include文件的路径;可以通过pkg-config --cflags
这个命令获得其内容。
CGO_LDFLAGS
这个环境变量用于连接时期,主要指定lib文件路径及需要连接的库。可以通过pkg-config --libs
获得其主要内容。见下面的注释。
1# 使用`pkg-config --cflags opencv4`获得
2export CGO_CPPFLAGS="-I/usr/local/include/opencv4"
3# 使用`pkg-config --libs --static opencv4`获得主要内容。然后添加上`--static`这个参数。
4export CGO_LDFLAGS="--static -L/usr/local/lib -L/usr/local/lib/opencv4/3rdparty -L/tmp/opencv/opencv-4.5.0/build/lib -lopencv_gapi -lopencv_stitching -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm -lopencv_highgui -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hfs -lopencv_img_hash -lopencv_intensity_transform -lopencv_line_descriptor -lopencv_mcc -lopencv_quality -lopencv_rapid -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching -lopencv_tracking -lopencv_datasets -lopencv_text -lopencv_dnn -lopencv_plot -lopencv_videostab -lopencv_videoio -lopencv_xfeatures2d -lopencv_shape -lopencv_ml -lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect -lopencv_calib3d -lopencv_imgcodecs -lopencv_features2d -lopencv_flann -lopencv_xphoto -lopencv_photo -lopencv_imgproc -lopencv_core -littnotify -llibprotobuf -llibwebp -llibopenjp2 -lIlmImf -lquirc -lippiw -lippicv -lade -ljpeg -lpng -lz -ltiff -lfreetype -lharfbuzz -ljbig -llzma -lm -lpthread -lrt -lc -ldl"
另外,如果要支持TIFF
格式(前面Makefile
中没有添加WITH_TIFF=OFF
选项),则CPP_LDFLAGS
中还要加上:-ljbig -llzma
这两个参数,否则编译Go代码的时候会报错。
最后使用go build -v -tags customenv .
命令就可以编译了。
3. 编译中碰到的一些错误
编译Go代码的时候经常碰到各种undefined reference to
错误,这都是因为要链接的库没有在CPP_LDFLAGS中指定。找到对应的库,添加到参数中就好了。
3.1 jbg
1(.text+0x45): undefined reference to `jbg_enc_init'
2(.text+0x4d): undefined reference to `jbg_enc_out'
3(.text+0x55): undefined reference to `jbg_enc_free'
以上错误是需要libjbig
这个库,应该是TIFF格式需要的。如果关闭了TIFF格式支持,应该不会报上面的错误。添加-ljbig
就可以了。
3.2 lzma
1(.text+0x1a0): undefined reference to `lzma_code'
以上错误是需要liblzma
这个库,应该也是TIFF格式需要的。添加上-llzma
参数解决。
3.3 dlopen、getaddrinfo
1warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
libc
1Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
这两个警告信息暂时找不到解决办法。
4. 其他一些CGO编译相关的指令
go clean -cache
可以清除已经编译的缓存。
附录、参考资料
- GoCV Home
- GoCV @Github
- Building OpenCV as a static library leads to thousands of undefined references
- Pls add static link opencv #217
- Golang 1.9 build warning : Using ‘getaddrinfo’ in statically linked applications requires at runtime the shared libraries from the glibc version used for linking #21421
- OpenCV configuration options reference
- ubuntu安装opencv无法下载IPPICV的问题 ippicv_2020_lnx_intel64_20191018_general.tgz
- How to build more compact OpenCV applications on Linux