pyqt5 + 百度api 打造一個圖像人臉識別、分割的程序

前序

這篇文章主要介紹利用 pyqt5 和 百度人臉識別 api 搭建一個具有人臉識別、頭像裁剪等多個功能集一體的小工具,我們先看一下程序的最終效果

end_imag11.gif

程序的基本使用步驟:

1,加載本地圖片並在界面上實現預覽;

2,點擊 convert 後臺調用百度 api 實現人臉識別並進行區域分割,同時返回關於人物顏值、性別、臉型等信息;

3,如果需要保存裁剪之後的圖像,點擊 Save as 保存到本地對應位置;

Snipaste_2020-03-07_16-44-44.jpg

整個程序的實現分爲三個部分:

1,獲取百度 api 實現人臉識別接口並進行調用;

2,利用Qt designer 進行界面設計,編寫代碼實現一些功能函數;

3,把1功能和2的界面進行信號槽鏈接;

2,程序開發詳細過程

2.1,獲取百度人臉識別 API 接口並進行調用;

對於人臉識別 API 接口 ,這裏只是以百度爲例,百度人臉識別 API 的地址 :https://ai.baidu.com/tech/face;利用這個接口,可以很方便地返回我們需要的信息

百度 API 構造基本流程:創建應用 -> 獲取 API Keys 和 Secret Keys -> 得到 token -> 利用 token 拼API ;

首先需要完成登錄(賬號百度雲即可),登錄之後會進入下面這個界面,左側欄列出了 人臉識別 專區提供的一些服務,有技術文檔(關於怎麼獲取接口,以及怎樣使用接口)、監控報表(調用接口的基本情況)…

Snipaste_2020-03-05_01-03-42.jpg

如果第一次使用需創建一個應用,用於獲取 API key 和 Secret key

Snipaste_2020-03-05_01-04-29.jpg

根據官網文檔,拿到 API key 和 Secret Key 之後,拼接成一個鏈接,利用 requests 進行訪問得到 token ,(注: token 的有效時間爲30天,30天之後如果繼續使用的話,需要更換)

import requests 

# client_id 爲官網獲取的AK, client_secret 爲官網獲取的SK
host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=【官網獲取的AK】&client_secret=【官網獲取的SK】'
response = requests.get(host)
if response:
    print(response.json()['access_token'])

token 拿到之後,與下面鏈接拼接在一起就得到了API 接口:

https://aip.baidubce.com/rest/2.0/face/v1/merge?access_token=[獲取得到的Token]

API 的使用方法如下:

import requests

'''
人臉檢測與屬性分析
'''
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect"

params = "{\"image\":\"027d8308a2ec665acb1bdf63e513bcb9\",\"image_type\":\"FACE_TOKEN\",\"face_field\":\"faceshape,facetype\"}"
access_token = '[調用鑑權接口獲取的token]'
request_url = request_url + "?access_token=" + access_token
headers = {'content-type': 'application/json'}
response = requests.post(request_url, data=params, headers=headers)
if response:
    print (response.json())

其中 headers 不用改變,access_token 就是前面獲取得到的 token ;重點是 params 參數,裏面需要寫入三個參數: image,image_type,image_filed:

image 當image_type = BASE64,填入圖片base64編碼(指的是本地文件);
當image_type = URL,填入圖片鏈接
當image_type = FACE_TOKEN,填入圖片 FACE_TOKEN;
image_type BASE64:圖片的base64值,base64編碼後的圖片數據,編碼後的圖片大小不超過2M;
URL:圖片的 URL地址( 可能由於網絡等原因導致下載圖片時間過長);
FACE_TOKEN: 人臉圖片的唯一標識,調用人臉檢測接口時,會爲每個人臉圖片賦予一個唯一的FACE_TOKEN,同一張圖片多次檢測得到的FACE_TOKEN是同一個。
image_filed 指的是你想要的信息,例如:age,beauty,expression,face_shape,gender,glasses,landmark,landmark150,race,quality,eye_status,emotion,face_type

image 的 BASE64 編碼值指的時本地文件讀取, 可以利用 base64.b64enconde 函數進行獲取,params 也可以寫成鍵值對字典形式:

params = {
                'image': str(base64.b64encode(open(file_name, 'rb').read()), 'utf-8'),#file_name指的時圖片的本地路徑;
                'image_type': 'BASE64',
                'face_field': 'age,beauty,expression,face_shape,location,gender'
            }

官方文檔對於 image_filed 介紹的很詳細,下面我貼上其中一部分,更詳細的可以參考:https://cloud.baidu.com/doc/FACE/s/yk37c1u4t ;

Snipaste_2020-03-05_10-29-20.jpg

爲了後面的獲取人臉裁剪位置,這裏在 image_filed 中加入了 location 參數,返回的結果中會有 location json 格式數據 ,裏面有人臉 left、width、top、height 等座標參數;得到這 4 個參數之後,用 **PIL 的 image.crop ** 函數得到人臉裁剪圖像

關於圖像人臉的全部信息會以 json 格式返回,requests 使用接口時需要注意的是 post 方式;到這裏 人臉識別API 獲取及使用方法已經介紹完畢了。

2.1,利用qt designer 進行界面設計;

這裏自己偷了個懶,不想寫代碼,直接用 qt designer 工具設計了一個簡單界面(下面是初期的界面,後面用代碼改了一部分):

Snipaste_2020-03-05_10-58-33.jpg

