opencv-python學習筆記(一)


筆記來源於官方文檔

安裝

. 在控制檯運行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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章