1. 程式人生 > >CV之OpenCV:OpenCV庫涉及概念、常見函式、常用案例總結

CV之OpenCV:OpenCV庫涉及概念、常見函式、常用案例總結

CV入門

1、計算機儲存一張圖片需要儲存三個RGB矩陣(一般是64*64畫素矩陣)

一、OpenCV使用過程

cv2呼叫自帶訓練好的xml模型兩步人臉檢測思路:可檢測人臉、人眼 、身體部位。
1、首先就是訓練好級聯分類器cv2.CascadeClassifier(model_path),即通過不同的分類器model_path型別(haar或lbp)進行初始化。
2、然後就是cv2.detectMultiScale()進行檢測,檢測出圖片中所有的人臉,並返回人臉的座標、大小(用矩形表示)的vector

catPath = "haarcascade_frontalcatface.xml"    
faceCascade = cv2.CascadeClassifier(catPath)  
faces = faceCascade.detectMultiScale()

3、級聯分類器整個過程主要包括:樣本準備,資料生成,訓練,交叉驗證,檢測

(1) 樣本標註的工具:
applications->opencv_annotation   opencv_annotation.exe  注意:在標註的過程中,需要注意標註程式要能正確讀取到相應的影象。每次畫完標註框,需要按C鍵才能儲存該標註框。  
(2) 測試或訓練樣本的生成工具:
applications->opencv_createsamples    opencv_createsamples.exe  說明:將樣本以向量的方式寫到vec檔案中,給定正樣本進行變形的方法沒有成功,目前只試過第三種方法:給定正樣本影象集合檔案(即第一步獲得的標註檔案),將樣本檔案的每個樣本逐個寫到vec檔案中,超過樣本影象數後會輸出parse error,但不是報錯,屬正常結束。  
(3) 級聯分類器訓練工具: 
applications->opencv_traincascade中的cascadeclassifier中的CvCascadeClassifier類,主要用於train,但具有私有方法predict; opencv_traincascade.exe (之前的諸如:貝葉斯,k-nn,SVM,決策樹,隨機樹等等,在old_ml中。但在boost中的CvCascadeBoost類,也有相關的公有的訓練和預測方法,與級聯分類器的區別需要進一步確認)  說明:bgName引數為負樣本描述檔案(.dat),檔案中包含一系列的影象檔名,這些影象將被隨機選作物體的背景,具體可以是每一行為一個包含絕對路徑的背景影象檔名。  
(4) 級聯分類器檢測:
可以利用modules->opencv_objdetect中cascadedetect中的CascadeClassifierImpl類;也可以利用opencv2/objdetect.hpp定義的CascadeClassifier類,具體在modules->opencv_objdetect->Src中cascadedetect.cpp中實現(基於BaseCascadeClassifier類實現);也可以利用訓練工具中的predict方法進行預測。 
(5) Opencv提供了測試方法:
tests accuracy->opencv_test_objdetect的測試方法;tests performance->opencv_perf_objdetect的測試方法。

Cascade Classification
Haar Feature-based Cascade Classifier for Object Detection

二、OpenCV的相關概念

1、OpenCV的級聯分類器:分為兩部分,訓練與檢測。訓練那塊程式碼在apps目錄下,有舊分類器haartraining和新分類器traincascade各自的程式碼。目前沒去看,訓練用OpenCV給的程式目前就足夠了。
2、XML:可理解為一種小型的資料庫。是eXtensible Markup Language, 翻譯成中文就是“可擴充套件標識語言“。首先XML是一種元標記語言,所謂“元標記”就是開發者可以根據自己的需要定義自己的標記,比如開發者可以定義如下標記<book> <name>,任何滿足xml命名規則的名稱都可以標記,這就為不同的應用程式打開了的大門。 第二xml是一種語義/結構化語言。它描述了文件的結構和語義。XML可利用於資料交換 主要是因為XML表示的資訊獨立於平臺的,這裡的平臺即可以理解為不同的應用程式也可以理解為不同的作業系統;它描述了一種規範,利用它Microsoft的word文件可以和Adobe 的Acrobat交換資訊,可以和資料庫交換資訊。  
3、CAM(Class Activation Mapping)產生的CAM圖與之類似,當我們需要模型解釋其分類的原因時,它以熱力圖(Saliency Map)的形式展示它的決策依據,如同在黑夜中告訴我們哪有發熱的物體。
    Grad-CAM的基本思路和CAM是一致的,也是通過得到每對特徵圖對應的權重,最後求一個加權和。但是它與CAM的主要區別在於求權重$w_kc$的過程。CAM通過替換全連線層為GAP層,重新訓練得到權重,而Grad-CAM另闢蹊徑,用梯度的全域性平均來計算權重。事實上,經過嚴格的數學推導,Grad-CAM與CAM計算出來的權重是等價的。為了和CAM的權重做區分,定義Grad-CAM中第$k$個特徵圖對類別$c$的權重為$\alpha_kc$。