界面中用兩個 Label 來放置原圖和裁剪之後的圖片,背景設爲不同顏色,左下角用三個 pushbutton 來作爲打開、保存、裁剪按鈕(上圖中的界面在後續用代碼做了一些改動)。

界面的右下角就是用於預覽 人臉識別後的信息:年齡、性別、顏值、臉型等。

Qt designer 設計好的界面以 ui 文件保存,用 PyGUI 工具把 .ui 轉化爲 .py

2.3,界面信號—槽鏈接

這一步就是把 2.1 獲取得到的信息 在 2.2 中的設計的界面進行鏈接,用專業一點術語就是 信號槽鏈接,在此之前需要構造槽函數

首先,實現open 讀取圖片、預覽功能函數,按鈕信號槽鏈接;

    self.pushButton.clicked.connect(self.open_file)#signal-slot connect
    
    def open_file(self):
        file_name = QFileDialog.getOpenFileName(self,"Open file..","/",'all files:(*.png);;(*.jpg)')
        if file_name[0]:#File exits
            #clear the contend of label;
           self.label.clear()
           self.label_2.clear()
           self.file_name = file_name[0]
           print("file name: {}".format(str(self.file_name)))
           img = Image.open(self.file_name)
           pixmap = ImageQt.toqpixmap(img)
           self.label.setPixmap(pixmap)
           self.label.setScaledContents(True)
           self.pushButton_2.setEnabled(True)

        else:
            QMessageBox.warning(self,"waring","文件爲空無法轉換")

其次,實現 **Convert **按鈕鏈接、圖片裁剪、信息顯示功能:

 self.pushButton_2.clicked.connect(self.get_date)#signal-slot connect
 
 
 def get_token(self):#get token
        get_token_url = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={}&client_secret={}'.format(
            self.api, self.keys)
        try:
            res = requests.get(get_token_url).json()['access_token']
            return str(res)
        except:
            return 0

    def get_date(self):
        if self.file_name:
            params = {
                'image': str(base64.b64encode(open(self.file_name, 'rb').read()), 'utf-8'),
                'image_type': 'BASE64',
                'face_field': 'age,beauty,expression,face_shape,location,gender'
            }
            headers = {'content-type': 'application/json'}
            # 構造百度人臉檢測請求url,獲取token;,
            token = self.get_token()
            res_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token={}".format(str(token))
            res = requests.post(res_url, data=params, headers=headers)
            try:
                total_list = res.json()['result']['face_list']
                loacation = total_list[0]['location']
                left = int(loacation['left']) - 10
                upper = int(loacation['top']) - 10
                right = int(loacation['left']) + int(loacation['width']) + 10
                bottom = int(loacation['top'] + int(loacation['height'])) + 10
                img = Image.open(self.file_name).crop((left, upper, right, bottom))
                print(res.json())
                self.crop_pixmap = ImageQt.toqpixmap(img)
                self.label_2.setPixmap(self.crop_pixmap)
                self.label_2.setScaledContents(True)

                age = total_list[0]['age']
                print(age)
                self.lineEdit.setText(str(age))

                self.lineEdit.setAlignment(Qt.AlignCenter)
                gender = total_list[0]['gender']['type']
                print(gender)
                self.lineEdit_2.setText(str(gender))
                self.lineEdit_2.setAlignment(Qt.AlignCenter)
                beauty = total_list[0]['beauty']
                self.lineEdit_3.setText(str(beauty))
                self.lineEdit_3.setAlignment(Qt.AlignCenter)
                face_shape = total_list[0]['face_shape']['type']
                self.lineEdit_4.setText(str(face_shape))
                self.lineEdit_4.setAlignment(Qt.AlignCenter)


                # Save pushbutton 保存一致;
                self.pushButton_3.setEnabled(True)

            except:
                QMessageBox.warning(self,'error','Face recognise failed!')
        else:
            QMessageBox.information(self,'info','The file path of pic is not exist!')

裁剪圖像保存,save 按鈕信號槽連接:

    self.pushButton_3.clicked.connect(self.save_file)# signal-slot connect
    
    
    def save_file(self):
        self.pushButton_3.setEnabled(True)
        name = QFileDialog.getSaveFileName(self,'Save file','/','png:(*.png);;jpg:(*.jpg)')
        if name[0]:
            img = ImageQt.fromqpixmap(self.crop_pixmap)
            img.save(str(name[0]))
            QMessageBox.information(self,'info','{} saved successfully'.format(str(name[0])))
        else:
            QMessageBox.warning(self,'error','{} saved failed'.format(str(name[0])))

3,關於 API接口的一點吐槽

以上就是關於 人臉識別小程序 製作的完整過程,感興趣的同學也可以試一下,完整源碼獲取方式:在公衆號(Z先生點記)後臺回覆關鍵字 人臉識別 即可。

在程序製作過程中,對百度 人臉識別API 做次性能測試, 在 meizi圖 網站 抓了400來張圖片,分別調用API進行識別、裁剪,並把返回的年齡、性別等信息保存到 excel 表格中;

原圖就不放了,下面是裁剪後圖片,裁剪的效果還是不錯的,

Snipaste_2020-03-05_11-55-41.jpg

但是識別年齡方面存在一點問題:返回的基本都是在21-23整個區間,也不知道是爬取圖片中的妹子都這麼年輕,還是公開的 API 在年齡識別方面具有侷限性。

Snipaste_2020-03-05_12-00-33.jpg

最後,感謝閱讀!

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