動手實操 | 如何用 Python 實現人臉識別,證明這個楊冪是那個楊冪?

七牛雲發表於2017-07-21

當前,人臉識別應用於許多領域,如支付寶的使用者認證,許多的能識別人心情的 AI,也就是人的面部表情,還有能分析人的年齡等等,而這裡面有著許多的難度,在這裡我想要分享的是一個利用七牛 SDK 簡單的實現人臉識別的方法,當然七牛的 SDK 中提供了很多的擴充,在返回的 JSON 中包含著如年齡等資訊,這裡就不進行分享了。這裡我們要使用的是七牛雲平臺中由第三方資料處理提供的 API。

以下為官方給出的功能:

  • 人臉 1v1 比對
  • 人臉關鍵點(106 點)
  • 人臉屬性(年齡,性別)

我們要用的服務就是第一個:人臉 1v1 比對

需求分析

要做安全方面的內容,依靠人臉識別通過和庫中的臉比對後判定相似率來驗證使用者身份。

快速從圖片中識別出人的資訊,用於尋人功能等。

其實從安全的角度出發有很多可以囊括的。比如智慧家居中的刷臉開門,支付軟體的刷臉支付等都是例子。

人臉特徵提取的步驟

真正的人臉識別需要很多的知識,大體上粗略的可以分為以下步驟:

  1.人臉檢測(從圖片中找到人臉):返回人臉位置和大小的引數。
  2.人臉特徵定位:一般 69 點或者 106 個點對人臉的特徵定位,技術上有 Adaboost&haar,以及 MSRA 的 alignment。
  3.人臉特徵歸一化(幾何歸一/灰度歸一):前者對影象進行仿射變化使得不同的臉可以進行比對,後者則能使影象展現更多的細節以及減弱光線光照的應用。
  4.特徵提取-特徵後期融合。(基於特徵近似度的多特徵融合)
  5.特徵距之間的距離來比對相似度、三氏距離。(馬氏、歐氏 、巴氏)

(以上根據以前查到整理的資料得出,可能會存在認識錯誤)
可以看出如果直接對人臉進行分析是很複雜的,而現在也有很多成熟的人臉識別庫,像是有名的 OpenCV ,OpenBR,還有國產的 Seeta Face engine 等等很多,這裡就先不介紹了,而利用開源雲平臺的 API 可以使我們的工作量更加的小。

七牛雲 API 的優點

應用七牛雲平臺的 API 對於使用者的能力要求較低,開發速度很快,只要輸入/返回即可,但更加適用於移動端。

操作過程中的注意事項

  1. 每張圖片要先上傳到 bucket 中才可以利用。
  2. API 對人臉匹配再返回很大程度依賴於使用者的網路頻寬。
  3. 當使用者網路不好的情況下需要很久的時間才能得到返回結果。
  4. 要經過壓縮處理,一般識別的較為準確最多可將圖片壓縮至 25 kb 左右。

使用七牛 API 的介面準備

我們需要用到的有 Qiniu 庫的上傳/鑑權命令,以及 requests 庫得到處理後的影象,以及 json 庫得到返回給我們的儲存在 JSON 中的資訊。

另外七牛的這個介面和圖片瘦身介面一樣也是要付錢的,具體的價格根據官方給的是(人臉識別對比服務 ->¥1.5/1000次 )可以先向賬戶充入 ¥2 避免無法使用服務。

解決問題的步驟

為了簡化這個問題,所以本例項僅凸顯 上傳->識別 ->返回結果 的過程,對於如何通過電腦攝像頭取像,窗體制作僅提供方法和思路不進行詳細分享。

首先,我們先分析七牛雲中這個 API 的介面 :

http://xxx.xxx.glb.clouddn.com/xxx.jpg?faceanalyze/verification/url/<urlSafeBase64URI><!-- 人臉一對一比對API-->複製程式碼

我們來分析下這個介面:
前面的xxx.xxx.glb.clouddn.com/xxx.jpg是我們剛… 是 API 的介面,其中我們將最後的這句 單獨拿出來說,因為這個的意思是要將我們用於人像比對的標準人像圖片的地址經過 urlbase64 加密後的地址資訊。

所以我們要進行如下的步驟:

1)得到我們剛剛通過攝像頭取得的人像
2)對我們的人像圖片進行壓縮
3)上傳我們的人像圖片到我們的 bucket 中
(這裡要申明一點,七牛所有支援的 API 都要求檔案在華東的 Bucket 下)
4)得到我們上傳的圖片的連結地址
5)對連結進行 urlbase64 加密(這裡只要 import python 的 base64 庫即可)
6)請求 API
7)得到網頁的 JSON 格式資料
8)通過 JSON 庫對資料進行分析
9)判斷人臉的相似度是否符合,輸出結果
10)刪除 Bucket 中上傳的臨時圖片

返回的 JSON 格式分析

{"status":"ok","confidence":0.73065597}複製程式碼

我們可以看到返回的 JSON 資訊很簡單, status 的意思是成功和不成功,而 confidence 則是相似度,所以我們對返回的資訊進行分析會很簡單。 status 如若成功則為 ok,不成功則為 invalid。

人臉相似度的判斷

上表中所用的圖片都來自己網際網路,從表資料我們可以大致將本人的相似度以 0.7 為分界線。不過有趣的是,不知道為什麼按楊冪進行整容的為什麼相似度竟然低於楊冪和范冰冰的相似度(其他女星照的圖片為范冰冰的人像),不同性別的相似度差異明顯,所以就粗略的根據表格定為 >0.7 即可認為是本人。

安裝所需的庫

在 python 中,我分享的這個例子總共需要引入 6 個庫

#import SDK
from qiniu import Auth,put_file,etag
import qiniu.config
import requestsimport base64
import json
from PIL import Image
import os複製程式碼

requests 庫,json 庫,PIL 庫請自行安裝;
base64 庫和 OS 庫為自帶所以無需安裝。

(由於電腦已經安裝了較多庫,所以對於這些庫是否為自帶也記得不太清楚,如果出現了錯誤,請大家對應自己安裝。)

程式的實現

請見下方的程式碼,採集到的人臉為 face.jpg。 (這裡用了楊冪的兩張圖片作為示例)

#七牛雲"人臉識別"功能的python實現方法:by xlxw
#請得到自己的Secret和Access key用於上傳圖片到空間中進行處理
#人像識別是七牛雲的一項收費專案,價格為 ¥1.5/1000次 測試時請先存2元避免意外

#import SDK
from qiniu import Auth,put_file,etag
import qiniu.config
import requests
import base64
import json
from PIL import Image
import os

#上傳
def upload(bucket,path,filename,key,url):
    token = key.upload_token(bucket, filename, 3600)
    print('正在上傳..')
    reform,inform = put_file(token, filename, path)
    if reform != None:
        print('已經成功地將{}->>{}'.format(filename,bucket))
        print("正在處理您的圖片...")
        url=url + '/' + filename
        path=path.split('/')[-1]
    else:
        print('這裡出現了一個小錯誤.無法上傳..')

#呼叫API
def apiget(urlbucket,url):
    try:
        url=urlbucket + '/001.jpg' + '?face-analyze/verification/url/' + url
        #標準對比的圖片地址,名稱為001.jpg
        r=requests.get(url)
        r.raise_for_status()
        r.encoding=r.apparent_encoding
        return r.text
    except:
        print("網路發生故障,請重試..")

#base64 Encode
def base64encode(url):
    try:
        print("正在加密連結..")
        enurl=base64.urlsafe_b64encode(bytes(url, "utf-8"))
        print("加密完成")
        enurl=str(enurl)
        enurl=enurl.split("'")[1]
        return enurl
    except:
        print("這裡出現了一個問題,請重試..")

#PIL 圖片壓縮
def pilresize(per,path):
    im=Image.open(path)
    imsize=im.size
    sizex=int(imsize[0]*per)
    sizey=int(imsize[1]*per)
    im=im.resize((sizex,sizey))
    im.save('trans.jpg','JPEG')
    print('圖片壓縮完成,輸出成功')
    print('{}->>({},{})'.format(imsize,sizex,sizey))

