1. 程式人生 > >Python-OpenCV人臉檢測---直接呼叫訓練好的Harr特徵

Python-OpenCV人臉檢測---直接呼叫訓練好的Harr特徵

  • 人臉檢測

定義人臉檢測函式detectFaces(),檢測圖片中所有出現的人臉,並返回人臉的矩形座標(矩形左上、右下頂點座標)。使用上面提到的xml檔案(haar特徵),haarcascades目錄下有好幾個是關於人臉檢測的檔案,這裡選擇haarcascade_frontalface_default.xml,當然也可以使用其他的。另外需要注意的是,必須以灰度圖作為haar分類器的輸入。

def detectFaces(image_name):
    img = cv2.imread(image_name)
    face_cascade = cv2.CascadeClassifier(
"/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml")if img.ndim ==3: gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)else: gray = img #if語句:如果img維度為3,說明不是灰度圖,先轉化為灰度圖gray,如果不為3,也就是2,原圖就是灰度圖 faces = face_cascade.detectMultiScale(gray,1.2,5)#1.35是特徵的最小、最大檢測視窗,它改變檢測結果也會改變 result
=[]for(x,y,width,height)in faces: result.append((x,y,x+width,y+height))return result

程式碼很好理解,先載入xml檔案生成級聯分類器face_cascade,然後用這個級聯分類器對灰度圖進行檢測face_cascade.detectMultiScale(gray, 1.2, 5),返回值即圖片中所有人臉的座標(x,y,w,h),在上面的函式中,我們轉化了一下,使得函式返回的是人臉矩形的左上、右下頂點座標。(注:座標零點即原始影象左上頂點,往下y增加,往右x增加)

  • 擷取儲存人臉圖

上面的detectFaces函式我們獲得了圖片中所有人臉的座標,在有些時候,我們希望把人臉截取出來,然後進行下一步操作(比如做人臉身份識別、表情識別等),儲存人臉圖的函式如下,使用了PIL的Image模組

def saveFaces(image_name):
    faces = detectFaces(image_name)if faces:#將人臉儲存在save_dir目錄下。#Image模組:Image.open獲取影象控制代碼,crop剪下影象(剪下的區域就是detectFaces返回的座標),save儲存。
        save_dir = image_name.split('.')[0]+"_faces"
        os.mkdir(save_dir)
        count =0for(x1,y1,x2,y2)in faces:
            file_name = os.path.join(save_dir,str(count)+".jpg")Image.open(image_name).crop((x1,y1,x2,y2)).save(file_name)
            count+=1
  • 框出人臉

有些時候,為了展示或者方便觀察,需要在原始影象上框出人臉,用矩形將人臉框出,這個功能的實現如下,主要用到PIL的ImageDraw模組(另外,opencv也有畫矩形工具,也可以實現):

#在原影象上畫矩形,框出所有人臉。#呼叫Image模組的draw方法,Image.open獲取影象控制代碼,ImageDraw.Draw獲取該影象的draw例項,然後呼叫該draw例項的rectangle方法畫矩形(矩形的座標即#detectFaces返回的座標),outline是矩形線條顏色(B,G,R)。#注:原始影象如果是灰度圖,則去掉outline,因為灰度圖沒有RGB可言。drawEyes、detectSmiles也一樣。def drawFaces(image_name):
    faces = detectFaces(image_name)if faces:
        img =Image.open(image_name)
        draw_instance =ImageDraw.Draw(img)for(x1,y1,x2,y2)in faces:
            draw_instance.rectangle((x1,y1,x2,y2), outline=(255,0,0))
        img.save('drawfaces_'+image_name)

好了,先看一下效果,執行drawFaces(‘obama.jpg’),得到右圖:

執行saveFaces(‘obama.jpg’),將在當前目錄下生成一個資料夾,並儲存上面框出來的人臉,當然,有一些人臉沒被檢測出來,有些不是人臉被誤認為人臉。

  • 眼睛檢測

在haarcascades目錄下,也有一些關於眼睛檢測的xml檔案。可以像函式detectFaces()那樣,將檢測face的xml檔案換成檢測eyes的xml檔案即可。但是,由於眼睛在人臉上,我們往往是先檢測出人臉,再細入地檢測眼睛。故detectEyes可在detectFaces基礎上來進行,程式碼中需要注意“相對座標”。detectEyes()函式同樣返回所有eyes在原圖中的座標。

def detectEyes(image_name):
    eye_cascade = cv2.CascadeClassifier('/usr/share/opencv/haarcascades/haarcascade_eye.xml')
    faces = detectFaces(image_name)

    img = cv2.imread(image_name)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    result =[]for(x1,y1,x2,y2)in faces:
        roi_gray = gray[y1:y2, x1:x2]
        eyes = eye_cascade.detectMultiScale(roi_gray,1.3,2)for(ex,ey,ew,eh)in eyes:
            result.append((x1+ex,y1+ey,x1+ex+ew,y1+ey+eh))return result
  • 框出眼睛
def drawEyes(image_name):
    eyes = detectEyes(image_name)if eyes:
        img =Image.open(image_name)
        draw_instance =ImageDraw.Draw(img)for(x1,y1,x2,y2)in eyes:
            draw_instance.rectangle((x1,y1,x2,y2), outline=(0,0,255))
        img.save('draweyes_'+image_name)

執行drawEyes(‘obama.jpg’),看下效果,非常差:


  • 笑臉檢測
def detectSmiles(image_name):
    img = cv2.imread(image_name)
    smiles_cascade = cv2.CascadeClassifier("/usr/share/opencv/haarcascades/haarcascade_smile.xml")if img.ndim ==3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)else:
        gray = img #if語句:如果img維度為3,說明不是灰度圖,先轉化為灰度圖gray,如果不為3,也就是2,原圖就是灰度圖

    smiles = smiles_cascade.detectMultiScale(gray,4,5)
    result =[]for(x,y,width,height)in smiles:
        result.append((x,y,x+width,y+height))return result
  • 框出笑臉
def drawSmiles(image_name):
    smiles = detectSmiles(image_name)if smiles:
        img =Image.open(image_name)
        draw_instance =ImageDraw.Draw(img)for(x1,y1,x2,y2)in smiles:
            draw_instance.rectangle((x1,y1,x2,y2), outline=(100,100,0))
        img.save('drawsmiles_'+image_name)

執行drawSmiles(‘obama.jpg’),看下效果,奧巴馬的眼睛會笑了:

總之,利用opencv裡訓練好的haar特徵的xml檔案,在圖片上檢測出人臉(眼睛、鼻子、笑臉…)的座標,利用這個座標,我們可以將人臉區域剪下儲存,也可以在原圖上將人臉框出。剪下儲存人臉以及用矩形工具框出人臉,本程式使用的是PIL裡的Image、ImageDraw模組。此外也可以用opencv裡的畫圖工具畫矩形。

參考: