OpenCV 是計算機視覺中經典的專用庫,其支持多語言、跨平台,功能強大。OpenCV-Python為OpenCV提供了Python接口,使得使用者在Python中能夠調用C/C++,在保證易讀性和運行效率的前提下,實現所需的功能。
一、安裝
安裝方法有多種,老猿機器上無C++環境,因此直接使用pip安裝,OpenCV-Python模塊名為opencv-python(在windows下大小寫不敏感,其他操作系統沒驗證),具體安裝命令如下:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
二、加載OpenCV
導入OpenCV 模塊指令很簡單:
import cv2 as cv
大多數OpenCV 的函數都在cv2模塊內,cv2並不是版本2.X的意思,而是因為這個版本是在原cv版本的基礎上採用了面向對象編程的方式重新實現,提供了更好的API接口。
三、讀取圖像文件
3.1、語法:imread(filename,mode)
3.2、參數說明
- filename:圖像文件名,不同操作系統支撐的文件類型不一樣,但都支持bmp圖像文件,另外可能還包括jpeg、png、tiff等格式文件
- mode:文件讀入模式,常用有三種取值
- cv.IMREAD_COLOR: 對應值為1,加載彩色圖像。任何圖像的透明度都會被忽視。它是默認標誌。
- cv.IMREAD_GRAYSCALE:對應值為0,以灰度模式加載圖
- cv.IMREAD_UNCHANGED:對應值為-1,加載圖像,包括alpha通道;
注意:除了這三個常用取值,還可以有多個取值,相關取值及含義如下:

