opencv視頻圖像識別方法「opencv保存視頻格式」

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:文件讀入模式,常用有三種取值
  1. cv.IMREAD_COLOR: 對應值為1,載入彩色圖像。任何圖像的透明度都會被忽視。它是默認標誌。
  2. cv.IMREAD_GRAYSCALE:對應值為0,以灰度模式載入圖
  3. cv.IMREAD_UNCHANGED:對應值為-1,載入圖像,包括alpha通道;

注意:除了這三個常用取值,還可以有多個取值,相關取值及含義如下:

opencv-python圖形圖像處理入門基礎知識

3.3 返回值說明

imread返回一個BGR格式的圖像對象,其類型為一個numpy數組。

3.4、案例

img = cv2.imread(r’F:screenpicredflower.jpg’)

注意:

  1. 圖片文件名不能是中文名,否則識別會報錯或不能讀入;
  2. 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)

補充說明:

  1. 閾值判斷時,是以小於等於閾值和大於閾值作為分界條件
  2. 如果是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:表示常數,它是一個從均勻或加權均值提取的常數,通常為正數,但也可以是負數或零
  • 返回值:處理後的圖像

補充說明:

  1. 亮度較高的圖像區域的二值化閾值通常會較高,而亮度較低的圖像區域的二值化閾值則會相適應地變小
  2. 在灰度圖像中,灰度值變化明顯的區域往往是物體的輪廓,所以將圖像分成一小塊一小塊的去計算閾值往往會得出圖像的輪廓。因此函數adaptiveThreshold除了將灰度圖像二值化,也可以進行邊緣提取
  3. 之所以能進行邊緣提取,是因為當block很小時,如block_size=3 or 5 or 7時,「自適應」的程度很高,即容易出現block裡面的像素值都差不多,這樣便無法二值化,而只能在邊緣等梯度大的地方實現二值化,結果顯得它是邊緣提取函數
  4. 當把blockSize設為比較大的值時,如blockSize=21 or 31 or 41時,adaptiveThreshold便是二值化函數
  5. blockSize必須為大於1的奇數(原理老猿還沒弄清楚) ,
  6. 如果使用平均值方法,平均值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)

運行效果:

源圖:

opencv-python圖形圖像處理入門基礎知識

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

opencv-python圖形圖像處理入門基礎知識

可以看到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的安裝、載入圖像文件、捕獲攝像頭、顯示圖像、滑鼠事件捕獲、鍵盤事件處理、幾何圖像繪製、顏色空間轉換、圖像閾值處理、圖像修復等基礎知識,適合開始學習opencv-python的初學者。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/275343.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-17 14:21
下一篇 2024-12-17 14:21

相關推薦

發表回復

登錄後才能評論