筆記來源於官方文檔
安裝
. 在控制檯運行pip install opencv-python,等待下載安裝完成就可以直接引用了
圖片的讀取顯示和保存
. 使用cv2.imread()來讀取圖片,cv2.imshow()來顯示圖片,cv2.imwrite()來保存圖片,例如:
import cv2
img = cv2.imread('kkxj.jpg')
#cv2.namedWindow('first',cv2.WINDOW_NORMAL)
cv2.imshow('first',img)
key = cv2.waitKey(0)
if key == 27: #ESC
cv2.destroyAllWindows()
elif key == ord('s'):
cv2.imwrite('new.jpg',img)
cv2.destroyAllWindows()
. cv2.imread()有兩個參數,第一個參數是文件名,第二個參數是讀取標識默認位(cv2.IMREAD_COLOR),標識有三種值:
cv2.IMREAD_COLOR :加載彩色圖像,會忽略掉透明度信息;.
cv2.IMREAD_GRAYSCALE :以灰度模式加載圖像;
cv2.IMREAD_UNCHANGED : 加載圖像,包含alpha通道(透明度信息)。
. 值得注意的是,如果文件不存在是不會在讀取這一步拋出異常,img的值將會是none,也會在之後的顯示這一步出錯。
. 代碼中cv2.namedWindow() 函數用在顯示前,用來決定窗口的大小能否通過拖拉鼠標改變,其默認值是cv2.WINDOW_AUTOSIZE 也就是窗口大小和圖片大小相同,且不能拖拉窗口邊緣改變其大小,如果要實現這點,可以在顯示前調用該函數,給第二個參數賦值cv2.WINDOW_NORMAL 。
. cv2.waitKey() 是鍵盤綁定函數,參數的單位是毫秒,表示在指定時間內等待鍵盤事件,如果參數位0表示無限期等待鍵盤事件,也可以用來檢測某個按鍵是否按下,類似之後的判斷是按下的是ESC還是‘s’,如果是按下的是ESC將會直接摧毀所有的窗口,如果按下的是‘s’將調用cv2.imwrite保存img爲新文件。
視頻的讀取顯示和保存
. opencv提供了簡單的接口方便對視頻進行抓取,首先需要創建一個VideoCapture 對象,傳入的參數可以是設備索引(比如筆記本電腦的攝像頭),也可以是某個視頻文件的名字。創建玩對象後就能實現對視頻進行逐幀抓取了:
#cap = cv2.VideoCapture('jackychen.m4s')
cap = cv2.VideoCapture(0)
while(True):
ret,frame = cap.read()
#將圖片轉化爲灰度模式
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
#cv2.resizeWindow('frame',640,360)
cv2.imshow('frame',gray )
#加上&0xff是因爲是64位機,但加不加在測試環境沒看出區別
if cv2.waitKey(1) & 0xff == ord('q'): #對視頻文件來說1毫秒太快了,一般25毫秒比較合適
break;
cap.release() #用完切記要釋放
cv2.destroyAllWindows()
. cap.read()的返回值是bool值,即如果正確讀取了一幀將會返回True,所以上面應該是ret是返回的bool值,frame是抓取的那幀畫面;
VideoCapture 對象有時不能知道是否初始化,可以調用isOpened() 函數檢查,如果沒有可以調用open() 來打開。
. 關於對視頻文件的操作可以通過get(propId) 和 set(propId, value) 函數來做到,propId 值是特殊定義的整型變量,對應值的意義如下:
參數值(對應從0開始) | 描述 |
---|---|
CV_CAP_PROP_POS_MSEC | 視頻文件的當前位置(以毫秒爲單位) |
CV_CAP_PROP_POS_FRAMES | 接下來要解碼/捕獲的幀的基於0的索引 |
CV_CAP_PROP_POS_AVI_RATIO | 視頻文件的相對位置:0-電影開始,1-電影結束 |
CV_CAP_PROP_FRAME_WIDTH | 視頻流中幀的寬度(這個和下面的高度好像只能用在攝像頭抓取的畫面上,要改視頻文件的窗口還是用resize函數) |
CV_CAP_PROP_FRAME_HEIGHT | 視頻流中幀的高度 |
CV_CAP_PROP_FPS | 幀率 |
CV_CAP_PROP_FOURCC | 編解碼器的4個字符的代碼 |
CV_CAP_PROP_FRAME_COUNT | 視頻文件中的幀數 |
CV_CAP_PROP_FORMAT | 由retrieve()返回的Mat對象的格式 |
CV_CAP_PROP_MODE | 特定於後端的值,指示當前的捕獲模式 |
CV_CAP_PROP_BRIGHTNESS | 圖像亮度(僅適用於相機) |
CV_CAP_PROP_CONTRAST | 圖像的對比度(僅適用於相機) |
CV_CAP_PROP_SATURATION | 圖像飽和度(僅適用於相機) |
CV_CAP_PROP_HUE | 圖像的色相(僅適用於相機) |
CV_CAP_PROP_GAIN | 圖像增益(僅適用於相機) |
CV_CAP_PROP_EXPOSURE | 曝光(僅適用於相機) |
CV_CAP_PROP_CONVERT_RGB | 布爾標誌,指示是否應將圖像轉換爲RGB |
CV_CAP_PROP_WHITE_BALANCE_U | 白平衡(攝像機對白色物體的還原)設置的U值(注意:當前僅由DC1394 v 2.x後端支持) |
CV_CAP_PROP_WHITE_BALANCE_V | 白平衡設置的V值(注意:當前僅由DC1394 v 2.x後端支持) |
CV_CAP_PROP_RECTIFICATION | 立體攝像機的整流標誌()(注意:當前僅受DC1394 v 2.x後端支持) |
CV_CAP_PROP_ISO_SPEED | 攝像機的ISO速度(快門速度)(注意:當前僅受DC1394 v 2.x後端支持) |
CV_CAP_PROP_BUFFERSIZE | 內部緩衝存儲器中存儲的幀數(注:當前僅由DC1394 v 2.x後端支持) |
. 保存抓取的視頻比起圖片稍微複雜一點。首先需要創建一個VideoWriter 對象,然後需要傳遞給他四個參數,第一個是需要輸出的文件名,第二個是FourCC代碼,第三個是幀率,第四個是畫面顯示大小,最後一個是isColor標誌,如果爲True,則編碼器需要彩色框,否則將與灰度框一起使用。
. 關於FourCC代碼,它是是一個4字節代碼,用於指定視頻編解碼器,種類非常多,試了幾個都沒出現問題,可以在這裏查看。
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'DIVX')
out = cv2.VideoWriter('output.avi',fourcc,20.0,(640,480))
while(True):
ret,frame = cap.read()
if ret == True:
out.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
畫些圖形
畫線
. 畫線使用的函數是cv2.line(),需要傳遞原圖像,開始座標,結束座標,線的顏色和粗細:
import cv2
import numpy as np
# 創建一塊黑色背景
img = np.zeros((512,512,3), np.uint8)
# 畫對角線
img = cv2.line(img,(0,0),(511,511),(255,0,0),5)
cv2.imshow('test',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
. numpy是一個用來處理複雜矩陣的庫,也包含了一些數學函數,zeros()函數相當於初始化一個數組,每個元素的類型由第二個參數指定,這裏是一個三位數組,可以前第一個參數中的將兩個值認爲是圖像的長寬,第三個值是每個像素點的RGB值。
畫矩形
. 畫矩形使用的函數是cv2.rectangle(),與畫線的函數類似,只是座標表示的是左上角座標和右下角座標了:
img = cv2.rectangle(img,(384,0),(510,128),(0,255,0),3)
畫圓
. 畫圓的函數是cv2.circle(),其中的座標參數換成了圓心座標和半徑:
#最後一個參數爲-1表示內部填充(實心)
img = cv2.circle(img,(447,63), 63, (0,0,255), -1)
畫橢圓
. 畫橢圓的函數是cv2.ellipse(),函數的參數變得更多了,第二個參數也是圓心座標,接下來是長軸和短軸的長度,然後是圖形的旋轉角度,然後是開始繪製的角度位置,然後是結束繪製的角度位置,最後也是繪製的線條粗細。
img = cv2.ellipse(img,(256,256),(100,50),0,120,360,(0,255,0),-1)
畫多邊形
. 畫多邊形的函數是cv2.polylines(),其參數主要是傳遞的各個頂點的座標:
#創建數組
pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
img = cv2.polylines(img,[pts],True,(0,255,255),3)
. 如果第三個參數傳遞的是False,將不會成爲一個封閉的圖形。第二個參數可以看出是一個三位數組,也就是說如果直接給一個三維數組,應該可以畫出多個圖形來,比如:
pts = np.array([
[[10,5],[20,30],[70,20],[50,10]],
[[100,50],[200,300],[170,200],[250,210]] ], np.int32)
img = cv2.polylines(img,pts,True,(0,255,255),5)
畫一些文字
. 在圖像上寫字可以使用函數cv2.putText(),需要的參數有:
1.原始圖像;
2.文字內容;
3.開始座標;
4.字體(文字樣式);
5.文字大小;
6.字體顏色;
7.筆跡粗細;
8.線形(線的樣式)。
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),3,cv2.LINE_AA)
鼠標作畫
鼠標事件
綁定回調函數
. 使用cv2.setMouseCallback() 來綁定鼠標事件發生時調用的函數,需要給調用的函數傳入事件類型變量:
#實現鼠標雙擊後自動生成一個圓
def draw_circle(event,x,y,falg,param):
if event == cv2.EVENT_LBUTTONDBLCLK:
cv2.circle(img,(x,y),100,(255,0,0),-1)
#生成黑色背景圖
img = np.zeros((512,512,3), np.uint8)
#窗口命名
cv2.namedWindow('image')
#綁定窗口和鼠標回調函數
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
if cv2.waitKey(20) == 27: #ESC
break
cv2.destroyAllWindows()
. 下面是一個更復雜的例子,通過鼠標拖動來畫矩形和圓:
import cv2
import numpy as np
#鼠標事件
drawing = False
eraer = True
mode = True
ix,iy = -1,-1
bx,by = -1,-1 #上一次的座標
def draw(event,x,y,falgs,param):
global ix,iy,drawing,mode,eraer,bx,by
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
eraer = True
ix,iy = x,y
bx, by = x, y
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
if mode == True:
if eraer == True:
cv2.rectangle(img, (ix, iy), (bx,by), (0, 0, 0), -1)
cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
bx,by = x,y
else:
cv2.circle(img,(x,y),5,(0,0,255),1)
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
eraer = False
if mode == True:
cv2.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 1)
else:
cv2.circle(img, (x, y), 5, (0, 0, 255), 1)
img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw)
while(1):
cv2.imshow('image',img)
if cv2.waitKey(1) == ord('m'):
mode = not mode
elif cv2.waitKey(1) == 27:
break
cv2.destroyAllWindows()
. 鼠標左鍵按下的時候定義原點座標,通過拖動來畫出矩形,左鍵釋放的時候確定最終圖形,通過按鍵‘m’來改變畫的圖形
使用TrackBar
. TrackBar的想滾動套一樣可以通過滑動來改變值,也可以設置滾動條的值來實現像按鈕開關一樣的功能。
. 主要使用的函數是cv2.getTrackbarPos(), cv2.createTrackbar(),前者是獲取當前trackbar的值,後者是創建一個trackbar,cv2.createTrackbar()的第一個參數是控件(trackbar)的名字,第二個參數是窗口名,第三個是trackbar的默認值,第四個參數是trackbar的最大值,第五個參數是當trackbar的值發生改變時調用的回掉函數。
. 以下是一個控制三基色的值改變屏幕背景色的例子:
def nothing(x):
pass
img = np.zeros((300,400,3),np.uint8)
cv2.namedWindow('image')
#創建trackbars
cv2.createTrackbar('R','image',0,255,nothing)
cv2.createTrackbar('G','image',0,255,nothing)
cv2.createTrackbar('B','image',0,255,nothing)
#使用trackbar充當按鈕開關一樣的功能
switch = '0: OFF \n 1: ON'
cv2.createTrackbar(switch,'image',0,1,nothing)
while(1):
cv2.imshow('img',img)
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
#獲取各個trackbar當前的值
r = cv2.getTrackbarPos('R','image')
g = cv2.getTrackbarPos('G','image')
b = cv2.getTrackbarPos('B','image')
s = cv2.getTrackbarPos(switch,'image')
if s == 0:
img[:] = 0
else:
img[:] = [b,g,r]
cv2.destroyAllWindows()