基於OpenCV的人臉檢測——C++和Python實現
弄了一天終於實現了簡單的人臉識別,參考學習的書籍《OpenCV影象處理程式設計例項》裡的程式碼並不合適,可能是我並沒有完全照抄書上的程式的原因,但是《OpenCV3計算機視覺Python語言實現》一書中關於人眼檢測那部分程式碼也是不行的,最後經過自己的簡單修改才實現的最後效果。
本來之前用著VS2013 Pro(版本VC12)的,但是前幾天電腦中毒了系統環境變數PATH全沒了,VS2013也打不開,重新設定之後還是有問題,昨天又花了一晚的時間將OpenCV3.1用TDM-GCC編譯出來,在codeblocks16.04上編寫工程,之前對codeblocks瞭解不多,這幾天也正好學習了。下面記錄一下今天的結果(主要是貼程式碼了~~),以備日後自己參考和提供入門新手的一些借鑑。
系統環境:win10 64bit
C++實現:
編譯器Compiler: TDM-GCC64(基於GCC5.1.0)
整合開發環境IDE:Codeblocks16.01 ,我之前的一篇文章說codeblocks下載自帶mingw編譯器的,但是從官網的說明來看mingw是32位版本的,也是基於TDM-GCC的,如果需要64位的就要另外安裝TDM-GCC64。另外可以提一下mingw(mingw32),mingw64和TDM-GCC是不同的,具體可以自行搜尋,總的來說TDM-GCC效能最穩定。
下面是檢測的子函式,大部分都有註釋了:
int detectfaces(Mat frame)
{
cv::CascadeClassifier face_cascade,eyes_cascade;
cv::String window_name = "Face detect" ;
/*!//載入Haar級聯檔案,由此執行人臉檢側和人眼檢測!*/
face_cascade.load("haarcascade_frontalface_default.xml");
eyes_cascade.load("haarcascade_eye.xml");
std::vector<Rect> faces; //儲存人臉位置
std::vector<Rect> eyes; //儲存人眼位置
Mat grayImg ;
cvtColor(frame, grayImg,COLOR_BGR2GRAY); //轉化為灰度圖
equalizeHist(grayImg,grayImg); //直方圖均衡
//多尺度人臉檢測
face_cascade.detectMultiScale(grayImg, faces, 1.1, 3,
0|CASCADE_SCALE_IMAGE, Size(30,30));
//人臉檢測結果判定
for(size_t i = 0;i < faces.size(); i++)
{
Point center(faces[i].x + faces[i].width/2,
faces[i].y + faces[i].height/2);
Point pt1(faces[i].x,faces[i].y); //矩形左上角座標
Point pt2(faces[i].x+faces[i].width, faces[i].y+faces[i].height); //矩形右下角座標
Mat face = grayImg(faces[i]);
rectangle(frame,pt1,pt2,Scalar(255,0,0),4); //繪製矩形,藍色邊框(BGR格式),邊框大小為4
/*!書籍上第一個引數是face,即人臉區域,但是不行,最後換成轉換出來的灰度圖就可以了,
原因不明,還在繼續學習中!*/
eyes_cascade.detectMultiScale(grayImg, eyes, 1.33, 2,
0 | CASCADE_SCALE_IMAGE, Size(30,30));
}
主函式:
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char *argv[])
{
VideoCapture cap(0); //新建VideoCapture物件
Mat frame;
while(cap.read(frame)) //開啟攝像頭
{
detectfaces(frame);
if(char(waitKey(1))=='Q') //如果按下‘Q'就退出
break;
}
return 0;
}
Python實現:
IDE: 輕量級的IDE——Pyzo ,效能很穩定,可以方便切換python2和python3環境,支援tab自動補全程式碼,當然,不足之處就是介面主題單一無法修改等。順便提一下,我自己用的是IEP3.7 (IEP是Pyzo老版本,官網有說明),本來一開始也是安裝了最新版本的Pyzo4.3.1,但是安裝完之後執行mayavi的函式會報錯,提示說mayavi不支援Pyqt5,查看了一下Pyzo的安裝檔案都是PyQT5的,應該是這裡起衝突了,換回IEP3.7就沒問題了。
程式碼如下:
import cv2
##下面的haarcascade_frontalface_alt2.xml和cascades\\haarcascade_eye.xml在opencv3.1原始碼的$opencv_source_path$/data/haarcascades下面,本地沒有原始碼的話可以去github線上找
def detect():
face_cascade = cv2.CascadeClassifier("D:\\Files\\python\\python2\\facialdetect\\cascades\\haarcascade_frontalface_alt2.xml") #載入級聯檔案
eye_cascade = cv2.CascadeClassifier("D:\\Files\\python\\python2\\facialdetect\\cascades\\haarcascade_eye.xml")
cap = cv2.VideoCapture(0) #開啟攝像頭
while (cap.isOpened()): #如果打開了攝像頭
ret,frame = cap.read() #獲取幀資料
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) #繪製矩形
#同樣,書籍的程式碼是給出 roi_gray 這個人臉區域來識別眼睛,但是不行,大家可以試試把下面引數 img 改回roi_gray
#roi_gray = gray[y:y+h,x:x+w]
eyes = eye_cascade.detectMultiScale(img,1.03,5,0,(30,30)) #人眼檢測
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(frame, (ex,ey), (ex+ew,ey+eh),(0,255,0),2) #繪製矩形
cv2.imshow('face',frame)
if cv2.waitKey(1) & 0xff == ord("Q"):
break
cap.release()
cv2.destroyAllWindows()
detect()
最終截圖就不貼出來了,從結果可以發現用Python的效果比較好,自己也沒怎麼去調引數了,detectMultiScale函式的一些引數可以調整來改變效果的。暫時先記錄到這裡了!
參考資料:
《OpenCV影象處理程式設計例項》
《OpenCV3計算機視覺Python語言實現》