def pilwork(path):
    try:
        size=os.path.getsize(path)
        size = float(size)
        kb=size/1024
        per=10/kb
        pilresize(per,path)
    except:
        print("請檢查您的地址是否輸入錯誤")


#JSON分析
def jsonanal(jtext):
    print("正在分析,請稍後..")
    rj=json.loads(jtext)
    stat=rj['status']
    confi=rj['confidence']
    return stat + ',' +str(confi)

#主體
def main():
    #填寫你的 AK 和 SK
    accesskey = input('請輸入您在七牛雲的AccessKey:')
    secretkey = input('請輸入您在七牛雲的SecretKey:')

    #鑑定身份
    keyq=Auth(accesskey,secretkey)

    #所要操作的空間
    bucketname =input("請輸入要操作的空間(公開)名字:")

    #所要操作空間的外鏈地址
    urlbucket = input("請輸入空間所繫結的域名或者預設外鏈地址:")

    #判定操作型別
    while 1:
        order=input('請輸入你需要進行的操作:')
        mode=order.split(' ')[0]
        if mode == '識別':
            path=order.split(' ')[1]
            fname=path.split('/')[-1:][0]
            unrl=urlbucket+'/trans.jpg'
            print('正在壓縮圖片.請稍後..')
            #呼叫函式
            pilwork(path)  #壓縮圖片
            print("正在上傳token,請稍後..")
            upload(bucketname,'./trans.jpg','trans.jpg',keyq,urlbucket) #上傳檔案
            enurl=base64encode(unrl)   #base64加密
            jtext=apiget(urlbucket,enurl) #呼叫七牛api並得到返回的json資料
            result=jsonanal(jtext)  #分析返回的json,得到最終相似度
            if result.split(',')[0] == 'invalid':
                print('識別發生了錯誤')
            else:
                if eval(result.split(',')[1]) >= 0.7:
                    print("識別成功,鑑定為本人,相似度為{:.1f}".format(eval(result.split(',')[1])*100))
                else:
                    print("識別成功,鑑定不是本人,相似度過低")
        if mode == '退出':
            print("歡迎您的使用..")
            break

#終端提示顯示
print("+----------------------------------------+")
print("|        歡迎使用七牛的人臉識別功能      |")
print("+----------------------------------------+")
print("|本程式須知:                            |")
print("|1.本程式測試圖片為楊冪的人像,見face.jpg |")
print("|2.您需要提供服務的Accesskey,Secretkey  |")
print("|3.您需要提供 bucket名字和bucket外鏈地址 |")
print("+----------------------------------------+")
print("|使用方法:                               |")
print("|1.識別輸入格式: 識別 圖片位置(包括字尾)|")
print("|2.退出輸入格式: 退出                   |")
print("+----------------------------------------+")
main()複製程式碼

程式執行的截圖:

用到的楊冪的兩張照片為:
(均來自百度圖片)

(用於比對的標準人像圖片)
(已用 PIL 壓縮 x0.3,y0.3)

(用於比對的圖片)

總結和擴充

總結

和大家分享七牛的 API 差不多結束了(說不定以後有更好玩的 API 也會拿來分享經驗)。七牛還有許多優秀方便的 API 可以方便我們的使用.在這期間也學習到了很多的知識,比如許多庫的熟悉掌握,像是 requests 庫、bs4 庫、 json 庫當然還有主角 Qiniu 庫。

擴充

可以用 python 的 QT 庫開發圖形介面,而 VideoCapture 庫可用來呼叫電腦的攝像頭進行拍照,然後經過本文的方法就能實現簡單的人像識別了(你需要上傳標準圖片到 Qiniu 的 bucket 裡)。

可另外再加入一些標準圖片,如低光,不戴眼鏡等等的圖片,然後設計一個評判演算法來適應各種各樣的情況.本文就不再進行擴充,有興趣的朋友可以試試。


推薦閱讀


報名方式:有更多有趣的作品分享給大家?掃描上方二維碼和美女隊長接頭,即可成為【動手實操】系列玩家。

相關文章