參考文獻:

憑什麼相信你,我的CNN模型?(篇一:CAM和Grad-CAM)

三、OpenCV一些常用函式

HOG detectMultiScale ()  
 #可以檢測出圖片中所有的人臉,並將人臉用vector儲存各個人臉的座標、大小(用矩形表示)。
winStride(可選)  HoG檢測視窗移動時的步長(水平及豎直)。  winStride和scale都是比較重要的引數,需要合理的設定。一個合適引數能夠大大提升檢測精確度,同時也不會使檢測時間太長。
padding(可選)  在原圖外圍新增畫素,作者在原文中提到,適當的pad可以提高檢測的準確率(可能pad後能檢測到邊角的目標?)  常見的pad size 有(8, 8), (16, 16), (24, 24), (32, 32).

CV_WRAP virtual void detectMultiScale( const Mat& image,
                      CV_OUT vector<Rect>& objects,
                      double scaleFactor=1.1,
                      int minNeighbors=3, int flags=0,
                      Size minSize=Size(),
                      Size maxSize=Size() );
minSize=Size()、maxSize=Size(): 決定了檢測到的最小和最大的人臉大小,如果圖片中人臉距離相機較遠,把minSize引數設定為=Size(20,20) 
scaleFactor:引數決定由多少不同大小的人臉要搜尋,通常為1.1 
minNeighbors: 決定著人臉檢測器如何確定人臉已經被找到,預設值是3,如果改為4的話,將會使檢測的正確率增加,但是漏檢率也可能增加,可以理解為引數越大,判斷的條件越苛刻。 
flags:是否要檢測所有人臉。

detectMultiScale(const Mat& image, vector& objects, double scaleFactor=1.1,int minNeighbors, int flag,cvSize)
#cv2中人臉、貓臉檢測使用的是 detectMultiScale函式。它可以檢測出圖片中所有的人臉、眼睛、嘴等(依據所呼叫的分類器);函式由分類器物件呼叫。 
(image為輸入的灰度影象;     objects為得到被檢測物體的矩形框向量組;scaleFactor為每一個影象尺度中的尺度引數,預設值為1.1。              scale_factor引數可以決定兩個不同大小的視窗掃描之間有多大的跳躍,這個引數設定的大,則意味著計算會變快,但如果視窗錯過了某個大小的人臉,則可能丟失物體。  如1.3;     minNeighbors引數為每一個級聯矩形應該保留的鄰近個數,預設為3。minNeighbors控制著誤檢測,預設值為3表明至少有3次重疊檢測,我們才認為人臉確實存;     flags對於新的分類器沒有用(但目前的haar分類器都是舊版的,CV_HAAR_DO_CANNY_PRUNING,這個值告訴分類器跳過平滑(無邊緣區域)。利用Canny邊緣檢測器來排除一些邊緣很少或者很多的影象區域;CV_HAAR_SCALE_IMAGE,這個值告訴分類器不要縮放分類器。而是縮放影象(處理好記憶體和快取的使用問題,這可以提高效能。)就是按比例正常檢測;CV_HAAR_FIND_BIGGEST_OBJECTS,告訴分類器只返回最大的目標(這樣返回的物體個數只可能是0或1)只檢測最大的物,CV_HAAR_DO_ROUGH_SEARCH,他只可與CV_HAAR_FIND_BIGGEST_OBJECTS一起使用,這個標誌告訴分類器在任何視窗,只要第一個候選者被發現則結束尋找(當然需要足夠的相鄰的區域來說明真正找到了,只做初略檢測 ;     cvSize()指示尋找人臉的最小區域。設定這個引數過大,會以丟失小物體為代價減少計算量。

cv2.rectangle()
下面我來跟大家講一下IMG取某區域內影象的座標以及cv2.rectangle的定位座標。參考部落格https://www.cnblogs.com/fightccc/p/8616068.html
1)cv2.rectangle,我們從上面的註釋中知道,獲取的是左上角和右下角的頂點座標,用畫圖的方式表達如下:


2)IMG區域取值範圍則和1)不同,IMG[左上頂點y:左下頂點y,左上頂點x:右上頂點x],用圖來表示S◇acef區域如下:所以,之後擷取後記得以最原始的IMG座標為頂點,再來表示要擷取的區域,不然就會報錯。

