Qt怎么实现实时人脸框

发布时间:2021-12-15 10:13:21 作者:iii
来源:亿速云 阅读:262

这篇文章主要介绍“Qt怎么实现实时人脸框”,在日常操作中,相信很多人在Qt怎么实现实时人脸框问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Qt怎么实现实时人脸框”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、前言

在人脸识别到以后,需要在实时视频上将所有人脸框绘制出来,一把来说识别人脸会有多种选择,一个是识别最大人脸,这种场景主要用于刷脸门禁,还有一种是识别所有人脸,这种场景主要用于人脸识别摄像机,就是将画面中的所有人脸识别出来发给服务器,人脸框的数据主要是四个参数,左上角和右下角的位置,也可以说是x、y、width、height,可能有些做的比较好的还有倾斜角度,这个意义不是很大,人脸识别的速度一般都是飞快的,就算你用学习上用的opencv做识别也是非常快的,基本上都是毫秒级的响应,主要的耗时操作在特征值的提取,所以一般要求能够响应每个通道每秒钟25帧-30帧的画面绘制+人脸框的绘制,当然人脸框的数据可能会有多个。

用Qt来绘制人脸框,核心就是一个函数,调用QPainter的drawRect方法,传入区域即可,如果花哨点的话还可以设置边框的粗细和颜色、圆角角度等,注意圆角角度使用的是drawRoundedRect而不是drawRoundRect,很多人这里会搞错哦。近期接触的项目对人脸框的要求越来越多,之前是让用户自己拿到图片来绘制,近期索性直接将这个功能内置到视频控件中(视频控件封装了多种内核版本,有ffmpeg、vlc、mpv、海康sdk等),提供了可设置边框粗细、颜色,传入人脸框区域集合的接口,用户只要自己的算法分析拿到人脸的区域集合(用户是上帝,用户的需求就是我的需求),通过setFaceRects函数设置即可,如果要清空人脸,只要设置人脸框区域集合为空即可。总体测试下来速度非常快,可以忽略,采用的QOPenGLWidget绘制的实时图像,也支持人脸框的绘制。

二、功能特点

  1. 支持的功能包括人脸识别、人脸比对、人脸搜索、活体检测等。

  2. 在线版还支持身份证、驾驶证、行驶证、银行卡等识别。

  3. 在线版的协议支持百度、旷视,离线版的支持百度,可定制。

  4. 除了支持X86架构,还支持嵌入式linux比如contex-A9、树莓派等。

  5. 每个功能的执行除了返回结果还返回执行用时时间。

  6. 多线程处理,通过type控制当前处理类型。

  7. 支持单张图片检索相似度最高的图片。

  8. 支持指定目录图片用来生成人脸特征值文件。

  9. 可设置等待处理图片队列中的数量。

  10. 每次执行都有成功或者失败的信号返回。

  11. 人脸搜索的返回结果包含了原图+最大相似度图+相似度等。

  12. 人脸比对同时支持两张图片和两个特征值比对。

  13. 相关功能自定义一套协议用于客户端和服务端,可以通过TCP通信进行交互。

  14. 自定义人脸识别协议非常适用于中心一台服务器,现场若干设备请求的场景。

  15. 每个模块全部是独立的一个类,代码整洁、注释完善。

三、效果图

Qt怎么实现实时人脸框

四、核心代码

bool FFmpegWidget::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == osdWidget && event->type() == QEvent::Paint) {
        if (drawImage) {
            QPainter painter;
            painter.begin(osdWidget);
            painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);

            //绘制边框
            drawBorder(&painter);
            if (thread->getIsInit()) {
                //绘制背景图片
                drawImg(&painter, image);
                //绘制人脸框
                drawFace(&painter);
                //绘制标签
                drawOSD(&painter, osd1Visible, osd1FontSize, osd1Text, osd1Color, osd1Image, osd1Format, osd1Position);
                drawOSD(&painter, osd2Visible, osd2FontSize, osd2Text, osd2Color, osd2Image, osd2Format, osd2Position);
            } else {
                //绘制背景
                if (!isDrag) {
                    drawBg(&painter);
                }
            }

            painter.end();
        }
    }

    return QWidget::eventFilter(watched, event);
}

void FFmpegWidget::drawBorder(QPainter *painter)
{
    if (borderWidth == 0) {
        return;
    }

    painter->save();
    QPen pen;
    pen.setWidth(borderWidth);
    pen.setColor(hasFocus() ? focusColor : borderColor);
    painter->setPen(pen);
    painter->drawRect(rect());
    painter->restore();
}

