ubuntu下用Qt实现人脸识别之检测人脸并绘制人脸框(三)
要检测出人脸并且还要识别出这个人是谁,就得用到人脸算法,这个算法如果你足够牛X的话可以自己写出来,当然,如果像我一样是个小菜鸟的话就得领悟----万物为我所用,万物不为我所有----的真谛。那么,怎么做到呢?答案就是借助虹软人脸识别sdk。去虹软官网中将这个SDK下载下来,放到自己的工程目录下。
下载下来的SDK:
将头文件和库文件放到自己的工程目录下
然后在pro文件中将头文件和库文件包含添加进去即可。
最后在虹软官网中将自己账号中的APP_ID和SDK_KEY记下来,后续可以用来激活SDK
代码实现
基本思路:使用opencv来打开摄像头获取到数据,就这些数据传入到算法的接口中,得到人脸坐标,再使用paintEvent来绘制人脸框。
头文件代码如下(示例):
#include <QWidget>
#include <QImage>
#include <QPainter>
#include <QObject>
#include <QTimer>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "ASF/inc/merror.h"
#include "ASF/inc/asvloffscreen.h"
#include "ASF/inc/arcsoft_face_sdk.h"
#include "ASF/inc/amcomdef.h"
using namespace cv;
namespace Ui {
class hrQtPro;
}
class hrQtPro : public QWidget
{
Q_OBJECT
public:
explicit hrQtPro(QWidget *parent = 0);
~hrQtPro();
protected:
void paintEvent(QPaintEvent* e);
private slots:
int slotReadFarme();
private:
Ui::hrQtPro *ui;
VideoCapture capture;
QTimer *cvTimer;
Mat cap;
QImage qImg;
ASF_MultiFaceInfo detectedFaces;
MHandle handle;
int ASFInit();
int OpenCamera();
QImage Mat2QImage(Mat &src);
};
cpp文件代码如下(示例):
#include "hrqtpro.h"
#include "ui_hrqtpro.h"
hrQtPro::hrQtPro(QWidget *parent) :
QWidget(parent),
handle(NULL),
ui(new Ui::hrQtPro)
{
cvTimer = new QTimer(this);
connect(cvTimer, SIGNAL(timeout()), this, SLOT(slotReadFarme()));
ASFInit();
OpenCamera();
}
hrQtPro::~hrQtPro()
{
MRESULT res = ASFUninitEngine(handle);
if (res != MOK)
printf("ASFUninitEngine fail: %d\n", res);
else
printf("ASFUninitEngine sucess: %d\n", res);
if(cvTimer) {
cvTimer->stop();
delete cvTimer;
cvTimer = NULL;
}
delete ui;
}
int hrQtPro::ASFInit()
{
MRESULT res = MOK;
#if 1
//激活SDK,只需要激活一次即可
//这里的APP_ID和SDK_KEY是从官网中获取到的
res = ASFOnlineActivation("APP_ID", "SDK_KEY");
if (MOK != res && MERR_ASF_ALREADY_ACTIVATED != res)
qDebug("ASFOnlineActivation fail: %d\n", res);
else
qDebug("ASFOnlineActivation sucess: %d\n", res);
#endif
//只是检测人脸,如果需要人脸识别还需要或上ASF_FACERECOGNITION,例如:ASF_FACE_DETECT | ASF_FACERECOGNITION
MInt32 mask = ASF_FACE_DETECT;
res = ASFInitEngine(ASF_DETECT_MODE_VIDEO, ASF_OP_0_ONLY, 16, 5, mask, &handle);
if (res != MOK)
qDebug("ASFInitEngine fail: %d\n", res);
else
qDebug("ASFInitEngine sucess: %d\n", res);
return res;
}
int hrQtPro::OpenCamera()
{
//打开摄像头
if(capture.open(0)) {
qDebug() << "open success";
} else {
qDebug() << "open error";
return -1;
}
//设置格式
capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M','J','P','G'));
cvTimer->start(20);
return 0;
}
//图像宽度需要四字节对齐,否则需要裁剪。
void CutIplImage(IplImage* src, IplImage* dst, int x, int y)
{
CvSize size = cvSize(dst->width, dst->height);//区域大小
cvSetImageROI(src, cvRect(x, y, size.width, size.height));//设置源图像ROI
cvCopy(src, dst); //复制图像
cvResetImageROI(src);//源图像用完后,清空ROI
}
//Mat转换为QImage
QImage hrQtPro::Mat2QImage(Mat &src) {
if(src.type() == CV_8UC3) {
const uchar *pSrc = (const uchar*)src.data;
QImage qImage(pSrc,src.cols,src.rows,src.step,QImage::Format_RGB888);
return qImage.rgbSwapped();
}
return QImage();
}
int hrQtPro::slotReadFarme()
{
//读取摄像头数据
capture.read(cap);
if(!cap.data || cap.empty()) {
return -1;
}
//Mat转换为QImage
qImg = Mat2QImage(cap);
if(qImg.isNull())
return -1;
IplImage ipi(cap);
IplImage* img = cvCreateImage(cvSize(ipi.width - ipi.width % 4,
ipi.height), IPL_DEPTH_8U, ipi.nChannels);
ASVLOFFSCREEN offscreen = { 0 };
if (img) {
CutIplImage(&ipi, img, 0, 0);
offscreen.u32PixelArrayFormat = ASVL_PAF_RGB24_B8G8R8;
offscreen.i32Width = img->width;
offscreen.i32Height = img->height;
offscreen.pi32Pitch[0] = img->widthStep;
offscreen.ppu8Plane[0] = (MUInt8*)img->imageData;
MRESULT res = ASFDetectFacesEx(handle, &offscreen, &detectedFaces);
if (MOK != res) {
qDebug("ASFDetectFacesEx failed: %d\n", res);
}
cvReleaseImage(&img);
}
}
//绘制人脸框
void hrQtPro::paintEvent(QPaintEvent* e)
{
if(!qImg.isNull()) {
QPainter painter(&qImg);
if(detectedFaces.faceNum > 0) {
// 设置人脸框颜色
painter.setPen(QColor(255, 0, 0));
//绘制人脸的框
painter.drawRect(detectedFaces.faceRect[0].left,
detectedFaces.faceRect[0].top,
detectedFaces.faceRect[0].right - detectedFaces.faceRect[0].left,
detectedFaces.faceRect[0].bottom - detectedFaces.faceRect[0].top);
}
ui->previewLabel->setPixmap(QPixmap::fromImage(qImg));
}
}