1. 程式人生 > >OpenCV3計算機視覺Python語言實現人臉識別筆記

OpenCV3計算機視覺Python語言實現人臉識別筆記

     老衲最近在學習《OpenCV3計算機視覺Python語言實現》中文版,學到第五章人臉識別時懵逼了,書上程式碼都是片段,不會搞啊,不死心找了英文版官網的原始碼,找了個遍,發現原版原始碼排版錯誤,把第四章的程式碼貼到了第五章裡。網上搜了一大圈,貌似各位大神都沒怎麼說到這章。腫麼辦,硬辦。老衲來死磕,下面給出我的方法。老衲平板電腦是七彩虹的i818w,CPU是Z3735F,記憶體2G,32位作業系統。裝了Anaconda2,opencv3.0.0,python是2.7。

    第一步,生成人臉識別資料。還好這段程式碼比較全,也是正確的。

import cv2

def generate():
    # 老衲把臉的特徵檔案放在了C盤,用絕對路徑呼叫,書上是相對路徑,xml檔案在opencv/sources/data/haarcascades裡,拷到下面的路徑裡
    face_cascade = cv2.CascadeClassifier('C:\MyW\cascades\haarcascade_frontalface_default.xml')
    # 開啟攝像頭,老衲用的是7寸windows平板,帶兩個攝像頭,1是前置,0是後置
    camera = cv2.VideoCapture(1)
    count = 0
    while (True):
        ret, frame = camera.read()
        # 作為初學者,老衲懷疑所有的新東西,print一下看看ret的輸出
        print ret
        
        # 把攝像頭的每一幀影象轉換成灰度影象,這時書上就比較亂了
        # 有用cv2.cvtColor(frame, 1)也有用下面的,其實都一樣
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 檢測人臉,沒好多說的,自己網上查大神們寫的吧,不解釋
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
        # 接下來就是迴圈儲存圖片了
        for (x, y, w, h) in faces:
            # 先畫一個正方形,這很簡單
            img = cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
            
            # 接下來把影象全部格式化成200x200畫素
            f = cv2.resize(gray[y: y+h, x:x+w], (200, 200))
            
            # 儲存圖片為opencv專用的*.pgm格式
            cv2.imwrite('C:\MyW\date\%s.pgm' % str(count), f)
            count += 1

        # 把咱們的老臉顯示在camera名字的窗口裡    
        cv2.imshow("camera", frame)
        # 這裡就個人理解是影象每秒12幀,當按下q鍵時退出while迴圈
        if cv2.waitKey(1000 / 12) & 0xff == ord("q"):
            break
    # 釋放攝像頭控制代碼
    camera.release()
    # 銷燬視窗,這句很重要,書上老漏導致老衲經常宕機
    cv2.destroyAllWindows()

# 開始執行
if __name__ == "__main__":
    generate()
    第二步,本著嚴謹的態度,老衲必須檢視剛剛儲存的人臉特徵圖,就是老衲的臉啦。用程式碼顯示出來。
import cv2

# 開啟C盤路徑下儲存圖片的12.pgm檔案,並儲存為灰度影象
img = cv2.imread('C:\\MyW\\date\\12.pgm', cv2.IMREAD_GRAYSCALE)
# 順便看看圖片的格式,好大的一個列表物件,
# 裡面的陣列代表了圖片上一個個行和列上的畫素,格式是[xxx,xxx,xxx]
# xxx = 0~255
print img
# 在名為img的視窗上顯示圖片,畫素為200x200
cv2.imshow('img',img)
cv2.waitKey()
cv2.destroyAllWindows()
    第三步,上正菜,老衲覺得出版社太坑了,給了很多片段,還不給全部原始碼,老衲一向自給自足豐衣足食,來看下面老衲整理的一大片程式碼。
#coding=utf-8
import os
import sys
import cv2
import numpy as np

# 圖片的路徑
filepath = 'c:\\MyW\\date\\'
# 定義2個數組,X存放每幅圖片的陣列列表,y存放每幅圖片的序號,後面有句print函式
# 可以在IDLE裡看哪張圖片特徵最匹配實時檢測到的臉,並給出置信度
X = []
y = []

