使用OpenCV通過攝像頭捕獲實時視頻並探測人臉


Opencv初接觸,圖片的基本操作這篇手記中,我介紹了一些圖片的基本操作,視頻可以看作是一幀一幀的圖片,因此圖片操作其實是視頻操作的基礎,這篇手記就來講講OpenCV中的視頻操作,並實現一個用筆記本自帶的攝像頭探測人臉的小功能,最后會把人臉提取出來並保存,作為后續用卷積神經網絡進行人臉識別的訓練數據。

本地視頻讀取

OpenCV中是通過創建一個VideoCapture對象來捕獲視頻,這里先以讀取和播放本地視頻為例:

import cv2 cap = cv2.VideoCapture('clementi sonatina in f major, op. 36 no. 4.mp4') # 注意這里視頻放在當前工作目錄下,VideoCapture的參數就是視頻文件名 while(cap.isOpened()): # isOpened方法判斷視頻是否成功打開 ret, frame = cap.read() # read方法返回一個表示視頻是否正確讀取的布爾值和一幀圖像 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 這里用cvtColor(cvt就是convert的縮寫)方法進行色彩空間的轉換,這里是從BGR空間轉換到灰度空間 cv2.imshow('frame', gray) # 通過imshow顯示一幀圖像 if cv2.waitKey(1) & 0xFF == ord('q'): # 一幀顯示一毫秒,通過上面的while循環不斷地顯示下一幀,從而形成動態的視頻;按q鍵退出循環,關閉視頻。 break cap.release() cv2.destroyAllWindows()

通過筆記本攝像頭捕獲實時視頻流

通過上面讀取本地視頻的代碼,可以理解OpenCV中顯示視頻的原理就是通過循環不斷顯示下一幀圖像從而得到動態的視頻,下面,只需改變VideoCapture的參數就可以捕獲筆記本電腦攝像頭的實時視頻流:

import cv2 #引入cv2,也就是引入opencv的一些包和處理類,不然下面的一些操作都無法完成 #打開攝像頭的方法,window_name為顯示窗口名,video_id為你設備攝像頭的id,默認為0或-1,如果引用usb可能會改變為1,等 def openvideo(window_name ,video_id): cv2.namedWindow(window_name) # 創建一個窗口 cap=cv2.VideoCapture(video_id) # 獲取攝像頭 while cap.isOpened(): ok,frame=cap.read() # ok表示攝像頭讀取狀態,frame表示攝像頭讀取的圖像 if not ok : break cv2.imshow(window_name,frame) # 將圖像矩陣顯示在一個窗口中 c=cv2.waitKey(10) # 等待10ms,10ms內沒有按鍵操作就進入下一次while循環,從而得到10ms一幀的效果,waitKey返回在鍵盤上按的鍵 if c & 0xFF==ord('q'): # 按鍵q后break break # 釋放資源 cap.release() cv2.destroyWindow(window_name) print("cam closed") # 主程序調用方法運行 if __name__ == '__main__': # __name__ 是當前模塊名,當模塊被直接運行時模塊名為 __main__ 。這句話的意思就是,當模塊被直接運行時,以下代碼塊將被運行,當模塊是被導入時,代碼塊不被運行。 print ('open camera...') openvideo('mycam' ,0)

從實時視頻流中探測人臉

如果你跟着上面的代碼成功運行到了這一步,應該已經可以在打開的攝像頭窗口里看到自己的臉了,下面要做的就是從里面探測到你的臉了:

import cv2 def facedetect(windowname,camera_id): #命名和打開攝像頭 cv2.namedWindow(windowname) # 創建一個已windowname為名字的窗口 cap=cv2.VideoCapture(camera_id) # camera_id為設備攝像頭的id,默認是0,如果有usb攝像頭可能會變為1 # Face Detection using Haar Cascades http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_objdetect/py_face_detection/py_face_detection.html?highlight=cascadeclassifier classfier=cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml') # 加載分類器,分類器位置可以自行更改,注意這里用opencv庫文件夾下的絕對路徑也不行,在庫文件夾里找到這個文件復制到這個程序的同目錄下,參考:https://blog.csdn.net/GAN_player/article/details/77993872 color=(0,225,0)#人臉框的顏色,采用rgb模型,這里表示g取255,為綠色框 while cap.isOpened(): ok,frame=cap.read() # 讀取一幀數據,ok表示攝像頭讀取狀態,frame表示攝像頭讀取的圖像矩陣mat類型 if not ok: break # 灰度化在后面檢測時可以降低計算量,cvtColor changing colorspace gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#圖像灰度化,cv2.cvtColor(input_image, flag) where flag determines the type of conversion.

