百度AI實現人臉識別之人臉檢測(Qt版)

前言


本文主要實現打開一張人臉圖片,識別出年齡、性別、顏值等人臉屬性信息。其它的人臉比對、身份驗證、活體檢測等等功能都可以在此基礎上進行擴展,以及對人臉識別接口的調用和信息處理。

Demo運行結果


這個功能可以當做是娛樂功能,同一個人不同風格的照片識別結果可能不同。


百度AI人臉識別接入


爲什麼使用百度AI接口

 


人臉識別可接入的平臺挺多的,阿里雲、騰訊雲、Face++等等,如果是商用的話就得慎重了,畢竟要考慮的不僅是接口穩定性,還有價格、技術支持、售後等很多方面。這裏只是用來學習,所以考慮的問題就比較簡單了,只是關乎Money,而百度AI的接口絕大部分都免費,只是商用需要高併發或者一些付費資源的話需要付費,學習的話免費資源完全滿足需求了。同樣註冊了阿里雲的應用,直接收費,Face++給了限定的測試次數,所以選擇了百度AI。技術而言,Face++可能在人臉識別這方面更專業一點,但目前各大平臺的識別率基本沒有什麼區別。

è¿éåå¾çæè¿°


接入步驟

 

 

  1. 註冊百度賬號,用來登錄百度AI開發平臺(http://ai.baidu.com/),有賬號的可以直接登錄
  2. 註冊成爲開發者
  3. 創建應用,應用創建成功之後也就開通了人臉檢測、人臉比對等等相關業務
  4. 獲取密鑰,AppID、API Key和Secret key
  5. 生成簽名(Access Token),這個寫代碼的時候要用到,每個應用的Access Token有效期爲30天,到期後要重新獲取,或者是在寫代碼時每次都獲取一下
  6. 啓動開發

百度AI開放平臺上有詳細的接入指南:http://ai.baidu.com/docs#/Begin/top

如何獲取Access Token

 


向授權服務地址https://aip.baidubce.com/oauth/2.0/token發送請求(推薦使用POST),並在URL中帶上以下參數:

  • grant_type: 必須參數,固定爲client_credentials
  • client_id: 必須參數,應用的API Key
  • client_secret: 必須參數,應用的Secret Key

具體的參數值可以在下圖位置中的“應用列表”裏查看:

è¿éåå¾çæè¿°

使用在線post工具按照上面的地址和參數進行請求就可以得到Access Token了,百度搜索“在線post工具"有很多可用的,這裏使用http://coolaf.com/舉例:

è¿éåå¾çæè¿°



Qt軟件開發


編程部分並不複雜,主要是對百度AI接口的調用及對請求數據的解析。但實現示例的功能還是用到了挺多知識點,下面會進行記錄。

人臉檢測Qt編程步驟

 

  1. 綁定請求服務器地址和密鑰
  2. 按照百度人臉檢測接口的格式要求添加header
  3. 將要檢測的圖片轉換爲爲BASE64編碼(這裏需要注意一下,官方說上傳的圖片不能大於2M,測試了一個3M的圖片依然可以請求成功,不過需要好幾秒才能收到反饋,測試的3M的圖片轉成BASE64編碼後長度超過1000萬個字節,圖片越小識別的速度越快)
  4. 按照百度人臉檢測接口的格式要求打包body數據
  5. 使用post方式上傳請求
  6. 解析反饋數據

注意:這裏的請求內容必須按照百度接口指定的格式,格式如下


知識點


網絡編程

 


這裏使用了QtNetwork模塊中的網絡接口來實現http編程,需要在.pro文件中添加 QT += network,主要用到了下面三個類:

  • QNetworkAccessManager:該類允許應用程序發送網絡請求和接收回復,類似於一箇中轉站或者一個容器,每當有請求創建或者接收到回覆都由該類進行調度
  • QNetworkRequest:網絡請求
  • QNetworkReply:網絡請求的應答,在請求被完成調度是由QNetworkAccessManager創建

get、put、post請求方式的區別簡述


這裏只用到了post請求,並且目前大多數網絡請求的方式均使用post。

  • GET請求(類似於數據庫select操作),會向數據庫發送數據的請求,從而來獲取信息,不會改變數據內容,並且無論進行多少次操作,結果都是一樣的
  • PUT請求(類似於數據庫update操作),是會向服務器端發送數據的,會修改數據的內容,但是不會增加數據的種類,並且無論進行多少次操作,結果都是一樣的
  • POST請求(類似於數據庫insert操作),是會向服務器端發送數據的,但是該請求會改變數據的種類等資源,會創建新的內容

POST 提交數據方式


常用格式如下:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • text/xml

這篇文章裏有這四種方式的詳細介紹

 

如何對圖片進行BASE64編碼

 

  1. 提取圖片
  2. 數據轉換爲BASE64編碼

代碼如下:

QImage image("H:/test.jpg");
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
//以png格式將圖片數據寫入ba
image.save(&buffer, "png");
//將圖片進行BASE64編碼
QString imgData = QString(ba.toBase64());
buffer.close();


JSON數據解析


這部分內容還挺多的,可以從網絡學習JSON教程,下面的代碼裏也有用到。

核心代碼


數據上傳

 

//設置請求地址
QUrl url(requestUrl + "?access_token=" + accessToken);
QNetworkRequest request(url);

//設置數據提交格式,這個不能自己隨便寫,每個平臺的格式可能不一樣,百度AI要求的格式爲application/json
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));

//將要檢測的圖片進行BASE64編碼
QImage image(imgPath);
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
//以png格式將圖片數據寫入ba
image.save(&buffer, "png");
//將圖片進行BASE64編碼
QString imgData = QString(ba.toBase64());
buffer.close();

//打包請求參數
QJsonObject post_data;;
QJsonDocument document;
post_data.insert("image", imgData);
post_data.insert("image_type", "BASE64");
post_data.insert("face_field", "age,beauty,gender,expression");
document.setObject(post_data);
QByteArray post_param = document.toJson(QJsonDocument::Compact);

//發送請求
manager->post(request, post_param);


請求反饋數據解析

 

replyData = reply->readAll();
qDebug()<<"reply data is:"<<QString(replyData);

QJsonParseError json_error;
QJsonDocument document = QJsonDocument::fromJson(replyData, &json_error);
if(json_error.error == QJsonParseError::NoError)
{
    //判斷是否是對象,然後開始解析數據
    if(document.isObject())
    {
        QJsonObject obj = document.object();
        //解析反饋的人臉屬性結果
        if(obj.contains("result"))
        {
            QJsonObject resultObj = obj.take("result").toObject();
            //解析人臉個數
            if(resultObj.contains("face_num"))
            {
                int faceNum = obj.take("face_num").toInt();
                qDebug()<<"查詢到了圖片中的人臉個數爲:"<<faceNum;
            }
            //解析人臉屬性
            if(resultObj.contains("face_list"))
            {
                QJsonArray faceArray = resultObj.take("face_list").toArray();

                for(int i = 0; i < faceArray.size(); i++)
                {
                    QJsonObject faceObj = faceArray.at(i).toObject();
                    if(faceObj.contains("gender"))
                    {
                        QJsonObject genderObj = faceObj.take("gender").toObject();
                        if(genderObj.contains("type"))
                        {
                            QString type = genderObj.take("type").toString();;
                            if(type == "male")
                            {
                                ui->lblSex->setText("男");
                            }
                            else
                            {
                                ui->lblSex->setText("女");
                            }
                        }
                    }
                    if(faceObj.contains("age"))
                    {
                        int age = faceObj.take("age").toDouble();
                        qDebug()<<"查詢到了年齡:"<<age;
                        ui->lblAge->setText(QString::number(age));
                    }
                    if(faceObj.contains("beauty"))
                    {
                        int beauty = faceObj.take("beauty").toDouble();;
                        qDebug()<<"查詢到了顏值:"<<beauty;
                        ui->lblBeauty->setText(QString::number(beauty));
                    }
                    if(faceObj.contains("expression"))
                    {
                        QJsonObject expressionObj = faceObj.take("expression").toObject();
                        if(expressionObj.contains("type"))
                        {
                            QString type = expressionObj.take("type").toString();;
                            if(type == "smile")
                            {
                                ui->lblFeature->setText("微笑");
                            }
                            else if(type == "laugh")
                            {
                                ui->lblFeature->setText("大笑");
                            }
                            else
                            {
                                ui->lblFeature->setText("不笑");
                            }
                        }
                    }
                }
            }
        }
    }
}
reply->deleteLater();



完整示例代碼
https://download.csdn.net/download/aidam_bo/10864949

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章