您好,登錄后才能下訂單哦!
這篇文章主要介紹“Qt怎么實現(xiàn)人臉識別服務(wù)端”,在日常操作中,相信很多人在Qt怎么實現(xiàn)人臉識別服務(wù)端問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Qt怎么實現(xiàn)人臉識別服務(wù)端”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
自定義人臉識別協(xié)議采用的是tcp通信協(xié)議,其實也可以改成http協(xié)議,這也是大部分廠家的做法,畢竟現(xiàn)在http post非常流行,通用性好,返回個json數(shù)據(jù)非常規(guī)范,本程序目前采用的tcp協(xié)議是為了兼容以前的舊的系統(tǒng),畢竟之前的系統(tǒng)都是按照那個格式定義的,推翻重來那之前寫過的很多設(shè)備的程序都需要更改,一個人肯定忙不過來,而且之前的程序也是經(jīng)過大量的現(xiàn)場應(yīng)用檢驗過的,非常穩(wěn)定,一旦改動程序的話有需要很長時間的磨合測試。
自定義人臉識別協(xié)議功能:
離線使用,同時支持百度的離線包和嵌入式linux人臉識別靜態(tài)庫。
支持多個連接并發(fā),自動排隊處理,返回的時候帶上唯一標識區(qū)分。
傳入單張圖片返回人臉區(qū)域。
傳入單張圖片返回人臉特征值。
傳入單張圖片或者多張圖片返回是否是活體。
傳入兩張圖片返回比對結(jié)果。
傳入兩個特征值返回比對結(jié)果。
傳入單張圖片添加人臉。
指定唯一標識符刪除人臉。
傳入單張照片返回相似度最大的人臉信息。
修改人臉服務(wù)的配置參數(shù)比如是否快速查找、人臉占比等。
支持的功能包括人臉識別、人臉比對、人臉搜索、活體檢測等。
在線版還支持身份證、駕駛證、行駛證、銀行卡等識別。
在線版的協(xié)議支持百度、曠視,離線版的支持百度,可定制。
除了支持X86架構(gòu),還支持嵌入式linux比如contex-A9、樹莓派等。
每個功能的執(zhí)行除了返回結(jié)果還返回執(zhí)行用時時間。
多線程處理,通過type控制當前處理類型。
支持單張圖片檢索相似度最高的圖片。
支持指定目錄圖片用來生成人臉特征值文件。
可設(shè)置等待處理圖片隊列中的數(shù)量。
每次執(zhí)行都有成功或者失敗的信號返回。
人臉搜索的返回結(jié)果包含了原圖+最大相似度圖+相似度等。
人臉比對同時支持兩張圖片和兩個特征值比對。
相關(guān)功能自定義一套協(xié)議用于客戶端和服務(wù)端,可以通過TCP通信進行交互。
自定義人臉識別協(xié)議非常適用于中心一臺服務(wù)器,現(xiàn)場若干設(shè)備請求的場景。
每個模塊全部是獨立的一個類,代碼整潔、注釋完善。
void FaceSdkSocket::checkData() { QMutexLocker locker(&mutex); QDomDocument dom; if (!DeviceFun::getReceiveXmlData(buffer, dom, "IFACE:", 10)) { return; } //逐個取出節(jié)點判斷數(shù)據(jù) emit receiveData(clientIP, dom.toString()); QDomElement element = dom.documentElement(); if (element.tagName() == "FaceClient") { QString deviceIP = element.attribute("DeviceIP"); QDomNode childNode = element.firstChild(); QString name = childNode.nodeName(); QString value = element.text(); //qDebug() << TIMEMS << name << value; if (name == "DeviceHeart") { sendOk(); emit receiveAnaly(deviceIP, "設(shè)備心跳"); } else if (name == "FindFace") { element = childNode.toElement(); value = element.text(); if (value.length() == 0) { return; } //用連接的描述符加上用戶傳入的描述符組合,方便接收處判斷發(fā)送給那個連接 QString faceID = element.attribute("FaceID"); QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID); QImage image = DeviceFun::getImage(value); checkImage(image); emit receiveAnaly(deviceIP, "請求人臉區(qū)域"); //發(fā)送到人臉識別線程處理 #ifdef facelocal FaceLocalBaiDu::Instance()->setType(0); FaceLocalBaiDu::Instance()->append(flag, image); #elif facearm FaceLocalArm::Instance()->setType(0); FaceLocalArm::Instance()->append(flag, image); #endif } else if (name == "FindFeature") { element = childNode.toElement(); value = element.text(); if (value.length() == 0) { return; } //用連接的描述符加上用戶傳入的描述符組合,方便接收處判斷發(fā)送給那個連接 QString faceID = element.attribute("FaceID"); QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID); QImage image = DeviceFun::getImage(value); checkImage(image); emit receiveAnaly(deviceIP, "請求人臉特征"); //發(fā)送到人臉識別線程處理 #ifdef facelocal FaceLocalBaiDu::Instance()->setType(1); FaceLocalBaiDu::Instance()->append(flag, image); #elif facearm FaceLocalArm::Instance()->setType(1); FaceLocalArm::Instance()->append(flag, image); #endif } else if (name == "FindLive") { element = childNode.toElement(); value = element.text(); if (value.length() == 0) { return; } //用連接的描述符加上用戶傳入的描述符組合,方便接收處判斷發(fā)送給那個連接 QString faceID = element.attribute("FaceID"); QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID); QImage image = DeviceFun::getImage(value); checkImage(image); emit receiveAnaly(deviceIP, "請求活體檢測"); //發(fā)送到人臉識別線程處理 #ifdef facelocal FaceLocalBaiDu::Instance()->setType(5); FaceLocalBaiDu::Instance()->append(flag, image); #endif } else if (name == "CompareByImage") { //取出子節(jié)點 QDomNodeList nodeList = childNode.childNodes(); int nodeCount = nodeList.count(); if (nodeCount == 2) { QString faceID1, faceID2; QImage faceImage1, faceImage2; for (int i = 0; i < nodeCount; i++) { childNode = nodeList.at(i); element = childNode.toElement(); name = childNode.nodeName(); value = element.text(); if (name == "FaceImage1") { faceID1 = element.attribute("FaceID"); faceImage1 = DeviceFun::getImage(value); } else if (name == "FaceImage2") { faceID2 = element.attribute("FaceID"); faceImage2 = DeviceFun::getImage(value); } } checkImage(faceImage1); checkImage(faceImage2); QString flag1 = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID1); QString flag2 = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID2); emit receiveAnaly(deviceIP, "請求人臉照片比對"); //發(fā)送到人臉識別線程處理 #ifdef facelocal FaceLocalBaiDu::Instance()->setType(2); FaceLocalBaiDu::Instance()->append(flag1 + "|" + flag2, faceImage1, faceImage2); #elif facearm FaceLocalArm::Instance()->setType(2); FaceLocalArm::Instance()->append(flag1 + "|" + flag2, faceImage1, faceImage2); #endif } } else if (name == "CompareByFeature") { element = childNode.toElement(); QString faceID = element.attribute("FaceID"); //取出子節(jié)點 QDomNodeList nodeList = childNode.childNodes(); int nodeCount = nodeList.count(); if (nodeCount == 2) { QStringList faceFeature1, faceFeature2; for (int i = 0; i < nodeCount; i++) { childNode = nodeList.at(i); element = childNode.toElement(); name = childNode.nodeName(); value = element.text(); if (name == "FaceFeature1") { faceFeature1 = value.split("|"); } else if (name == "FaceFeature2") { faceFeature2 = value.split("|"); } } emit receiveAnaly(deviceIP, "請求人臉特征比對"); //特征比對速度非???忽略不計,立即比對并將結(jié)果返回 int count1 = faceFeature1.count(); int count2 = faceFeature2.count(); if (count1 != 256 || count2 != 256) { sendMsg("faceFeature count != 256"); return; } QList<float> feature1, feature2; for (int i = 0; i < 256; i++) { feature1 << faceFeature1.at(i).toFloat(); feature2 << faceFeature2.at(i).toFloat(); } #ifdef facelocal float result = FaceLocalBaiDu::Instance()->getFaceCompare(faceID, feature1, feature2); sendFaceCompare(faceID, result, 1); #elif facearm float result = FaceLocalArm::Instance()->getFaceCompare(faceID, feature1, feature2); sendFaceCompare(faceID, result, 1); #endif } } else if (name == "AppendFace") { element = childNode.toElement(); value = element.text(); if (value.length() == 0) { return; } //用連接的描述符加上用戶傳入的描述符組合,方便接收處判斷發(fā)送給那個連接 QString faceID = element.attribute("FaceID"); QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID); QImage image = DeviceFun::getImage(value); checkImage(image); emit receiveAnaly(deviceIP, "添加人臉"); //發(fā)送到人臉識別線程處理 QString file = QString("%1/%2.txt").arg(FACEPATH).arg(faceID); #ifdef facelocal FaceLocalBaiDu::Instance()->appendFace(flag, image, file); #elif facearm FaceLocalArm::Instance()->appendFace(flag, image, file); #endif } else if (name == "DeleteFace") { element = childNode.toElement(); value = element.text(); if (value.length() == 0) { return; } //用連接的描述符加上用戶傳入的描述符組合,方便接收處判斷發(fā)送給那個連接 QString faceID = element.attribute("FaceID"); emit receiveAnaly(deviceIP, "刪除人臉"); //發(fā)送到人臉識別線程處理 #ifdef facelocal FaceLocalBaiDu::Instance()->deleteFace(faceID); #elif facearm FaceLocalArm::Instance()->deleteFace(faceID); #endif sendOk(); } else if (name == "FindByImage") { element = childNode.toElement(); value = element.text(); if (value.length() == 0) { return; } //用連接的描述符加上用戶傳入的描述符組合,方便接收處判斷發(fā)送給那個連接 QString faceID = element.attribute("FaceID"); QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID); QImage image = DeviceFun::getImage(value); checkImage(image); emit receiveAnaly(deviceIP, "根據(jù)圖片查找人臉"); //發(fā)送到人臉識別線程處理 #ifdef facelocal FaceLocalBaiDu::Instance()->setOneImg(flag, image); #elif facearm FaceLocalArm::Instance()->setOneImg(flag, image); #endif } else if (name == "FindByFeature") { element = childNode.toElement(); value = element.text(); if (value.length() == 0) { return; } //用連接的描述符加上用戶傳入的描述符組合,方便接收處判斷發(fā)送給那個連接 QString faceID = element.attribute("FaceID"); QStringList faceFeature = value.split("|"); emit receiveAnaly(deviceIP, "根據(jù)特征查找人臉"); int count = faceFeature.count(); if (count != 256) { return; } QList<float> feature; for (int i = 0; i < 256; i++) { feature << faceFeature.at(i).toFloat(); } //比對速度很快,立即比對并返回結(jié)果 QString targetName; float result; int msec; #ifdef facelocal FaceLocalBaiDu::Instance()->getFaceOne(faceID, feature, targetName, result, msec); #elif facearm FaceLocalArm::Instance()->getFaceOne(faceID, feature, targetName, result, msec); #endif if (!targetName.isEmpty()) { QString imageFile = QString("%1/%2").arg(FACEPATH).arg(targetName); sendFaceCompareOne(faceID, QImage(), QImage(imageFile), targetName, result, msec); } } else if (name == "UpdateConfig") { element = childNode.toElement(); emit receiveAnaly(deviceIP, "修改人臉配置"); bool findFast = (element.attribute("FindFast") == "true" ? true : false); int facePercent = element.attribute("FacePercent").toInt(); #ifdef facelocal FaceLocalBaiDu::Instance()->setFindFast(findFast); FaceLocalBaiDu::Instance()->setPercent(facePercent); #elif facearm FaceLocalArm::Instance()->setFindFast(findFast); FaceLocalArm::Instance()->setPercent(facePercent); #endif //立即回復 sendFaceConfig(findFast, facePercent); emit configChanged(findFast, facePercent); } } } void FaceSdkSocket::checkImage(const QImage &image) { //如果照片寬高過大則發(fā)出提示到客戶端 if (image.width() >= 1280 || image.height() >= 720) { sendMsg("Image Size Is Too Large"); } } void FaceSdkSocket::setClientIP(const QString &clientIP) { this->clientIP = clientIP; } QString FaceSdkSocket::getClientIP() { return this->clientIP; } void FaceSdkSocket::sendData(const QString &body) { //構(gòu)建xml字符串 QStringList list; list.append(QString("<FaceServer TargetIP=\"%1\" NowTime=\"%2\">").arg(clientIP).arg(DATETIME)); list.append(body); list.append("</FaceServer>"); QString data = DeviceFun::getSendXmlData(list.join(""), "IFACE:"); this->write(data.toUtf8()); emit sendData(clientIP, data); } void FaceSdkSocket::sendOk() { sendData(""); emit sendAnaly(clientIP, "心跳應(yīng)答"); } void FaceSdkSocket::sendMsg(const QString &msg) { sendData(QString("<Msg>%1</Msg>").arg(msg)); emit sendAnaly(clientIP, "提示信息"); } void FaceSdkSocket::sendFaceRect(const QString &faceID, const QString &faceRect, int msec) { QString data = QString("<FaceRect FaceID=\"%1\" TimeUsed=\"%3\">%2</FaceRect>") .arg(faceID).arg(faceRect).arg(msec); sendData(data); emit sendAnaly(clientIP, "返回人臉區(qū)域"); } void FaceSdkSocket::sendFaceFeature(const QString &faceID, const QString &faceFeature, int msec) { QString data = QString("<FaceFeature FaceID=\"%1\" TimeUsed=\"%3\">%2</FaceFeature>") .arg(faceID).arg(faceFeature).arg(msec); sendData(data); emit sendAnaly(clientIP, "返回人臉特征"); } void FaceSdkSocket::sendFaceCompare(const QString &faceID, float result, int msec) { QString data = QString("<FaceCompare FaceID=\"%1\" TimeUsed=\"%3\" Result=\"%2\" />") .arg(faceID).arg(result).arg(msec); sendData(data); emit sendAnaly(clientIP, "返回人臉比對結(jié)果"); } void FaceSdkSocket::sendFaceCompareOne(const QString &faceID, const QImage &sourceImage, const QImage &targetImage, const QString &targetName, float result, int msec) { QString data = QString("<FaceCompareOne FaceID=\"%1\" TimeUsed=\"%6\" Result=\"%2\" TargetName=\"%3\">%4|%5</FaceCompareOne>") .arg(faceID).arg(result).arg(targetName).arg(DeviceFun::getImageData(sourceImage)).arg(DeviceFun::getImageData(targetImage)).arg(msec); sendData(data); emit sendAnaly(clientIP, "返回最相似人臉"); }
到此,關(guān)于“Qt怎么實現(xiàn)人臉識別服務(wù)端”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。