cv2.estimateRigidTransform()  #計算兩個2D點集之間的最優仿射變換。
https://docs.opencv.org/2.4/modules/video/doc/motion_analysis_and_object_tracking.html#cv2.estimateRigidTransform
cv2.destroyAllWindows()

#刪除建立的全部視窗;可以輕易刪除任何我們建立的視窗。如果 你想刪除特定的視窗可以使用,在括號內輸入你想刪 除的視窗名。
cv2.destroyWindows():刪除指定的視窗。
cv2.namedWindow('視窗標題',預設引數)  
建立命名視窗,預設引數:cv2.WINDOW_AUTOSIZE+cv2.WINDOW_KEEPRATIO+cv2.WINDOW_GUI_EXPANDED)  
引數: 
cv2.WINDOW_NORMAL     視窗大小可改變 
cv2.WINDOW_AUTOSIZE   視窗大小不可改變 
cv2.WINDOW_FREERATIO  自適應比例 
cv2.WINDOW_KEEPRATIO  保持比例餓 
cv2.WINDOW_GUI_NORMAL 
cv2.WINDOW_GUI_EXPANDED 
用法:cv2.imshow('視窗標題', image),如果前面沒有cv2.namedWindow,就自動先執行一個cv2.namedWindow。

cv2.imshow()
顯示影象。視窗會自動調整為影象大小。第一個引數是視窗的名字,其次才是我們的影象。cv2.imshow():建立一個視窗顯示圖片,共兩個引數,第一個引數表示視窗名字,可以建立多個視窗中,但是每個視窗不能重名;第二個引數是讀入的圖片。

cv2.imread()  
讀入圖片,使用函式cv2.imread() 讀入影象。這幅影象應該在此程式的工作路徑,或者給函式提供完整路徑,第二個引數是要告訴函式應該如何讀取這幅圖片。共兩個引數,第一個引數為要讀入的圖片檔名,第二個引數為如何讀取圖片,包括cv2.IMREAD_COLOR:讀入一副彩色圖片;
cv2.IMREAD_COLOR:讀入一副彩色影象。影象的透明度會被忽略,  這是預設引數。  
cv2.IMREAD_GRAYSCALE:以灰度模式讀入影象
cv2.IMREAD_UNCHANGED:讀入一幅圖片,幷包括其alpha通道。

cv2.imwrite()  
#儲存圖片,共兩個引數,第一個為儲存檔名,第二個為讀入圖片。

cv2.resize(image, image2,dsize)
影象縮放方法;即(輸入原始影象,輸出新影象,影象的大小)
cv2.INTER_LINEAR    
|#影象尺寸變換的方法,預設的雙線性插值
cv2.putText(img,'text',(50,150),cv2.FONT_HERSHEY_COMPLEX,6,(0,0,255),25)  
#(照片,新增的文字,左上角座標,字型,字型大小,顏色,字型粗細)
cv2.boundingRect(img) 
#img是一個二值圖,也就是它的引數; 返回四個值,分別是x,y,w,h;  x,y是矩陣左上點的座標,w,h是矩陣的寬和高
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
#畫出矩行 ;
(img是原圖,(x,y)是矩陣的左上點座標,(x+w,y+h)是矩陣的右下點座標,(0,255,0)是畫線對應的rgb顏色,2是所畫的線的寬度)

