arm-linux移植opencv心历路程

2019-07-12 17:35发布

最近产品需要做STOP路标识别,开始了解人脸识别,OpenCV等相关技术,下面是我学习一些经历。 传统人脸识别过程: 1. 训练样本,得到haar分类器(一个.xml格式文件) 2. 将图片套入haar分类器检测

一、理论知识:

图像金字塔 https://baike.baidu.com/item/%E5%9B%BE%E5%83%8F%E9%87%91%E5%AD%97%E5%A1%94 HOG特征,LBP特征和Haar-like特征 https://blog.csdn.net/q123456789098/article/details/52748918 adaboost算法原理 http://www.360doc.com/content/14/1109/12/20290918_423780183.shtml 强烈推荐下面链接的介绍 https://zhuanlan.zhihu.com/p/31427728 https://zhuanlan.zhihu.com/p/35058334 还有其他一些知识:比如机器学习,决策树,SVM,随机森林等 更高级的机器学习方法:深度学习

二、OpenCV介绍

opencv是一个计算机视觉库,详细我就不介绍了 了解点: opencv2.x和3.x有什么区别? opencv的模块组成? https://blog.csdn.net/zkl99999/article/details/48676487 https://docs.opencv.org/3.3.0/index.html samples目录是一个非常重要的目录,学习opencv可以用过从samples入手。(我是从facedetect.cpp入手学习的)

三、OpenCV移植

opencv是用cmake来生成Makefile的,可以先大概了解下cmake。 arm-linux移植我参考的是下面的链接:(用cmake-gui方式) https://blog.csdn.net/gatieme/article/details/49080355 (默认是生成动态库,如果想生成静态库,只需将BUILD_SHARED_LIBS设置为OFF) 同理在ubuntu上面移植opencv也可以用上面链接的方法, 只是cmake-gui第一步不选着Specify options for cross-compiling,而是用默认的Use default native compilers即可。
遇到的问题: opencv程序用静态库编译不成功(动态库是可以的) 分析:静态库更其他一些库有关联,比如:图像处理库libopencv_imgproc.a依赖于libjpg,libpng等。 注意:opencv源码有一个3rdparty的目录,主要是包含第三方的库(如:jpg、png、tiff等图片的开源解码库) 解决办法:修改Makefile(确切来说是修改CMakeCache.txt),或者在cmake-gui界面配置的时候将jasper,jpeg,png,tbb,ipp,zlib等模块都配置成需要编译 arm-hisiv300-linux-g++ stopdetect.cpp -o static_stopdetect -I/opencv/output/include -L/opencv/output/lib -L/opencv/build/3rdparty/lib -lopencv_dnn -lopencv_ml -lopencv_objdetect -lopencv_shape -lopencv_stitching -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_imgproc -lopencv_flann -lopencv_core -lpthread -lIlmImf -llibjpeg -llibpng -llibtiff -lzlib -ldl -llibjasper -llibwebp 注意: -lIlmImf -llibjpeg -llibpng -llibtiff -lzlib -ldl -llibjasper -llibwebp这些库是有顺序要求的,可以按我这个来
如果是在ubuntu编译静态库时,ippicv下载失败 解决办法:打开build目录的CMakeDownloadLog.txt,里面有所需要的ippicv安装包官方下载路径。通过windows下载下来拷贝到源码目录的3rdparty/ippicv,并重命名为下载失败的ippicv安装包名字(一般是前面加一大串字符,类似MD5码那种

四、代码示例

#include "opencv2/objdetect.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include using namespace std; using namespace cv; #define CASCADE_FILE_PATH "/mnt/stopsign_classifier.xml" void detectAndDraw(Mat& img, CascadeClassifier& cascade) { double t = 0; Mat gray; vector stopsigns; const static Scalar colors[] = { Scalar(255,0,0), Scalar(255,128,0), Scalar(255,255,0), Scalar(0,255,0), Scalar(0,128,255), Scalar(0,255,255), Scalar(0,0,255), Scalar(255,0,255) }; cvtColor(img, gray, COLOR_BGR2GRAY); equalizeHist(gray, gray); t = (double)getTickCount(); cascade.detectMultiScale(gray, stopsigns, 1.1, 10) ; t = (double)getTickCount() - t; printf("detect results: time = %g ms stopsignsNum = %d ", t*1000/getTickFrequency(), stopsigns.size()); for (size_t i = 0; i < stopsigns.size(); i++) { Rect r = stopsigns[i]; Point center; Scalar color = colors[i%8]; rectangle(img, cvPoint(cvRound(r.x), cvRound(r.y)), cvPoint(cvRound(r.x + r.width-1), cvRound(r.y + r.height-1)), color, 2); } imshow("result", img); /* remove if run in arm-linux */ //imwrite("/mnt/dvr_handle.jpg", img); } int main(int argc, const char** argv) { Mat image; CascadeClassifier cascade; if(argc != 2) { printf("USAGE: ./stopdetect IMAGE "); return -1; } if(!cascade.load(CASCADE_FILE_PATH)) { printf("ERROR: Could not load classifier cascade ! "); return -1; } image = imread(argv[1], 1); if(image.empty()) { printf("Could not read %s ", argv[1]); return -1; } printf("Detecting STOP sign in %s ", argv[1]); detectAndDraw(image, cascade); waitKey(0); /* remove if run in arm-linux */ return 0; }

五、opencv的API和数据类型介绍

detectMultiScale函数介绍:
https://blog.csdn.net/Cooli7wa/article/details/53959195
MAT类型(矩阵,matrix的缩写)介绍 —— 图像容器
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/core/mat%20-%20the%20basic%20image%20container/mat%20-%20the%20basic%20image%20container.html Scalar类型
https://blog.csdn.net/liuweiyuxiang/article/details/76929534

六、其他

如果编译的是so库,可以先给用arm-linux-strip给库“脱衣服”在放入开发板中; 同理,如果是静态库,则给生成的可执行程序strip