遇到的問題:sudo?apt-get?install?python-imaging?
安裝過程中提示cache size空間不足。
解決:sudo apt-get clean ,然后sudo apt-get update,再次使用sudo apt-get install “需要安裝的文件”
@author:wepon
@blog:http://blog.csdn.net/u012162613/article/details/43523507
做人臉識別,首先要檢測出圖片/視頻中的人臉,今天就研究了一下OpenCV的Python接口,把常用的一些功能模塊寫成函數(shù)。基于Python-OpenCV以及PIL,實現(xiàn)圖片中人臉的檢測以及截取保存、眼睛檢測、笑臉檢測。下面簡單總結一下。
一、軟件安裝
安裝Python-OpenCV以及其依賴庫、PIL,通過軟件包管理器安裝即可(Ubuntu系統(tǒng)):
[python]?view
plain?copy
sudo?apt-get?install?libopencv-*??
sudo?apt-get?install?python-opencv??
sudo?apt-get?install?python-imaging??
安裝完后,在”/usr/share/opencv/haarcascades/”目錄下,可以看到很多的xml文件,如下圖。這些文件保存的就是訓練好之后的haar特征,關于人臉檢測的haar分類器,推薦博文:《淺析人臉檢測之Haar分類器方法》、《目標檢測的圖像特征提取之(三)Haar特征》。本文不闡述原理,只介紹怎么用這些xml文件來進行人臉檢測。
二、python-opencv實現(xiàn)人臉檢測
人臉檢測
定義人臉檢測函數(shù)detectFaces(),檢測圖片中所有出現(xiàn)的人臉,并返回人臉的矩形坐標(矩形左上、右下頂點坐標)。使用上面提到的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.3和5是特征的最小、最大檢測窗口,它改變檢測結果也會改變 ????result?=?[] ????for?(x,y,width,height)?in?faces: ????????result.append((x,y,x+width,y+height)) ????return?result
代碼很好理解,先加載xml文件生成級聯(lián)分類器face_cascade,然后用這個級聯(lián)分類器對灰度圖進行檢測face_cascade.detectMultiScale(gray, 1.2, 5),返回值即圖片中所有人臉的坐標(x,y,w,h),在上面的函數(shù)中,我們轉化了一下,使得函數(shù)返回的是人臉矩形的左上、右下頂點坐標。(注:坐標零點即原始圖像左上頂點,往下y增加,往右x增加)。
?
截取保存人臉圖
上面的detectFaces函數(shù)我們獲得了圖片中所有人臉的坐標,在有些時候,我們希望把人臉截取出來,然后進行下一步操作(比如做人臉身份識別、表情識別等),保存人臉圖的函數(shù)如下,使用了PIL的Image模塊:
def?saveFaces(image_name): ????faces?=?detectFaces(image_name) ????if?faces: ????????#將人臉保存在save_dir目錄下。 ????????#Image模塊:Image.open獲取圖像句柄,crop剪切圖像(剪切的區(qū)域就是detectFaces返回的坐標),save保存。 ????????save_dir?=?image_name.split('.')[0]+"_faces" ????????os.mkdir(save_dir) ????????count?=?0 ????????for?(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
?
?
框出人臉
有些時候,為了展示或者方便觀察,需要在原始圖像上框出人臉,用矩形將人臉框出,這個功能的實現(xiàn)如下,主要用到PIL的ImageDraw模塊(另外,opencv也有畫矩形工具,也可以實現(xiàn)):
#在原圖像上畫矩形,框出所有人臉。 #調(diào)用Image模塊的draw方法,Image.open獲取圖像句柄,ImageDraw.Draw獲取該圖像的draw實例,然后調(diào)用該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文件??梢韵窈瘮?shù)detectFaces()那樣,將檢測face的xml文件換成檢測eyes的xml文件即可。但是,由于眼睛在人臉上,我們往往是先檢測出人臉,再細入地檢測眼睛。故detectEyes可在detectFaces基礎上來進行,代碼中需要注意“相對坐標”。detectEyes()函數(shù)同樣返回所有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文件,在圖片上檢測出人臉(眼睛、鼻子、笑臉…)的坐標,利用這個坐標,我們可以將人臉區(qū)域剪切保存,也可以在原圖上將人臉框出。剪切保存人臉以及用矩形工具框出人臉,本程序使用的是PIL里的Image、ImageDraw模塊。此外也可以用opencv里的畫圖工具畫矩形。
?
代碼文件放在我的github上:wepe/OpenCV-demo/FaceDetection_python-opencv
參考:
1、OpenCV-Python Tutorials ? Object Detection ??Face Detection using Haar Cascades
2、?Python Imaging Library Handbook