cv2.cvtColor(i, cv2.COLOR_BGR2GRAY)
顏色空間轉換:生活中大多數看到的彩色圖片都是RGB型別,但是在進行影象處理時,需要用到GRAY灰度圖、二值圖、HSV、HSI等顏色制式,opencv提供了cvtColor()函式來實現這些功能

cv2.VideoCapture(0) 
#函式定義攝像頭物件,其引數0表示第一個攝像頭,一般就是筆記本的內建攝像頭。

cameraCapture.read()  
#從攝像裝置中讀入資料
cameraCapture.release()  
#函式釋放Camera,以便其他應用程式呼叫,結束後一定要釋放Camera

cv2.waitKey() 
鍵盤繫結函式。共一個引數,表示等待毫秒數,將等待特定的幾毫秒,看鍵盤是否有輸入,返回值為ASCII值。如果其引數為0,則表示無限期的等待鍵盤輸入。如果按下任意鍵,這個函式會返回按鍵的ASCII 碼值,程式將會繼續執行。如果沒有鍵盤輸入,返回值為-1。它也可以被用來檢測特定鍵是否被按下,例如按鍵a 是否 被按下。

cv2.waitKey(1) == -1:  
#不斷重新整理影象,頻率delay=1單位ms;如果delay>0,那麼超過指定時間則返回-1;如果delay=0,將沒有返回值;鍵盤繫結函式:看鍵盤是否有輸入,返回值為ASCII值。如果引數為0,則表示無限期的等待鍵盤輸入。
cv2.warpAffine()  #仿射變換函式,接受三個引數(需要變換的原始影象、移動矩陣M 、變換的影象大小),這個大小如果不和原始影象大小相同,那麼函式會自動通過插值來調整畫素間的關係。

OpenCV一些常用案例

#利用CV2開啟一張圖片
import cv2 
img = cv2.imread("F:/File_Python/Resources/biaoqingbao021.jpg") 
cv2.namedWindow("Image") 
cv2.imshow("Image", img) 
cv2.waitKey (0)

2、利用CV2讀取本地攝像頭

#1、opencv讀取攝像頭
import cv2
cap = cv2.VideoCapture(0)       #使用opencv自帶的Videocapture()函式定義攝像頭物件,0表示第一個攝像頭,一般是筆記本內攝像頭
while(1):                       #一幀一幀獲取影象
    ret,frame = cap.read()
    cv2.imshow("capture",frame) #一幀一幀顯示影象
    if cv2.waitKey(1)&0xFF == ord('q'):
        break
cap.release()
cap.destroyAllWindows()
#2、opencv讀取攝像頭畫面變為灰色
import cv2
cap = cv2.VideoCapture(0)                         # 建立一個VideoCapture物件
while(True):
    ret, frame = cap.read()                       # 一幀一幀讀取視訊
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 對每一幀做處理,設定為灰度圖
    cv2.imshow('frame',gray)                      # 顯示結果
    if cv2.waitKey(1) & 0xFF == ord('q'):         # 按q停止
        break
cap.release()                                     # 釋放cap,銷燬視窗
cv2.destroyAllWindows()

3、利於CV2讀取本地視訊(無聲音),並原畫質顯示、灰色顯示

#T1、opencv讀取本地視訊
import cv2
import numpy as np

cap = cv2.VideoCapture("F:\File_Python\Python_example\YOLOv3_use_TF\RunMan2.mp4")
while(1):
    # get a frame
    ret, frame = cap.read()
    # show a frame
    cv2.imshow("capture", frame)
    if cv2.waitKey(100) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows() 

#T2、opencv讀取本地視訊輸出灰色畫質
import numpy as np
import cv2
   
cap = cv2.VideoCapture('F:\File_Python\Python_example\YOLOv3_use_TF\RunMan2.mp4')
while(cap.isOpened()):
    ret, frame = cap.read()
   
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):  # 適當調整等待時間
        break
cap.release()
cv2.destroyAllWindows()

 4、利用CV2讀取本地視訊並調整顯示視窗大小為640*380

#opencv讀取本地視訊並調整顯示視窗大小為640*380
import cv2
import numpy as np