這一部分代碼在前面捕獲實時視頻流的基礎上加載了OpenCV所提供的用於對象檢測的分類器,注意分類器文件haarcascade_frontalface_alt2.xml可以在OpenCV包文件夾下找到,要放到當前工作目錄下才能使用,這個分類器就是用來探測人臉的,在探測到人臉后,我們要在視頻窗口中把人臉部分框出來,color變量就用來指定框的顏色,接着我們就來看看得到人臉框的代碼:

 # detectMultiScale完成人臉探測工作,returns the positions of detected faces as Rect(x,y,w,h),x、y是左上角起始坐標,h、w是高和寬 # grey是要識別的圖像數據,scaleFactor圖像縮放比例,可以理解為同一個物體與相機距離不同,其大小亦不同,必須將其縮放到一定大小才方便識別,該參數指定每次縮放的比例 faceRects=classfier.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=3,minSize=(32,32)) # 利用分類器檢測灰度圖像中的人臉矩陣數,1.2和3分別為圖片縮放比例和需要檢測的有效點數 if len(faceRects)>0:#大於0則檢測到人臉  for faceRect in faceRects:# 可能檢測到多個人臉,用for循環單獨框出每一張人臉 x,y,w,h=faceRect#獲取框的左上的坐標,框的長寬 # cv2.rectangle()完成畫框的工作,這里外擴了10個像素以框出比人臉稍大一點的區域,從而得到相對完整一點的人臉圖像;cv2.rectangle()函數的最后兩個參數一個用於指定矩形邊框的顏色,一個用於指定矩形邊框線條的粗細程度。 cv2.rectangle(frame,(x-10,y-10),(x+w-10,y+h-10),color,2) cv2.imshow(windowname,frame) # 顯示圖像 c=cv2.waitKey(10) if c&0xFF==ord('q'): # 退出條件 break cap.release()#釋放攝像頭並銷毀所有窗口 cv2.destroyAllWindows() if __name__ == '__main__':#主程序 print ('face detecting... ') facedetect('facedetect',0)

現在,運行上面的程序,應該就能在視頻窗口里看到你的臉被綠色的框框起來了,下一步我們要把框出來的人臉保存下來。

保存人臉圖像數據

上面的程序里我們已經得到了人臉區域的起始坐標和寬高,只需利用Opencv初接觸,圖片的基本操作這篇手記中提到的訪問圖片特定像素和區域的方法把這一區域單獨拿出來存成圖片就行了,這里的關鍵代碼是:

image = frame[y:y+h, x:x+w] # 將當前幀含人臉部分保存為圖片,注意這里存的還是彩色圖片,前面檢測時灰度化是為了降低計算量;這里訪問的是從y位開始到y+h-1位 cv2.imwrite(image_name, image)

最后給出捕獲筆記本攝像頭探測人臉並存儲人臉圖片程序的完整代碼,這也是這個人臉識別項目中的第一部分功能:

import cv2 def getTrainingData(window_name, camera_id, path_name, max_num): # path_name是圖片存儲目錄,max_num是需要捕捉的圖片數量 cv2.namedWindow(window_name) # 創建窗口 cap = cv2.VideoCapture(camera_id) # 打開攝像頭 classifier = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml') # 加載分類器 color = (0,255,0) # 人臉矩形框的顏色 num = 0 # 記錄存儲的圖片數量 while cap.isOpened(): ok, frame = cap.read() if not ok: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 灰度化 faceRects=classifier.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=3,minSize=(32,32)) if len(faceRects) > 0: for faceRect in faceRects: x,y,w,h = faceRect # 捕捉到的圖片的名字,這里用到了格式化字符串的輸出 image_name = '%s%d.jpg' % (path_name, num) # 注意這里圖片名一定要加上擴展名,否則后面imwrite的時候會報錯:could not find a writer for the specified extension in function cv::imwrite_ 參考:https://stackoverflow.com/questions/9868963/cvimwrite-could-not-find-a-writer-for-the-specified-extension image = frame[y:y+h, x:x+w] # 將當前幀含人臉部分保存為圖片,注意這里存的還是彩色圖片,前面檢測時灰度化是為了降低計算量;這里訪問的是從y位開始到y+h-1位 cv2.imwrite(image_name, image) num += 1 # 超過指定最大保存數量則退出循環 if num > max_num: break cv2.rectangle(frame, (x,y), (x+w,y+h), color, 2) # 畫出矩形框 font = cv2.FONT_HERSHEY_SIMPLEX # 獲取內置字體 cv2.putText(frame, ('%d'%num), (x+30, y+30), font, 1, (255,0,255), 4) # 調用函數,對人臉坐標位置,添加一個(x+30,y+30)的矩形框用於顯示當前捕捉到了多少人臉圖片 if num > max_num: break cv2.imshow(window_name, frame) c = cv2.waitKey(10) if c & 0xFF == ord('q'): break cap.release()#釋放攝像頭並銷毀所有窗口 cv2.destroyAllWindows() print('Finished.') #主函數 if __name__ =='__main__': print ('catching your face and writting into disk...') getTrainingData('getTrainData',0,'training_data_me/',100) # 注意這里的training_data_xx 文件夾就在程序工作目錄下

運行這段程序后你要做的就是坐在電腦前變換姿勢表情和光線等等讓攝像頭采集你的人臉,這里如果你有條件的話可以多叫幾個小伙伴來幫你采集他們的臉,然后放在另一個文件夾,比如training_data_others下,后續我們訓練卷積神經網絡的時候就是要告訴它什么樣的圖片是你的臉,什么樣的圖片是別人的臉。

總結 廈門叉車公司哪家好,多少錢

這篇手記以OpenCV圖片的基本操作為基礎講解了OpenCV中視頻的基本操作並實現了探測人臉的基本功能,后續的幾篇手記打算繼續講講如何在搜集的人臉數據的基礎上如何准備數據集,加載數據集,數據集的划分,如何用Keras和Tensorflow構造卷積神經網絡以及訓練神經網絡等。


參考資料

  1. OpenCV Python Tutorial —— Getting Started with Videos
  2. 知乎 —— if name == 'main' 如何正確理解?
  3. OpenCV Python Tutorial —— Face Detection using Haar Cascades
  4. opencv之人臉檢測之cv2.CascadeClassifier

本作品采用知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議進行許可。要查看該許可協議,可訪問 http://creativecommons.org/licenses/by-nc-sa/4.0/ 或者寫信到 Creative Commons, PO Box 1866, Mountain View, CA 94042, USA。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM