一、OpenCV-python 之 圖像/視頻/繪圖

1、圖像部分

(1)圖像讀取

cv.imread(filepath, model)
filepath:圖片路徑
model:cv.IMREAD_COLOR				# 讀取3通道BGR圖像,默認參數
	   cv.IMREAD_GRAYSCALE			# 讀取灰度圖
       cv.IMREAD_UNCHANGED			# 讀取4通道rgba圖像

(1)讀取方式是根據文件的編碼內容,而不是根據文件名後綴
(2)對於彩色圖像,默認讀取順序是:B G R

(2)圖像顯示

cv.imshow(
	windowsname,		# 窗口名稱(保證與其他窗口不同)
    image				# 讀取的圖像變量
)
cv.waitKey(0)			# 指定顯示等待的時間,如果參數值爲0則一直顯示直到(在圖像窗口)按下任何鍵
cv.destroyAllWindows()	# 銷燬窗口

如果圖像類型不正確(例如通道順序),需要通過cv.convertTo、cv.cvtColor等方式去轉換。如果圖像的數據類型不正確(一般要求 uint8),OpenCV會進行默認處理,這有可能會使得我們看不到想要的結果,具體如下:

  • 如果是 8位無符號,那麼照常顯示;
  • 如果是 16位無符號/32位整型,那麼會除以256(如果像素值偏小,會得到幾乎全爲黑色的結果);
  • 如果是 32/64位浮點型,那麼會乘以255(如果像素值較小,會得到偏白色的結果);

(3)圖像保存

cv.imwrite(
    filename,			# 保存位置
    img,				# 圖像數據
    params
)

理論上只能保存8位的單通道、3通道BGR圖像,但是也有特殊情況(這裏包括保存爲不同的格式):保存爲 .jpg 後綴文件時,數據會有損失;如果是保存爲 .png 格式,則是無損保存,保存前後所有位置的像素值都不會改變。

  • 之所以保存爲 .jpg 格式會改變數據,是由於 JPG 格式自身存在數據壓縮(丟掉一部分不重要的重複數據),也就是說如果一直重複“保存-讀取-保存-讀取-…”這種操作,數據會不斷丟失、圖像會不斷變小;
  • 雖然可以通過 imwrite 的第三個參數來設置壓縮率,但是對於 .jpg 格式來說,即便設置爲 100(最大),也還是會有些許損失,無法避免;
  • BMP:這是一種具有深度的圖像格式,不採用任何壓縮,但是佔用文件空間會很大;
  • PNG:這是一種無損壓縮格式(有壓縮,但是無損),佔用空間比 .jpg 大(同樣一張圖PNG大概比JPG大2-3倍)。

(4)matplotlib的簡單使用

img = cv2.imread('messi4.jpg')			# OpenCV讀取圖像, BGR格式
img2 = img[:, :, ::-1]					# 轉換爲 RGB 格式
plt.subplot(121);plt.imshow(img)		# plt 顯示 BGR 圖像
plt.subplot(122);plt.imshow(img2)		# plt 顯示 RGB 圖像(正常的圖像)
plt.show()

OpenCV可以和matplotlib混用,但是OpenCV讀取的圖像內容按照 BGR 順序,而matplotlib則是按照 RGB 順序處理圖像,在混用時需要注意順序的轉換

2、視頻部分

(1)打開攝像頭

cap = cv.VideoCapture(0)
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()							# 返回第一個參數爲bool,讀取成功爲True

    # Our operations on the frame come here
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

    # Display the resulting frame
    cv.imshow('frame', frame)
    if cv.waitKey(1) & 0xFF == ord('q'):			# 注意這裏waitKey的參數是 1,表示 1 ms刷新
        break

# When everything done, release the capture
cap.release()
cv.destroyAllWindows()

cap.get可以獲取視頻窗口的參數,cap.set可以設置視頻窗口的參數

(2)讀取本地視頻

cap = cv.VideoCapture('test.avi')		# 將參數改成視頻名稱即可,後續步驟相同

(3)保存視頻

cap = cv.VideoCapture(0)

# Define the codec and create VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'XVID')							# 指定視頻編碼格式,這個跟系統環境有關(不同格式需要安裝不同編碼庫)
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640,480))		# 其他參數:幀率,尺寸大小,顏色(彩色或是灰度,這裏該參數省略)

while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        frame = cv.flip(frame,0)

        # write the flipped frame
        out.write(frame)

        cv.imshow('frame',frame)
        if cv.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

# Release everything if job is finished
cap.release()
out.release()
cv.destroyAllWindows()

