tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测

系统:Ubuntu 18.04.1 LTS amd64
编译工具链: arm-linux-gcc version 7.3.1
一、 准备工作:
下载QT 5.12带集成开发环境(QT Creator)的可执行文件:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
下载QT5.12源码:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
下载opencv4.0.0源码:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
下载交叉编译工具链7.3.1:
https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabi/
选择gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabi.tar.xz
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
二、 安装QT Creator和PC版QT 5.12
在work目录下进入QT5.12文件夹,运行.run文件:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
需要更改权限,不然不能运行。
然后弹出图形化安装界面:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
Next->Skip->Next:
选择自己的路径:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
勾选所有
Next
同意协议
Install
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
安装完成。
Next
Finish。
创建一个带窗体的工程hello试试看是否成功:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
成功。
三、 编译PC端opencv4.0.0
进入opencv文件夹解压opencv4.0.0源码,直接右击解压:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
进入源码目录创建build_x86_64文件夹并进入:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
安装cmake-gui:
sudo apt-get install cmake-qt-gui
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
执行cmake-gui进入配置界面并填写如下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
点击configure 选择第一项 点击finish。

过程会自动下载一些缺少的库,需要等待一段时间。
修改CMAKE_INSTALL_PREFIX为/usr/local/opencv_4.0.0
修改CMAKE_BUILD_TYPE为Release
取消WITH_TIFF
点击generate生成Makefile
退出cmake-gui
在终端make –j4等待make完成。
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
sudo make install安装到刚才指定的位置:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测

配置opencv环境:
sudo gedit /etc/ld.so.conf
加入一行:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
sudo ldconfig
在QT creator中打开刚才创建的hello QT工程,配置工程如下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
Mainwindow.cpp 内容如下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
点击运行:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
证明一切正常,至此PC版的opencv配置完成。
四、 安装新版的交叉编译工具链v7.3.1
在安装这个之前请从PATH中移除了旧版本的工具链路径:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
解压下载的预编译好的工具链包,直接右击解压并将解压后的文件夹移动到/usr/local/arm下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
设置新工具链的环境变量写到.bashrc文件中:
sudo gedit ~/.bashrc
在文件最后添加:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
保存退出。
source ~/.bashrc
输出PATH看看:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
命令测试:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
建立软连接通过一个脚本完成:
Cd /usr/local/arm/arm-linux-gcc-7.3.1/bin
Sudo gedit link.sh
填入内容:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
执行脚本:
Sudo chmod 777 link.sh
./link.sh
建立的软连接如下图所示:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
查看版本:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
成功。
五、 交叉编译QT5.12
进入QT源码目录并解压,直接右击解压:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
进入源码目录编辑文件/qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf
加入这些:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
configure:
./configure -prefix /usr/local/arm/QT5.12.0/ -release -opensource -make libs -xplatform linux-arm-gnueabi-g++ -optimized-qmake -pch -qt-libjpeg -qt-zlib -no-opengl -skip qt3d -skip qtcanvas3d -skip qtpurchasing -no-sse2 -no-openssl -no-cups -no-glib -no-iconv -nomake examples -nomake tools -skip qtvirtualkeyboard
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
make –j4(至少需要一个多小时)
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
Sudo make install
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
配置默认的qmake,打开/usr/lib/x86_64-linux-gnu/qt-default/qtchooser/default.conf,将内容修改为:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
qmake –v
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
安装完成。
六、 交叉编译opencv_4.0.0
进入opencv4.0.0源码目录并创建build_arm文件夹:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
cmake-gui打开配置界面
配置如下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
点击configure
选择最后一项 Specify options for cross-compiling
并填入选择自己编译器路径。
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
Finish
等待生成configure。
修改CMAKE_INSTALL_PREFIX 为 /usr/local/arm/opencv_4.0.0(自己创建这个文件夹)
修改CMAKE_BUILD_TYPE 为 Release
取消BUILD_PROTOBUF、BUILD_OPENEXR、BUILD_TIFF、BUILD_ZLIB、WITH_TIFF、WITH_CUFFT、WITH_OPENCL、WITH_OPENCLAMDFFT、WITH_OPENCL_SVM、WITH_OPENCLAMDBLAS。
打开CMakeCache.txt 修改CMAKE_EXE_LINKER_FLAGS:STRING =

CMAKE_EXE_LINKER_FLAGS:STRING = -lpthread –lrt –ldl
保存。
点击generate生成makefile
关闭cmake-gui
make –j4
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
编译成功。
如果过程中抱错:#error: “No suitable threading library available”
打开3rdparty/protobuf/src/google/stubs/common.cc文件修改52行为:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
去掉#include<pthread.h>的限制条件。保存。
sudo make install 安装到指定位置
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
至此,opencv4.0.0交叉编译完成。
七、 网络挂载文件系统:
将上篇制作的文件系统拷贝到work下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
配置nfs server:
打开/etc/exports 设置如下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
重启nfs-server:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
重启开发板设置bootargs:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
reset:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
启动成功。
在文件系统中新建一个文件夹yjp并进入:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
之前装好的工具链没有测试过能不能正常使用,这里写个helloworld测试一下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
因为是通过网络挂载的,所以这里增加的内容都会在同步到开发板的文件系统里,在板子上执行程序:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
看到可以正常执行,所以工具链没问题。删掉测试文件hello hello.c hello.o
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
八、 交叉编译的QT库移植:
这里使用的文件系统是自做的(使用新版的工具链arm-linux-gcc7.3.1+busybox1.29.3制作的,制作过程省略,和上篇博客一样),所以它是纯净版的,里面什么库都没有,为了运行QT先把QT库拷贝到板子上,进入rootfs目录并执行:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
然后打开rootfs下的etc/init.d/rcS,设置内容为:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
然后在etc下新建文件mdev.conf设置内容为:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
(就是直接将友善的对应目录下的mdev.conf拷贝过来)
打开etc/profile文件,增加内容:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
然后在电脑端新建一个工程,拖一个按钮,拷贝一份源码到yjp文件夹下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
进入目录后:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
生成了可执行文件。
在板子上执行该文件:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
报错,解决方案:
定位到libQt5Core.so.5文件:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
再次在板子上运行:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
没有字库,我们把友善的字库文件夹直接拿过来:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
改一下权限:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
在板子上再次运行:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
同时在板子上:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
九、 人脸识别:
在刚才创建的opencvTest工程中将lena.jpg和人脸检测用到haarcascade_frontalface_default.xml拷贝到工程源码目录下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
打开该工程,设置UI为:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测