3.3 返回值說明
imread返回一個BGR格式的圖像對象,其類型為一個numpy數組。
3.4、案例
img = cv2.imread(r’F:screenpicredflower.jpg’)
注意:
- 圖片文件名不能是中文名,否則識別會報錯或不能讀入;
- imread會去除圖像的alpha通道信息
四、顯示圖像
4.1、調用語法:imshow(title,img)
4.2、參數說明:
- title:圖像顯示窗窗口標題和名字
- img:opencv圖像對象
imread讀入的函數使用imshow即可顯示,顯示可以給顯示窗設定標題,這個標題也是顯示窗口的名字,標題不同的imshow會顯示不同窗口。標題為一個英文字符串,相同標題的窗口就是同一個窗口。對於窗口,OpenCV提供鼠標及鍵盤事件處理機制。
imshow的窗口可以通過destroyWindow和destroyAllWindows進行關閉,前者要帶窗口的標題,後者是關閉所有由當前程序創建的窗口。
4.3、案例
img = cv2.imread(r’F:screenpicredflower.jpg’)
cv2.imshow(‘img’,img)
五、VideoCapture讀取攝像頭、圖像文件、或視頻流
VideoCapture既支持從視頻文件(.avi , .mpg格式)讀取,也支持直接從攝像機(比如電腦自帶攝像頭)中讀取。要想獲取視頻需要先創建一個VideoCapture對象,VideoCapture對象的創建方式有以下三種:
調用語法:
VideoCapture(int deviceIndex,int apiPreference = CAP_ANY ):打開攝像頭捕獲視頻。deviceIndex為攝像頭序列號,打開缺省攝像頭傳0,apiPreference 為VideoCapture API後端標識符,老猿沒有仔細研究,用缺省值即可
VideoCapture(filename,int apiPreference = CAP_ANY):打開filename指定的文件
更多VideoCapture的內容請參考《opencv學習—VideoCapture 類基礎知識》。
下面的代碼打開缺省攝像頭捕獲視頻,並將捕獲內容顯示為窗口視頻,並寫入視頻文件中保存,按q終止退出:
import cv2
def captureVideoFromCamera():
cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
WIDTH = 1920
HEIGHT = 1920
FILENAME = r’f:videomyvideo.avi’
FPS = 24
cap.set(cv2.CAP_PROP_FPS, 24)
# 建議使用XVID編碼,圖像質量和文件大小比較都兼顧的方案
fourcc = cv2.VideoWriter_fourcc(*’XVID’)
out = cv2.VideoWriter(FILENAME, fourcc=fourcc, fps=FPS,frameSize=(WIDTH,HEIGHT))
if not cap.isOpened():
print(“Cannot open camera”)
exit()
while True:
# 逐幀捕獲
ret, frame = cap.read()
# 如果正確讀取幀,ret為True
if not ret:
print(“Can’t receive frame (stream end?). Exiting …”)
break
frame = cv2.flip(frame, 1) # 水平翻轉
ret = out.write(frame)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 顯示結果幀e
cv2.imshow(‘frame’, frame)
if cv2.waitKey(1) == ord(‘q’): break
# 完成所有操作後,釋放捕獲器
out.release()
cap.release()
cv2.destroyAllWindows()
captureVideoFromCamera()
六、OpenCV-Python的鼠標事件捕獲
OpenCV提供了設置鼠標事件回調函數來提供鼠標事件處理的機制,設置回調函數的方法如下:
cv2.setMouseCallback(winName, OnMouseFunction, param)
其中winName為要設置鼠標回調處理的窗口名,OnMouseFunction為回調函數,用於處理鼠標響應,param為設置回調函數時傳入的應用相關特定參數,可以不設置,但需要在回調函數訪問設置回調函數對象屬性時非常有用。
示例:
cv2.namedWindow(‘image’)
cv2.setMouseCallback(‘image’, draw_circle)
七、waitKey鍵盤事件處理
openCV提供了快速的鍵盤處理支持函數waitKey,調用語法:
retval = cv.waitKey( [, delay] )
其中:
- delay:等待鍵盤響應的時間,單位是毫秒,如果為0,則是一直等待到有鍵盤輸入,否則就是等待對應時間還沒有輸入就超時返回
- retval:如果是超時返回-1,否則返回對應鍵盤按鍵的ASCII碼,但注意對於部分功能鍵如F1–F10返回值為0,其他功能鍵老猿未一一測試,可以確認ESC鍵值可以正常返回(返回值27),Ctrl+c返回3
八、OpenCV的矩形繪製
OpenCV提供了在圖像中繪製幾何圖形的方法,繪製的圖像包括矩形、橢圓、扇形、弧等。本文主要介紹矩形的繪製,具體調用語法如下:
rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
其中參數:
- img:要顯示的圖像,為numpy數組,格式為BGR格式
- pt1:左上角點的坐標
- pt2:右下角點的坐標
- color:繪製的顏色,為BGR格式的三元組,如(255,0,0)表示藍色
- thickness:邊框的厚度,如果為負數,則該矩形為實心矩形,否則為空心矩形
- linetype:線型,包括4連通、8連通以及抗鋸齒線型,使用缺省值即可
- shift:坐標值的精度,為2就表示精確到小數點後2位
另外該方法還有個變種調用方式:
rectangle(img, rec, color[, thickness[, lineType[, shift]]]),其中的rec為上面pt1和pt2構建的矩形。
除了矩形,OpenCV還支持繪製點、直線、圓、橢圓、文本(不支持中文)等,具體可參考《使用Python OpenCV處理圖像之詳解直線、圓、矩形及文字的繪製》,老猿就不展開介紹了。
下面的示例代碼是打開視頻播放,鼠標點擊後暫停播放並在點擊位置畫圓,再次點擊恢復播放:
import cv2
def mouseEvent( event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
param[0] = not param[0]
param[1] = (x,y)
def playVideoFile():
cap = cv2.VideoCapture(r’f:videozbl1.mp4′)
fps = 1
eventInf = [False,None]
frame = None
if not cap.isOpened():
print(“Cannot open camera”)
exit()
cv2.namedWindow(‘image’)
cv2.setMouseCallback(‘image’, mouseEvent,eventInf)
while True:
# 逐幀捕獲
pause,mousePos = eventInf
if not pause:
ret, frame = cap.read()
if not ret:
if frame is None :
print(“The video has end.”)
else:
print(“Read video error!”)
break
else:
if mousePos:
cv2.circle(frame, mousePos,60, (255,0,0),2)
cv2.imshow(‘image’, frame)
ch = cv2.waitKey(int(1000/fps))
if ch == ord(‘q’): break
cap.release()
cv2.destroyAllWindows()
playVideoFile()
九、OpenCV的顏色空間轉換方法
cv2.cvtColor是openCV提供的顏色空間轉換函數,調用語法如下:
cvtColor(src, code, dstCn=None)
其中:
- src:要轉換的圖像
- code:轉換代碼,表示從何種類型的圖像轉換為何種類型,如下面需要使用的cv2.COLOR_BGR2GRAY就是將BGR格式彩色圖像轉換成灰度圖片,具體轉換代碼請參考官網文檔
- dstCn:目標圖像的通道數,如果為0表示根據源圖像通道數以及轉換代碼自動確認
更多內容請參考《學習opencv之cvtColor》,示例請參考下面圖像閾值處理部分的案例。
十、圖像閾值處理
openCV圖像的閾值處理又稱為二值化,之所以稱為二值化,是它可以將一幅圖轉換為感興趣的部分(前景)和不感興趣的部分(背景)。轉換時,通常將某個值(即閾值)當作區分處理的標準,通常將超過閾值的像素作為前景。
閾值處理有2種方式,一種是固定閾值方式,又包括多種處理模式,另一種是非固定閾值,由程序根據算法以及給出的最大閾值計算圖像合適的閾值,再用這個閾值進行二值化處理,非固定閾值處理時需要在固定閾值處理基礎上疊加組合標記。
調用語法:
retval, dst = cv2.threshold (src, thresh, maxval, type)
其中:
- src:源圖像,8位或32位圖像的numpy數組
- thresh:閾值,0-255之間的數字,在進行處理時以閾值為邊界來設不同的輸出
- maxval:最大閾值,當使用固定閾值方法時為指定閾值,當疊加標記時為允許最大的閾值,算法必須在小於該值範圍內計算合適的閾值
- type:處理方式,具體取值及含義如下:
- dst:閾值化處理後的結果圖像numpy數組,其大小和通道數與源圖像相同
- retval:疊加cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE標記後返回真正使用的閾值
案例:
ret, mask = cv2.threshold(img, 35, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
補充說明:
- 閾值判斷時,是以小於等於閾值和大於閾值作為分界條件
- 如果是32位彩色圖像,則是以RGB每個通道的值單獨與閾值進行比較,按每個通道進行閾值處理,返回的是一個閾值處理後的RGB各自的值。請參考《OpenCV閾值處理函數threshold處理32位彩色圖像的案例》。
下面的代碼生成一個圖像的掩碼圖像:
def createImgMask(img):
# 創建img的掩碼
if img is None:return None
if len(img.shape)>=3:
img2gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:img2gray = img
ret, mask = cv2.threshold(img2gray, 35, 255, cv2.THRESH_BINARY)
return mask
十一、adaptiveThreshold自適應閾值化圖像處理
上面介紹的threshold 函數的圖像閾值處理對於某些光照不均的圖像,這種全局閾值分割的方法會顯得蒼白無力。圖像閾值化操作中,我們更關心的是從二值化圖像中分離目標區域和背景區域,僅僅通過固定閾值很難達到理想的分割效果。在圖片中的灰度是不均勻的,所以通常情況下圖片中不同區域的閾值是不一樣的。這樣就需要一種方法根據圖像不同區域亮度或灰度分布,計算其局部閾值來進行閾值處理。這種方法就是自適應閾值化圖像處理,實際上這可以稱為局部閾值法,在OpenCV中的adaptiveThreshold就是這種方法。
調用語法:
adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
說明:
- src:源圖像,必須是8位的灰度圖
- dst:處理後的目標圖像,大小和類型與源圖像相同
- maxValue:用於指定滿足條件的像素設定的灰度值
- adaptiveMethod:使用的自適應閾值算法,有2種類型ADAPTIVE_THRESH_MEAN_C算法(局部鄰域塊均值)或ADAPTIVE_THRESH_GAUSSIAN_C(局部鄰域塊高斯加權和),ADAPTIVE_THRESH_MEAN_C的計算方法是計算出鄰域的平均值再減去第六個參數C的值,ADAPTIVE_THRESH_GAUSSIAN_C的計算方法是計算出鄰域的高斯均勻值再減去第六個參數C的值。處理邊界時使用BORDER_REPLICATE | BORDER_ISOLATED模式
- thresholdType:閾值類型,只能是THRESH_BINARY或THRESH_BINARY_INV二者之一,具體參考上面“圖像閾值處理”的表格
- blockSize:表示鄰域塊大小,用來計算區域閾值,一般選擇3、5、7……
- C:表示常數,它是一個從均勻或加權均值提取的常數,通常為正數,但也可以是負數或零
- 返回值:處理後的圖像
補充說明:
- 亮度較高的圖像區域的二值化閾值通常會較高,而亮度較低的圖像區域的二值化閾值則會相適應地變小
- 在灰度圖像中,灰度值變化明顯的區域往往是物體的輪廓,所以將圖像分成一小塊一小塊的去計算閾值往往會得出圖像的輪廓。因此函數adaptiveThreshold除了將灰度圖像二值化,也可以進行邊緣提取
- 之所以能進行邊緣提取,是因為當block很小時,如block_size=3 or 5 or 7時,“自適應”的程度很高,即容易出現block裡面的像素值都差不多,這樣便無法二值化,而只能在邊緣等梯度大的地方實現二值化,結果顯得它是邊緣提取函數
- 當把blockSize設為比較大的值時,如blockSize=21 or 31 or 41時,adaptiveThreshold便是二值化函數
- blockSize必須為大於1的奇數(原理老猿還沒弄清楚) ,
- 如果使用平均值方法,平均值mean為180,差值delta為10,maxValue設為255。那麼灰度小於170的像素為0,大於等於170的像素為255,如果是反向二值化,灰度小於170的像素為255,大於等於170的像素為0
案例:
import cv2
img = cv2.imread(r’F:screenpic1.jpg’,cv2.IMREAD_GRAYSCALE)
newImg = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 3, 5)
cv2.imshow(‘img’,img)
cv2.imshow(‘newImg’,newImg)
cv2.waitKey(60000)
運行效果:
源圖:

下面是分別設置不同塊大小的結果圖,左圖塊大小為31,右圖為3:

可以看到blockSize小時,輪廓識別效果明顯,而大時,就是一個二值化圖像。
十二、OpenCV的圖像修復方法
OpenCV中的cv2.inpaint()函數使用插值方法修復圖像,調用語法如下:
dst = cv2.inpaint(src,mask, inpaintRadius,flags)
參數含義如下:
- src:輸入8位1通道或3通道圖像
- inpaintMask:修復掩碼,8位1通道圖像。非零像素表示需要修復的區域
- dst:輸出與src具有相同大小和類型的圖像
- inpaintRadius:算法考慮的每個點的圓形鄰域的半徑
- flags:修復算法標記,其中INPAINT_NS表示基於Navier-Stokes方法,INPAINT_TELEA表示Alexandru Telea方法。具體方法在此不展開介紹
下面的代碼對一個包含亮色Logo的圖片進行去Logo處理:
import cv2
def createImgMask(img):
# 創建img的掩碼
if img is None:return None
if len(img.shape)>=3:
img2gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
img2gray = img
ret, mask = cv2.threshold(img2gray, 35, 255, cv2.THRESH_BINARY)
return mask
def delLogFromImg(img):
imgMask = createImgMask(img)
imgMask = cv2.inpaint(img, imgMask , 3, cv2.INPAINT_TELEA)
return imgMask
img1 = cv2.imread(r’F:templogo.jpg’)
img2 = cv2.imread(r’F:templogo.jpg’,cv2.IMREAD_GRAYSCALE)
newImg1 = delLogFromImg(img1)
newImg2 = delLogFromImg(img2)
cv2.imshow(‘img1’,img1)
cv2.imshow(‘newImg1’,newImg1)
cv2.imshow(‘img2’,img2)
cv2.imshow(‘newImg2’,newImg2)
cv2.waitKey(60000)
執行截圖1:

小結
本文詳細介紹了opencv-python的安裝、加載圖像文件、捕獲攝像頭、顯示圖像、鼠標事件捕獲、鍵盤事件處理、幾何圖像繪製、顏色空間轉換、圖像閾值處理、圖像修復等基礎知識,適合開始學習opencv-python的初學者。
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/275343.html
微信掃一掃
支付寶掃一掃