這裏需要注意的幾個參數:
fourcc:這個需要根據系統類型、系統配置來,一般情況下 XVID 都會適用於Windows,所以保存爲 .avi 格式居多;但是在 OSX 中往往是 MJPG/x264 居多。
尺寸大小:要以所存圖像的大小爲依據,如果錯了會導致視頻無法播放;而且這個尺寸以 tuple 形式傳入,格式是 (width, height),這跟 image.shape 返回的格式剛好相反(OpenCV 中圖像數據的類型是 numpy.array,相當於是一個數組,所以它返回的 shape 就是數組的形狀(h,w,c))。

(4)視頻參數

cap = cv.VideoCapture(v_path)
cap.get([option])			# 獲取視頻的相關參數
cap.set([option], [value])	# 設置視頻的相關參數

參數options:
CV_CAP_PROP_FRAME_WIDTH	:視頻寬度
CV_CAP_PROP_FRAME_HEIGHT:視頻高度
CV_CAP_PROP_FRAME_COUNT	:視頻總幀數
CV_CAP_PROP_FPS			:視頻幀率
CV_CAP_PROP_POS_FRAMES	:當前幀的索引數(到第幾幀了)

e.g:
cap.get(CV_CAP_PROP_FRAME_COUNT)	:獲取視頻的總幀數
cap.set(CV_CAP_PROP_POS_FRAMES, 10)	:定位到視頻的第10

3、繪圖部分

具體參數參考官網實例

# 通用參數
pt1/pt2		: tuple 類型,cv.Point,裏面必須是整數
center		: tuple 類型,cv.Point,裏面必須是整數
color		: tuple 類型,用來設置線條顏色,注意是 BGR 配色
radius		: int 類型,單位是 px
axes		: tuple 類型,用來設置長短軸
angle		: double 類型,旋轉角度
org			: tuple 類型,cv.Point,文字的書寫位置
fontFace	: int 類型,可設置值有0~7/16,每種都會呈現不同的字體效果(個人一般取5)
fontScale	: double 類型,字體大小
thickness	: int 類型,用來設置線寬,單位是 px,如果是負值表示填充整個區域
linetype	: 用來設置線型,cv.FILLED/cv.LINE_4/cv.LINE_8/cv.LINE_AA
shift		: 座標中的小數位數,默認爲0,一般不作處設置

cv.line(img, pt1, pt2, color, thickness, lineType, shift)
cv.circle(img, center, radius, color, thickness, lineType, shift)
cv.rectangle(img, pt1, pt2, color, thickness, lineType, shift)
cv.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness, lineType, shift)
cv.putText(img, text, org, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin)

這裏重點看一下 OpenCV 如何在圖像中書寫文字。OpenCV 書寫文字的接口 cv.putText 上面展示了,它總共有九種字體,用 0~7、16 分別編號,具體效果如下:
在這裏插入圖片描述
有時候我們需要給文字添加背景色,那這個背景區域的長寬、位置該如何確定?這實際上取決於文字的長寬、位置,OpenCV 獲取文字尺寸的方式:

cv.getTextSize(
	text,			# 需要書寫的文本內容,OpenCV默認不支持中文書寫
	fontType, 		# 選擇哪種字體
	fontScale, 		# 字體縮放比列
	thickness		# 文本書寫的線寬
)

return:
	retval:	(w, h),文本區域所需要的寬高
	baseline: 基線相對於最底部文本點的y座標

所以要注意:OpenCV 書寫文本的位置參數並不是左上角,而是基線的最左端;同時,英文還有一個 baseline 距離!因此,如果要給文本添加一個背景色,那麼背景區域的左上角、右下角就是 pt1=(pos[0],pos[1]-h), pt2=(pos[0]+w,pos[1]+baseline)
在這裏插入圖片描述
OpenCV 如何書寫中文?它需要藉助 PIL:

import cv2 as cv
from PIL import Image, ImageDraw, ImageFont

def draw_(img, text_src, pos, rgb_color, font_scale):
	# 將 OpenCV 的BGR圖像轉換到 Image 的RGB圖像
    out_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
    out_img = Image.fromarray(out_img)

	# 新建畫筆
    draw = ImageDraw.Draw(out_img)
    # 字體屬性設置
    font = ImageFont.truetype("C:\Windows\Fonts\simhei.ttf", font_scale)
    # 書寫漢字,書寫位置是左上角
    draw.text(pos, text_src, rgb_color, font=font)
    # 轉換回 OpenCV 的BGR空間
    out_img = cv.cvtColor(np.array(out_img), cv.COLOR_RGB2BGR)

    return out_img

4、鼠標事件

(後續補充!)

5、進度條控制參數

(後續補充!)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章