工程配置文件为:

QT       += core gui
INCLUDEPATH += /usr/local/opencv_4.0.0/include/opencv4 \
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_calib3d.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_core.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_features2d.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_flann.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_gapi.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_highgui.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_imgcodecs.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_imgproc.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_ml.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_objdetect.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_photo.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_stitching.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_video.so
LIBS += /usr/local/opencv_4.0.0/lib/libopencv_videoio.so
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = opencvTest
TEMPLATE = app
SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

Mainwindow.cpp文件为:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "opencv2/imgproc.hpp"
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/imgproc/types_c.h>
#include "QMessageBox"
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),   ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    imgSrc=imread("lena.jpg");
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_BTorigendisplay_clicked()
{
QImage img = MatToQImage(imgSrc);
ui->imglabel->clear();
ui->imglabel->setPixmap(QPixmap::fromImage(img));
}

void MainWindow::on_BTfacedection_clicked()
{
    Mat image=imgSrc.clone();
    QImage img =MatToQImage( DetectFace(image));
    ui->imglabel->clear();
ui->imglabel->setPixmap(QPixmap::fromImage(img));
}

void MainWindow::on_BTexit_clicked()
{
this->close();
}


QImage	 MainWindow::MatToQImage(cv::Mat mtx)
{
    switch (mtx.type())  {
    case CV_8UC3:
        {
            QImage img((const unsigned char *)(mtx.data), mtx.cols, mtx.rows, mtx.cols * 3, QImage::Format_RGB888);
            return img.rgbSwapped();
        }
        break;
    default:
        {
            QImage img;
            return img;
        }
        break;
    }
}
Mat  MainWindow::DetectFace(Mat image)
{
        CascadeClassifier ccf;   //创建分类器对象
       if(!ccf.load("haarcascade_frontalface_default.xml")) //加载训练文件
       {
           QMessageBox::warning(this,"error","haarcascade_forontalface_default.xml load failed!");
       return image;
        }

       vector<Rect> faces;  //创建一个容器保存检测出来的脸
        Mat gray;
        cvtColor(image,gray,CV_BGR2GRAY); //转换成灰度图,因为harr特征从灰度图中提取
        equalizeHist(gray,gray);  //直方图均衡行

        ccf.detectMultiScale(gray,faces,1.1,3,0,Size(10,10),Size(600,600)); //检测人脸

       for(vector<Rect>::const_iterator iter=faces.begin();iter!=faces.end();iter++)
        {
            rectangle(image,*iter,Scalar(0,0,255),2,8); //画出脸部矩形
       }
     return image;
}

点击运行,测试功能是否正常,发现不能正常读入图像,原因是Qt Creator在编译的时候会自己创建一个build-opencvTest-Desktop_Qt_5_12_GCC_64bit-Debug,那么我们把刚才的lena.jpg和haarcascade_frontalface_default.xml放在这个文件夹下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
重新运行:
点击OrigenDisplay:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
点击FaceDection:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
证明源代码写的没错,接下来就应该把源码拷贝一份进行交叉编译。
十、 将人脸识别工程移植到开发板:
先把opencv4.0.0库拷贝到板子上:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
改一下权限:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
在profile中导入opencv lib的库:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
保存退出。
把opencvTest工程拷贝一份到yjp文件夹:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
改一下权限:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
打开opencvTest.pro修改内容为:



QT       += core gui

INCLUDEPATH += /usr/local/arm/opencv_4.0.0/include/opencv4 \

LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_calib3d.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_core.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_features2d.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_flann.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_gapi.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_highgui.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_imgcodecs.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_imgproc.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_ml.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_objdetect.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_photo.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_stitching.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_video.so
LIBS += /usr/local/arm/opencv_4.0.0/lib/libopencv_videoio.so


greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = opencvTest
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

保存,编译工程:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
可以看到编译成功了,但是有一大堆warning,说什么库找不着,暂时忽略。
在板子上执行看看:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
报错,opencv的库找不着,但是它说的是…/…/lib下没有库,这是一个相对路径,那我们把opencv的库考到这个相对路径下:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
再在板子上执行:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
点OrigenDisplay
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
点FaceDection:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
点Exit:
tiny4412 移植最新版QT5.12+opencv4.0.0+人脸检测
至此全部移植成功。

但任然存在还有一些问题,程序只能在相对路径下运行,网上说跟opencv编译时有关,需要在toolchain.cmake文件中添加一行:
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
具体没实践。