OpenCV是計算機視覺算法開發(fā)常用的工具逮栅。如果我們需要在嵌入式設(shè)備上運行opencv护锤,那么就需要交叉編譯,將它移植到對應(yīng)平臺上缔俄。但是有些嵌入式平臺的存儲空間有限,能節(jié)省1MB也有相當(dāng)大的作用器躏。OpenCV帶了很多用不到的東西俐载,如果對OpenCV做裁剪,可以節(jié)省不少空間登失。
準(zhǔn)備工作
- 下載源碼
在https://opencv.org/releases/下載OpenCV的源碼包瞎疼,我這里用的是3.4.10。 - 準(zhǔn)備交叉編譯器
需要提前安裝好海思的交叉編譯器壁畸,并配置到環(huán)境變量。 - 安裝cmake
ubuntu/deepin/debian系統(tǒng)下直接apt install cmake make
即可茅茂。
如何編譯捏萍?
參考網(wǎng)上的教程,要用cmake-gui來配置空闲,但是令杈,實際上編譯用cmake命令行,指定交叉編譯器碴倾,然后配置一些目標(biāo)平臺的參數(shù)就可以了逗噩。
首先解壓源碼包掉丽,然后創(chuàng)建build和output文件夾,用來進行編譯以及保存編譯好的庫异雁。
unzip opencv-3.4.10
cd opencv-3.4.10
mkdir output build
cd build
然后使用cmake進行編譯捶障。這里指定交叉編譯器,然后配置輸出文件夾為上面創(chuàng)建的../output
纲刀。由于是嵌入式平臺项炼,沒有g(shù)tk之類的圖形庫,所以選擇WITH_GTK=OFF
示绊。OpenCV默認調(diào)用系統(tǒng)的zlib锭部,在嵌入式平臺上,需要重新編譯面褐,所以添加選項BUILD_ZLIB=ON
和OPENCV_FORCE_3RDPARTY_BUILD=ON
拌禾。
cmake ../ \
-DCMAKE_C_COMPILER=arm-himix200-linux-gcc \
-DCMAKE_CXX_COMPILER=arm-himix200-linux-g++ \
-DOPENCV_FORCE_3RDPARTY_BUILD=ON \
-DBUILD_ZLIB=ON \
-DWITH_GTK=OFF \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_BUILD_TYPE=RELEASE \
-DCMAKE_INSTALL_PREFIX=../output
等待cmake執(zhí)行完成后,就可以進行編譯了展哭。使用make -j && make install
命令湃窍,完成編譯以,并把編譯好的庫存到指定位置摄杂。
進行裁剪
這里為了展示編譯效果坝咐,替換掉make,使用ninja build來進行編譯析恢,因為ninja build可以顯示出需要編譯的文件的數(shù)量墨坚,而make只顯示編譯的百分比。ninja build的簡介可以看這里ninja build簡介
實際上效果是相同的映挂。cmake只是一個編譯信息生成工具泽篮,真正執(zhí)行編譯的是make或者ninja build。使用時柑船,cmake添加
-GNinja
參數(shù)即可生成ninja build所需要的文件帽撑,然后就可以用ninja 來進行編譯了。下面會使用cmake + ninja build
的方式來進行編譯鞍时,實際使用cmake + make
也可以亏拉。從ninja build的截圖可以看到,需要處理(編譯逆巍、鏈接)1283個對象(包括源碼及塘、編譯中間產(chǎn)物.o),生成22MB的庫文件锐极。
a.裁剪不需要的OpenCV組件
裁剪掉不需要的組件是最簡單的方法笙僚。先看下opencv包含了什么東西。
通常灵再,在嵌入式端肋层,比如海思這種芯片亿笤,有對視頻解碼的硬件,而這種平臺CPU性能并不強栋猖,所以O(shè)penCV關(guān)于視頻解碼的部分净薛,可以完全干掉。在海思上掂铐,有深度學(xué)習(xí)推理硬件NNIE罕拂,所以O(shè)penCV的機器學(xué)習(xí)、深度學(xué)習(xí)的模塊也可以干掉全陨。opencv_highgui是用來顯示圖像的爆班,在海思平臺,沒有這種圖像顯示的設(shè)備辱姨,關(guān)于顯示是用海思專門的模塊實現(xiàn)的柿菩,所以highgui也干掉。
實際上雨涛,一般在海思平臺開發(fā)有關(guān)NNIE的應(yīng)用枢舶,用OpenCV最多的就是其中數(shù)據(jù)表示方式,比如cv::Mat替久、cv::Rect之類的凉泄,還有一些圖像處理的功能。此外蚯根,在測試時后众,也可能對圖像做讀寫操作。所以颅拦,這里我只留下了opencv_core蒂誉、opencv_imgproc、opencv_imgcodecs這三個模塊距帅。至于opencv_superres右锨、opencv_feature2d等模塊,可以按需保留碌秸,但是又有多少人會在嵌入式端用CPU來做超分辨绍移、圖像特征點這些事呢?
所以讥电,按照上面裁剪的方法登夫,寫出cmake命令。
cmake ../ \
-DCMAKE_C_COMPILER=arm-himix200-linux-gcc \
-DCMAKE_CXX_COMPILER=arm-himix200-linux-g++ \
-DOPENCV_FORCE_3RDPARTY_BUILD=ON \
-DBUILD_ZLIB=ON \
-DWITH_GTK=OFF \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_opencv_ts=OFF \
-DBUILD_opencv_shape=OFF \
-DBUILD_opencv_stitching=OFF \
-DBUILD_opencv_apps=OFF \
-DBUILD_opencv_calib3d=OFF \
-DBUILD_opencv_dnn=OFF \
-DBUILD_opencv_features2d=OFF \
-DBUILD_opencv_flann=OFF \
-DBUILD_opencv_highgui=OFF \
-DBUILD_opencv_ml=OFF \
-DBUILD_opencv_objdetect=OFF \
-DBUILD_opencv_photo=OFF \
-DBUILD_opencv_video=OFF \
-DBUILD_opencv_videoio=OFF \
-DBUILD_opencv_videostab=OFF \
-DCMAKE_BUILD_TYPE=RELEASE \
-DCMAKE_INSTALL_PREFIX=../output
可以看到允趟,現(xiàn)在只需處理601個文件,比之前少了一半多鸦致,而OpenCV的庫也只要9.9MB
b.繼續(xù)裁剪opencv
在編譯選項里潮剪,可以看到涣楷,還有很多WITH_XXX的編譯選項,這些也有很多不需要抗碰,來刪一點點干掉狮斗。
要被干掉的選項 | 含義 |
---|---|
WITH_GTK | 圖形庫GTK |
WITH_GTK_2_X | 圖形庫GTK |
WITH_CUDA | NVIDIA的CUDA |
WITH_IPP | 嚶特爾CPU加速的一個東西 |
WITH_OPENCL | OPENCL異構(gòu)計算 |
WITH_OPENCLAMDBLAS | 按摩店的OPENCL的blas |
WITH_QUIRC | 二維碼識別 |
WITH_OPENCLAMDFFT | 按摩店的OPENCL的fft |
WITH_1394 | 1394,一種接口,可以連接相機 |
WITH_FFMPEG | 解碼視頻 |
WITH_WEBP | webp圖像格式 |
WITH_TIFF | tiff圖像格式 |
WITH_OPENEXR | openexr圖像,工業(yè)光魔(特效公司)家的圖像格式 |
WITH_PNG | png圖像格式 |
WITH_PROTOBUF | protobuf,估計是dnn模塊加載caffe模型的 |
WITH_GSTREAMER | Gstreamer弧蝇,多用于處理流媒體 |
WITH_IMGCODEC_SUNRASTER | SUNRASTER圖像格式解碼 |
以上是需要被干掉的一些東西碳褒。部分的解釋可能不準(zhǔn)確,如有問題請指正看疗。在海思這種平臺沙峻,圖像最常用的格式Y(jié)UV、BGR(RGB)格式两芳,還有壓縮過的jpg/jpeg格式摔寨,以及未經(jīng)過壓縮的bmp格式。以上配置怖辆,可以按照個人需要來進行設(shè)置是复。以上的cmake命令如下:
cmake ../ \
-DCMAKE_C_COMPILER=arm-himix200-linux-gcc \
-DCMAKE_CXX_COMPILER=arm-himix200-linux-g++ \
-DOPENCV_FORCE_3RDPARTY_BUILD=ON \
-DBUILD_ZLIB=ON \
-DWITH_GTK=OFF \
-DWITH_GTK=OFF \
-DWITH_GTK_2_X=OFF \
-DWITH_CUDA=OFF \
-DWITH_IPP=OFF \
-DWITH_OPENCL=OFF \
-DWITH_OPENCLAMDBLAS=OFF \
-DWITH_QUIRC=OFF \
-DWITH_OPENCLAMDFFT=OFF \
-DWITH_1394=OFF \
-DWITH_FFMPEG=OFF \
-DWITH_WEBP=OFF \
-DWITH_TIFF=OFF \
-DWITH_OPENEXR=OFF \
-DWITH_PNG=OFF \
-DWITH_PROTOBUF=OFF \
-DWITH_GSTREAMER=OFF \
-DWITH_IMGCODEC_SUNRASTER=OFF \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_opencv_ts=OFF \
-DBUILD_opencv_shape=OFF \
-DBUILD_opencv_stitching=OFF \
-DBUILD_opencv_apps=OFF \
-DBUILD_opencv_calib3d=OFF \
-DBUILD_opencv_dnn=OFF \
-DBUILD_opencv_features2d=OFF \
-DBUILD_opencv_flann=OFF \
-DBUILD_opencv_highgui=OFF \
-DBUILD_opencv_ml=OFF \
-DBUILD_opencv_objdetect=OFF \
-DBUILD_opencv_photo=OFF \
-DBUILD_opencv_video=OFF \
-DBUILD_opencv_videoio=OFF \
-DBUILD_opencv_videostab=OFF \
-DCMAKE_BUILD_TYPE=RELEASE \
-DCMAKE_INSTALL_PREFIX=../output
以上配置,需要處理的文件數(shù)量以及生成的庫的大小如下圖:
現(xiàn)在可以看到竖螃,opencv已經(jīng)被壓縮到很小了淑廊。
c.還能不能再小特咆?
已經(jīng)完成了opencv的裁剪季惩,現(xiàn)在已經(jīng)是裁剪到不能再裁剪了,那么能不能再讓它變小點呢坚弱?能蜀备,當(dāng)然能!這時候就要從編譯器的角度來看了荒叶。
我們使用file命令來看下編譯產(chǎn)物碾阁。這里,我們可以看到些楣,這個是arm平臺下的動態(tài)庫脂凶,是not stripped的。這也就是說愁茁,這里包含符號表蚕钦、重定位信息等多余的東西。
我們再看編譯選項
-s
和-Os
-s
是鏈接器的選項鹅很,是在鏈接時刪除所有的符號表等信息嘶居,實際使用的時候,傳給鏈接器ld,當(dāng)然傳給gcc/g++也可以實現(xiàn)相同功能邮屁,-Os
是針對體積進行優(yōu)化整袁。所以,在編譯的時候佑吝,設(shè)置編譯選項為-s -Os
坐昙,就可以達到目的。現(xiàn)在芋忿,cmake命令如下:
cmake ../ \
-DCMAKE_C_COMPILER=arm-himix200-linux-gcc \
-DCMAKE_CXX_COMPILER=arm-himix200-linux-g++ \
-DOPENCV_FORCE_3RDPARTY_BUILD=ON \
-DBUILD_ZLIB=ON -DWITH_GTK=OFF -DWITH_GTK=OFF \
-DWITH_GTK_2_X=OFF -DWITH_CUDA=OFF -DWITH_IPP=OFF \
-DWITH_OPENCL=OFF -DWITH_OPENCLAMDBLAS=OFF \
-DWITH_QUIRC=OFF -DWITH_OPENCLAMDFFT=OFF \
-DWITH_1394=OFF -DWITH_FFMPEG=OFF -DWITH_WEBP=OFF \
-DWITH_TIFF=OFF -DWITH_OPENEXR=OFF -DWITH_PNG=OFF \
-DWITH_PROTOBUF=OFF -DWITH_GSTREAMER=OFF -DWITH_IMGCODEC_SUNRASTER=OFF \
-DBUILD_SHARED_LIBS=ON -DBUILD_opencv_ts=OFF \
-DBUILD_opencv_shape=OFF -DBUILD_opencv_stitching=OFF \
-DBUILD_opencv_apps=OFF -DBUILD_opencv_calib3d=OFF \
-DBUILD_opencv_dnn=OFF -DBUILD_opencv_features2d=OFF \
-DBUILD_opencv_flann=OFF -DBUILD_opencv_highgui=OFF \
-DBUILD_opencv_ml=OFF -DBUILD_opencv_objdetect=OFF \
-DBUILD_opencv_photo=OFF -DBUILD_opencv_video=OFF \
-DBUILD_opencv_videoio=OFF -DBUILD_opencv_videostab=OFF \
-DCMAKE_BUILD_TYPE=RELEASE \
-DCMAKE_INSTALL_PREFIX=../output \
-DCMAKE_CXX_FLAGS="-s -Os" -DCMAKE_C_FLAGS="-s -Os"
在命令行中指定編譯選項炸客,cmake會自動把這些選項與cmake生成的選項合并。
執(zhí)行編譯戈钢,和上面相同痹仙,需要處理283個文件∧嫒ぃ看下生成的文件:
現(xiàn)在已經(jīng)是stripped的了蝶溶。然后現(xiàn)在生成的庫的只剩了5.2MB的大小,相比之前宣渗,小了非常多抖所。
結(jié)束
在某些嵌入式設(shè)備上,存儲空間非常緊張痕囱,通過這樣的方法以及思路可以節(jié)省不少的存儲空間田轧。
以上編譯opencv的命令如下,直接復(fù)制粘貼了執(zhí)行就可以鞍恢,當(dāng)然也可以替換了交叉編譯器傻粘,來編譯不同平臺的庫。
cmake ../ \
-DCMAKE_C_COMPILER=arm-himix200-linux-gcc \
-DCMAKE_CXX_COMPILER=arm-himix200-linux-g++ \
-DOPENCV_FORCE_3RDPARTY_BUILD=ON \
-DBUILD_ZLIB=ON -DWITH_GTK=OFF -DWITH_GTK=OFF \
-DWITH_GTK_2_X=OFF -DWITH_CUDA=OFF -DWITH_IPP=OFF \
-DWITH_OPENCL=OFF -DWITH_OPENCLAMDBLAS=OFF \
-DWITH_QUIRC=OFF -DWITH_OPENCLAMDFFT=OFF \
-DWITH_1394=OFF -DWITH_FFMPEG=OFF -DWITH_WEBP=OFF \
-DWITH_TIFF=OFF -DWITH_OPENEXR=OFF -DWITH_PNG=OFF \
-DWITH_PROTOBUF=OFF -DWITH_GSTREAMER=OFF -DWITH_IMGCODEC_SUNRASTER=OFF \
-DBUILD_SHARED_LIBS=ON -DBUILD_opencv_ts=OFF \
-DBUILD_opencv_shape=OFF -DBUILD_opencv_stitching=OFF \
-DBUILD_opencv_apps=OFF -DBUILD_opencv_calib3d=OFF \
-DBUILD_opencv_dnn=OFF -DBUILD_opencv_features2d=OFF \
-DBUILD_opencv_flann=OFF -DBUILD_opencv_highgui=OFF \
-DBUILD_opencv_ml=OFF -DBUILD_opencv_objdetect=OFF \
-DBUILD_opencv_photo=OFF -DBUILD_opencv_video=OFF \
-DBUILD_opencv_videoio=OFF -DBUILD_opencv_videostab=OFF \
-DCMAKE_BUILD_TYPE=RELEASE \
-DCMAKE_INSTALL_PREFIX=../output \
-DCMAKE_CXX_FLAGS="-s -Os" -DCMAKE_C_FLAGS="-s -Os"