# 顧名思義,讀取特徵圖片
def read_images(path):
    # 初始化計數器
    c = 0

    # 掃描路徑下的路徑名,檔名,不明白的可以在下面print一下
    for dirname, dirnames, filenames in os.walk(path):
        # print dirname, dirnames, filename
        # 提取每個檔案並儲存到X,y數組裡,這裡老衲做了點改動,應為老衲的特徵圖片路徑沒有書上程式碼那麼深
        for filename in filenames:
            try:
                # 組合路徑和檔名,得到特徵圖的絕對路徑c:\MyW\date\1.pgm
                filename = os.path.join(path, filename)
                # 把特徵圖以灰度圖讀取
                im = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)

                # 重新格式化圖片為200x200畫素,原書估計打錯字了
                if (im is not None):
                   im = cv2.resize(im, (200, 200))

                # 把特徵圖片陣列新增到X陣列中,組成一個大的特徵陣列
                X.append(np.asarray(im, dtype=np.uint8))
                y.append(c)
            # 輸入輸出錯誤檢查
            except IOError, (errno, strerror):
                print "I/O error({0}): {1}".format(errno, strerror)

            except:
                print "Unexpected error:", sys.exc_info()[0]
                raise
            c = c + 1
    #print X
    #print y
    # 估計到這,這陣列的維度大得嚇人了
    return [X, y] 

# 顧名思義,人臉檢測開始了
def face_rec():
    # 定義一個名字的陣列,隨便瞎打幾個英文字母,等會下面會用到
    names = ['SHG', 'JSY', 'LYF']
    # 載入特徵圖片
    [x, y] = read_images(filepath)
    # 把y陣列儲存為int32格式的陣列,用asarry()不用開闢新的記憶體,其實老衲覺得array()函式也可以,現在誰的電腦記憶體沒個幾G啊
    y = np.asarray(y, dtype=np.int32)
    # 載入EigenFaceRecognizer演算法,這裡必須改為EigenFaceRecognizer_create,原書createEigenFaceRecognizer
    # 因為老衲用的是opencv_contrib_python-3.4.0.12-cp27-cp27m-win32.whl
    # 如何安裝contrib請各位施主自行百度,後面會講一個老衲安裝時碰到的小故事
    model = cv2.face.EigenFaceRecognizer_create()
    # 訓練資料集,貌似機器學習,好高深,不深究
    model.train(np.asarray(X), np.asarray(y))

    # 和第一步裡generate()裡的用法一樣,懶得解釋了
    face_cascade = cv2.CascadeClassifier('C:\MyW\cascades\haarcascade_frontalface_default.xml')
    camera = cv2.VideoCapture(1)
    
    while (True):
        read, img = camera.read()
        faces = face_cascade.detectMultiScale(img, 1.3, 5)
        for (x, y, w, h) in faces:
            img = cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            roi = gray[x: x+w, y: y+h]
            try:
                # 選出感興趣的區域,使用內插法,還是老規矩自行百度
                roi = cv2.resize(roi, (200, 200), interpolation=cv2.INTER_LINEAR)
                # 預測實時圖片,這裡老衲也沒看明白,下次有時間去看看EigenFaceRecognizer的方法
                params = model.predict(roi)
                # 把匹配的特徵和置信度列印在IDLE內
                print "Label: %s, Confidence: %.2f" % (params[0], params[1])
                # 把匹配的名字顯示在方框左上角,有時候會瞎顯示,以後研究,還有就是現在無法顯示中文字元,也以後吧 :P
                cv2.putText(img, names[params[0]], (x, y - 20), \
                            cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)
            except:
                continue
        cv2.imshow("camera", img)
        if cv2.waitKey(1000 / 12) & 0xff == ord("q"):
            break
    cv2.destroyAllWindows()

if __name__ == "__main__":
    face_rec()
    第四步,按F5執行,噹噹噹當,老衲被照妖鏡照出來啦,悟空,師傅不是妖精。

參考:1.《OpenCV3計算機視覺Python語言實現》作者:喬.米尼奇諾 約瑟夫.豪斯
         2. 《人臉識別經典演算法實現(一)》  作者:freedom098  點選開啟連結