void FFmpegWidget::drawBg(QPainter *painter)
{
    painter->save();

    //背景图片为空则绘制文字,否则绘制背景图片
    if (bgImage.isNull()) {
        painter->setFont(this->font());
        painter->setPen(palette().foreground().color());
        painter->drawText(rect(), Qt::AlignCenter, bgText);
    } else {
        //居中绘制
        int x = rect().center().x() - bgImage.width() / 2;
        int y = rect().center().y() - bgImage.height() / 2;
        QPoint point(x, y);
        painter->drawImage(point, bgImage);
    }

    painter->restore();
}

void FFmpegWidget::drawImg(QPainter *painter, QImage img)
{
    if (img.isNull()) {
        return;
    }

    painter->save();

    int offset = borderWidth * 1 + 0;
    img = img.scaled(width() - offset, height() - offset, Qt::KeepAspectRatio, Qt::SmoothTransformation);

    if (fillImage) {
        QRect rect(offset / 2, offset / 2, width() - offset, height() - offset);
        painter->drawImage(rect, img);
    } else {
        //按照比例自动居中绘制
        int x = rect().center().x() - img.width() / 2;
        int y = rect().center().y() - img.height() / 2;
        QPoint point(x, y);
        painter->drawImage(point, img);
    }

    painter->restore();
}

void FFmpegWidget::drawFace(QPainter *painter)
{
    if (faceRects.count() == 0) {
        return;
    }

    painter->save();

    //人脸边框的颜色
    QPen pen;
    pen.setWidth(faceBorder);
    pen.setColor(faceColor);
    painter->setPen(pen);

    //逐个取出人脸框区域进行绘制
    foreach (QRect rect, faceRects) {
        painter->drawRect(rect);
    }

    painter->restore();
}

void FFmpegWidget::drawOSD(QPainter *painter,
                           bool osdVisible,
                           int osdFontSize,
                           const QString &osdText,
                           const QColor &osdColor,
                           const QImage &osdImage,
                           const FFmpegWidget::OSDFormat &osdFormat,
                           const FFmpegWidget::OSDPosition &osdPosition)
{
    if (!osdVisible) {
        return;
    }

    painter->save();

    //标签位置尽量偏移多一点避免遮挡
    QRect osdRect(rect().x() + (borderWidth * 2), rect().y() + (borderWidth * 2), width() - (borderWidth * 5), height() - (borderWidth * 5));
    int flag = Qt::AlignLeft | Qt::AlignTop;
    QPoint point = QPoint(osdRect.x(), osdRect.y());

    if (osdPosition == OSDPosition_Left_Top) {
        flag = Qt::AlignLeft | Qt::AlignTop;
        point = QPoint(osdRect.x(), osdRect.y());
    } else if (osdPosition == OSDPosition_Left_Bottom) {
        flag = Qt::AlignLeft | Qt::AlignBottom;
        point = QPoint(osdRect.x(), osdRect.height() - osdImage.height());
    } else if (osdPosition == OSDPosition_Right_Top) {
        flag = Qt::AlignRight | Qt::AlignTop;
        point = QPoint(osdRect.width() - osdImage.width(), osdRect.y());
    } else if (osdPosition == OSDPosition_Right_Bottom) {
        flag = Qt::AlignRight | Qt::AlignBottom;
        point = QPoint(osdRect.width() - osdImage.width(), osdRect.height() - osdImage.height());
    }

    if (osdFormat == OSDFormat_Image) {
        painter->drawImage(point, osdImage);
    } else {
        QDateTime now = QDateTime::currentDateTime();
        QString text = osdText;
        if (osdFormat == OSDFormat_Date) {
            text = now.toString("yyyy-MM-dd");
        } else if (osdFormat == OSDFormat_Time) {
            text = now.toString("HH:mm:ss");
        } else if (osdFormat == OSDFormat_DateTime) {
            text = now.toString("yyyy-MM-dd HH:mm:ss");
        }

        //设置颜色及字号
        QFont font;
        font.setPixelSize(osdFontSize);
        painter->setPen(osdColor);
        painter->setFont(font);

        painter->drawText(osdRect, flag, text);
    }

    painter->restore();
}

到此,关于“Qt怎么实现实时人脸框”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. Qt实现 实时监控文件夹状态
  2. Java OpenCV4.0.0实现实时人脸识别

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

qt

上一篇:Qt中如何获取桌面宽度高度

下一篇:golang刷leetcode滑动窗口之如何实现颜色分类

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》