最近产品需要做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 <iostream> 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<Rect> 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\n", 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: \n\t./stopdetect IMAGE\n"); return -1; } if(!cascade.load(CASCADE_FILE_PATH)) { printf("ERROR: Could not load classifier cascade !\n"); return -1; } image = imread(argv[1], 1); if(image.empty()) { printf("Could not read %s\n", argv[1]); return -1; } printf("Detecting STOP sign in %s\n", 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