cap = cv2.VideoCapture("F:\File_Python\Python_example\YOLOv3_use_TF\RunMan2.mp4")
while(1):
    # get a frame
    ret, frame = cap.read()
    # show a frame
    cv2.namedWindow("capture",0);
    cv2.resizeWindow("capture", 640, 380);
    cv2.imshow("capture", frame)
    if cv2.waitKey(100) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows() 

5、利用Cv2調取攝像頭並錄製視訊(視窗為640*380),然後儲存到指定資料夾

#opencv調取攝像頭並錄製(視窗為640*380)儲存到指定資料夾
import numpy as np
import cv2
  
cap = cv2.VideoCapture(0)  
fourcc = cv2.VideoWriter_fourcc(*'XVID')  # 定義解碼器並建立VideoWrite物件,linux: XVID、X264; windows:DIVX
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480)) #20.0指定一分鐘的幀數
  
while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        frame = cv2.flip(frame,0)
  
        # 寫入幀
        out.write(frame)
  
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break
cap.release()  # 釋放記憶體
out.release()
cv2.destroyAllWindows()

1、OpenCV實現檢測幾何形狀並進行識別、輸出周長、面積、顏色、形狀型別

輪廓提取:在OpenCV中使用輪廓發現相關函式時候要求輸入影象是二值影象,這樣便於輪廓提取、邊緣提取等操作。輪廓發現的函式與引數解釋如下:  
findContours ( image ,  mode ,  method ,  contours = None ,  hierarchy = None ,  offset = None ) 
(image 輸入/輸出的二值影象;mode  返回輪廓的結構、可以是 List 、 Tree 、 External ;method  輪廓點的編碼方式,基本是基於鏈式編碼 ;contours  返回的輪廓集合 ;hieracrchy  返回的輪廓層次關係 ;offset  點是否有位移)
多邊形逼近:是通過對輪廓外形無限逼近,刪除非關鍵點、得到輪廓的關鍵點,不斷逼近輪廓真實形狀的方法,OpenCV中多邊形逼近的函式與引數解釋如下:  
approxPolyDP ( curve ,  epsilon ,  closed ,  approxCurve = None ) 
(curve  表示輸入的輪廓點集合 ;epsilon  表示逼近曲率,越小表示相似逼近越厲害;close 是否閉合)
幾何距計算:影象幾何距是影象的幾何特徵,高階幾何距中心化之後具有特徵不變性,可以產生Hu距輸出,用於形狀匹配等操作,這裡我們通過計算一階幾何距得到指定輪廓的中心位置,計算幾何距的函式與引數解釋如下:  
moments ( array ,  binaryImage = None )
(array 表示指定輸入輪廓 ;binaryImage 預設為 None)

HALCON機器視覺軟體

      HALCON是德國MVtec公司開發的一套完善的標準的機器視覺演算法包,擁有應用廣泛的機器視覺整合開發環境。它節約了產品成本,縮短了軟體開發週期——HALCON靈活的架構便於機器視覺,醫學影象和影象分析應用的快速開發。在歐洲以及日本的工業界已經是公認具有最佳效能的Machine Vision軟體。
      HALCON源自學術界,它有別於市面一般的商用軟體包。事實上,這是一套image processing library,由一千多個各自獨立的函式,以及底層的資料管理核心構成。其中包含了各類濾波,色彩以及幾何,數學轉換,形態學計算分析,校正,分類辨識,形狀搜尋等等基本的幾何以及影像計算功能,由於這些功能大多並非針對特定工作設計的,因此只要用得到影象處理的地方,就可以用HALCON強大的計算 分析能力來完成工作。應用範圍幾乎沒有限制,涵蓋醫學,遙感探測,監控,到工業上的各類自動化檢測。
      HALCON支援Windows,Linux和Mac OS X操作環境,它保證了投資的有效性。整個函式庫可以用C,C++,C#,Visual basic和Delphi等多種普通程式語言訪問。HALCON為大量的影象獲取裝置提供介面,保證了硬體的獨立性。它為百餘種工業相機和影象採集卡提供介面,包括GenlCam,GigE和IIDC 1394。