您好,登錄后才能下訂單哦!
這篇文章主要介紹“Qt怎么實現實時人臉框”,在日常操作中,相信很多人在Qt怎么實現實時人臉框問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Qt怎么實現實時人臉框”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
在人臉識別到以后,需要在實時視頻上將所有人臉框繪制出來,一把來說識別人臉會有多種選擇,一個是識別最大人臉,這種場景主要用于刷臉門禁,還有一種是識別所有人臉,這種場景主要用于人臉識別攝像機,就是將畫面中的所有人臉識別出來發給服務器,人臉框的數據主要是四個參數,左上角和右下角的位置,也可以說是x、y、width、height,可能有些做的比較好的還有傾斜角度,這個意義不是很大,人臉識別的速度一般都是飛快的,就算你用學習上用的opencv做識別也是非常快的,基本上都是毫秒級的響應,主要的耗時操作在特征值的提取,所以一般要求能夠響應每個通道每秒鐘25幀-30幀的畫面繪制+人臉框的繪制,當然人臉框的數據可能會有多個。
用Qt來繪制人臉框,核心就是一個函數,調用QPainter的drawRect方法,傳入區域即可,如果花哨點的話還可以設置邊框的粗細和顏色、圓角角度等,注意圓角角度使用的是drawRoundedRect而不是drawRoundRect,很多人這里會搞錯哦。近期接觸的項目對人臉框的要求越來越多,之前是讓用戶自己拿到圖片來繪制,近期索性直接將這個功能內置到視頻控件中(視頻控件封裝了多種內核版本,有ffmpeg、vlc、mpv、海康sdk等),提供了可設置邊框粗細、顏色,傳入人臉框區域集合的接口,用戶只要自己的算法分析拿到人臉的區域集合(用戶是上帝,用戶的需求就是我的需求),通過setFaceRects函數設置即可,如果要清空人臉,只要設置人臉框區域集合為空即可。總體測試下來速度非常快,可以忽略,采用的QOPenGLWidget繪制的實時圖像,也支持人臉框的繪制。
支持的功能包括人臉識別、人臉比對、人臉搜索、活體檢測等。
在線版還支持身份證、駕駛證、行駛證、銀行卡等識別。
在線版的協議支持百度、曠視,離線版的支持百度,可定制。
除了支持X86架構,還支持嵌入式linux比如contex-A9、樹莓派等。
每個功能的執行除了返回結果還返回執行用時時間。
多線程處理,通過type控制當前處理類型。
支持單張圖片檢索相似度最高的圖片。
支持指定目錄圖片用來生成人臉特征值文件。
可設置等待處理圖片隊列中的數量。
每次執行都有成功或者失敗的信號返回。
人臉搜索的返回結果包含了原圖+最大相似度圖+相似度等。
人臉比對同時支持兩張圖片和兩個特征值比對。
相關功能自定義一套協議用于客戶端和服務端,可以通過TCP通信進行交互。
自定義人臉識別協議非常適用于中心一臺服務器,現場若干設備請求的場景。
每個模塊全部是獨立的一個類,代碼整潔、注釋完善。
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怎么實現實時人臉框”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。