arm-linux移植opencv心历路程

时间:2021-05-06 16:37:45

最近产品需要做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