嵌入式学习-QT-Day10
嵌入式学习-QT-Day10
十、OpenCV
1、OpenCV介绍
2、环境搭建
3、验证环境
4、灰度处理
5、人脸检测
6、摄像头捕捉
6.1 摄像头单帧捕捉
6.2 摄像头连续捕捉
十、OpenCV
1、OpenCV介绍
OpenCV(Open Source Computer Visio n Library)是一个开源的计算机视觉库,它提供了丰富的图像处理和计算机视觉功能。该库由英特尔公司发起,并在 BSD 许可证下发布,因此它是免费的,且开放源代码。
OpenCV默认使用的色彩空间BGR(蓝、绿、红)而不是RGB(红、绿、蓝)。两种通道需要在代码之间相互转换。
应用非常广泛:
人机交互 物体识别 图像分割
人脸识别 自动驾驶
2、环境搭建
OpenCV支持不同的开发语言和开发环境,本次搭建的开发环境,基于Qt5.4
整个环境配置步骤如下:
把OpenCV的压缩包放到D盘根目录中。
解压(解压之后注意层级,只有一个opencv的目录层级)
再windows的环境变量Path中添加OpenCV的路径。
上面的路径为:
D:\opencv\opencv3.4-install\install\x86\mingw\bin
逐级点击确定
重启电脑
3、验证环境
创建一个简单的Qt项目尝试调用OpenCV的功能,操作步骤如下:
随便创建一个Qt的项目
项目创建完成后,在.pro文件中,添加以下配置项:
INCLUDEPATH += D:/opencv/opencv3.4-install/install/include
INCLUDEPATH += D:/opencv/opencv3.4-install/install/include/opencv
INCLUDEPATH += D:/opencv/opencv3.4-install/install/include/opencv2
LIBS += D:/opencv/opencv3.4-install/install/x86/mingw/lib/libopencv_*.a
点击项目的小锤子图标,重新构建,使项目构建出构建目录。随便找一张图片,放置到构建目录中,并命名为demo(名称随便,没有中文和特殊字符即可)
在主函数中编写一个简单的读取图片并展示的功能。
main.cpp
#include "dialog.h"
#include <QApplication>
#include <QDebug>
#include <opencv2/opencv.hpp> // 头文件,.hpp也是C++的文件格式
using namespace cv; // 名字空间
int main(int argc, char *argv[])
{
// QApplication a(argc, argv);
// Dialog w;
// w.show();
// 读取图片
// 参数为读取的图片文件名称
// Mat 矩阵,最原始的数学表示图像的方式
Mat src = imread("demo.jpg");
if(!src.data) // 如果没有数据,表示读取失败
{
qDebug() << "读取图片失败";
}
// 给窗口设置标题,并设置图片显示模式为自动
namedWindow("窗口",CV_WINDOW_AUTOSIZE);
// 展示图片到窗口
imshow("窗口",src);
// 窗口长期保持(0表示无限等待)。
waitKey(0);
return 0;
}
实现效果:
4、灰度处理
图像灰度化是将一幅彩色的图像转换为灰度图像的过程。在灰度图像中,每个像素只包含一个灰度值,而不是彩色图像中的红、绿、蓝三个通道。灰度图像通常用于简化图像处理和分析,因为它们只包含亮度信息,而没有颜色信息。
图像灰度化的应用包括图像处理、机算机视觉、模式识别等领域。它有助于减少数据维度,简化图像处理算法,并提供更好的对比度和亮度信息,使图像特征更容易分析和识别。
main.cpp
#include "dialog.h"
#include <QApplication>
#include <QDebug>
#include <opencv2/opencv.hpp> // 头文件,.hpp也是C++的文件格式
using namespace cv; // 名字空间
int main(int argc, char *argv[])
{
// QApplication a(argc, argv);
// Dialog w;
// w.show();
// 读取图片
// 参数为读取的图片文件名称
// Mat 矩阵,最原始的数学表示图像的方式
Mat src = imread("kk.jpg");
if(!src.data) // 如果没有数据,表示读取失败
{
qDebug() << "读取图片失败";
}
Mat gray;
// cvtColor:转换颜色空间
// 参数1:src原始图像数据
// 参数2:转换后的图像数据
// 参数3:转换方式
cvtColor(src,gray,COLOR_BGR2GRAY);
// 给窗口设置标题,并设置图片显示模式为自动
namedWindow("窗口",CV_WINDOW_AUTOSIZE);
// 展示图片到窗口
imshow("窗口",src);
imshow("gray",gray);
// 窗口长期保持(0表示无限等待)。
waitKey(0);
return 0;
}
原图 灰度图
5、人脸检测
检测人脸是靠OpenCV的级联分类器来完成的,级联分类器本身并不仅仅能查找人脸,理论上可以查找任何的物体。级联分类器需要一个数据模型,我们可以直接使用Opencv已经训练好的一些模型。
模型目录在:
里面有很多xml文件。
这些包括眼睛、全身、车牌、猫、狗、人脸。根据自己的需要选择对应的模型即可。
需要通过CascadeClassifier类来加载分类器
CascadeClassifier classifier("xxx/install/etc/haarcascades/haarcascade_frontalface_alt2.xml");
通过CascadeClassifier的deterctMltiScale方法来检测是否存在人脸。
// 检测是否有目标(人脸、人眼等)
// 参数1:待检测的灰度图
// 参数2:查找到的目标矩形输出
void detectMultiScale(InputArray image,CV_OUT std::vector<Rect>& objects);
// 识别到的区域结果会存储到这个向量中
vector<Rect> faces;
classifier.detectMultiScale(gray,faces);
通过vector.size方法可以获取到识别到的人脸。进行画框。可能会有多张人脸(用循环)
// 循环遍历出所有的人脸
for(int i = 0; i < faces.size(); i++)
{
// 在原图上画出选定框,标定人脸
// 参数1:原始图像数据
// 参数2:表示标定第几张人脸
// 参数3:标定框的颜色【BGR】
// 参数4:框的线条粗度
rectangle(src,faces[i],Scalar(255,0,0),3);
}
main.cpp
#include "dialog.h"
#include <QApplication>
#include <QDebug>
#include <vector>
#include <opencv2/opencv.hpp> // 头文件,.hpp也是C++的文件格式
using namespace cv; // 名字空间
using namespace std;
int main(int argc, char *argv[])
{
// QApplication a(argc, argv);
// Dialog w;
// w.show();
// 加载人脸分类器(识别模型)
CascadeClassifier classifier = CascadeClassifier("D:/opencv/opencv3.4-install/install/etc/haarcascades/haarcascade_frontalface_alt2.xml");
// 读取图片
// 参数为读取的图片文件名称
// Mat 矩阵,最原始的数学表示图像的方式
Mat src = imread("demo.jpg");
if(!src.data) // 如果没有数据,表示读取失败
{
qDebug() << "读取图片失败";
}
Mat gray;
// cvtColor:转换颜色空间
// 参数1:src原始图像数据
// 参数2:转换后的图像数据
// 参数3:转换方式
cvtColor(src,gray,COLOR_BGR2GRAY);
// 识别到的区域结果会存储到这个向量中
vector<Rect> faces;
classifier.detectMultiScale(gray,faces);
// 循环遍历出所有的人脸
for(int i = 0; i < faces.size(); i++)
{
// 在原图上画出选定框,标定人脸
// 参数1:原始图像数据
// 参数2:表示标定第几张人脸
// 参数3:标定框的颜色【BGR】
// 参数4:框的线条粗度
rectangle(src,faces[i],Scalar(255,0,0),3);
}
// 给窗口设置标题,并设置图片显示模式为自动
namedWindow("窗口",CV_WINDOW_AUTOSIZE);
// 展示图片到窗口
imshow("窗口",src);
// 窗口长期保持(0表示无限等待)。
waitKey(0);
return 0;
}
6、摄像头捕捉
6.1 摄像头单帧捕捉
OpenCV提供了VideoCapture类来处理视频流,利用这个类可以很容易的调用本地摄像头获取摄像头图像帧。
打开摄像头
// 打开摄像头
// 参数0表示打开默认摄像头
VideoCapture cap(0);
检查摄像头是否打开成功
// 检查摄像头是否打开成功
if(cap.isOpened() == false)
{
return -1;
}
读取摄像头图像
// 读取图片
Mat src;
// 读取一帧图像
cap >> src;
释放摄像头
// 释放摄像头
cap.release();
main.cpp
#include "dialog.h"
#include <QApplication>
#include <QDebug>
#include <vector>
#include <opencv2/opencv.hpp> // 头文件,.hpp也是C++的文件格式
using namespace cv; // 名字空间
using namespace std;
int main(int argc, char *argv[])
{
// QApplication a(argc, argv);
// Dialog w;
// w.show();
// 加载人脸分类器(识别模型)
CascadeClassifier classifier = CascadeClassifier("D:/opencv/opencv3.4-install/install/etc/haarcascades/haarcascade_frontalface_alt2.xml");
// 打开摄像头
// 参数0表示打开默认摄像头
VideoCapture cap(0);
// 检查摄像头是否打开成功
if(cap.isOpened() == false)
{
return -1;
}
// 读取图片
Mat src;
// 读取一帧图像
cap >> src;
if(!src.data) // 如果没有数据,表示读取失败
{
qDebug() << "读取图片失败";
}
Mat gray;
// cvtColor:转换颜色空间
// 参数1:src原始图像数据
// 参数2:转换后的图像数据
// 参数3:转换方式
cvtColor(src,gray,COLOR_BGR2GRAY);
// 识别到的区域结果会存储到这个向量中
vector<Rect> faces;
classifier.detectMultiScale(gray,faces);
// 循环遍历出所有的人脸
for(int i = 0; i < faces.size(); i++)
{
// 在原图上画出选定框,标定人脸
// 参数1:原始图像数据
// 参数2:表示标定第几张人脸
// 参数3:标定框的颜色【BGR】
// 参数4:框的线条粗度
rectangle(src,faces[i],Scalar(255,0,0),3);
}
// 给窗口设置标题,并设置图片显示模式为自动
namedWindow("窗口",CV_WINDOW_AUTOSIZE);
// 展示图片到窗口
imshow("窗口",src);
// 释放摄像头
cap.release();
// 窗口长期保持(0表示无限等待)。
waitKey(0);
return 0;
}
6.2 摄像头连续捕捉
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QTimer>
#include <vector>
#include <QImage>
#include <QPixmap>
#include <QDebug>
#include <opencv2/opencv.hpp> // 头文件,.hpp也是C++的文件格式
using namespace cv; // 名字空间
using namespace std;
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
// 定时器指针
QTimer *timer;
// 打开摄像头的载体对象
VideoCapture cap;
vector<Rect>faces;
Mat src;
CascadeClassifier classifier;
private slots:
void timeoutSlot(); // 定时器槽函数
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
// 加载人脸分类器(识别模型)
classifier = CascadeClassifier("D:/opencv/opencv3.4-install/install/etc/haarcascades/haarcascade_frontalface_alt2.xml");
if(cap.open(0))
{
qDebug() << "摄像头打开成功";
timer = new QTimer(this);
timer->setInterval(50); // 50毫秒检测一次
timer->setSingleShot(false);
connect(timer,SIGNAL(timeout()),
this,SLOT(timeoutSlot()));
timer->start();
}
else
{
qDebug() << "摄像头打开失败";
}
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::timeoutSlot()
{
// 从cap中提取一帧图片
cap >> src;
if(!src.data) // 如果没有数据,表示读取失败
{
qDebug() << "读取图片失败";
}
Mat gray;
// cvtColor:转换颜色空间
// 参数1:src原始图像数据
// 参数2:转换后的图像数据
// 参数3:转换方式
cvtColor(src,gray,COLOR_BGR2GRAY);
// 识别到的区域结果会存储到这个向量中
vector<Rect> faces;
classifier.detectMultiScale(gray,faces);
// 循环遍历出所有的人脸
for(int i = 0; i < faces.size(); i++)
{
// 在原图上画出选定框,标定人脸
// 参数1:原始图像数据
// 参数2:表示标定第几张人脸
// 参数3:标定框的颜色【BGR】
// 参数4:框的线条粗度
rectangle(src,faces[i],Scalar(255,0,0),3);
}
// 展示图像
// BGR -> RGB
Mat rgb;
cvtColor(src,rgb,CV_BGR2RGB);
// Mat -> QImage
// 参数1:原始数据
// 参数2:宽度
// 参数3:高度
// 参数4:每一行的总通道数 = 宽度*3(rgb的通道数)
// 参数5:转换格式
QImage img(rgb.data,rgb.cols,rgb.rows,rgb.cols*3,QImage::Format_RGB888);
// QImage -> QPixmap
QPixmap p = QPixmap::fromImage(img);
// 设置给QLabel
ui->label->resize(p.width(),p.height());
ui->label->setPixmap(p);
}