2021-05-12 14:32:11
OpenCV計算機視覺學習(1)——影象基本操作(影象視訊讀取,ROI區域擷取,常用cv函數解釋)
1,計算機眼中的影象
我們開啟經典的 Lena圖片,看看計算機是如何看待圖片的:
簡易的矩形ROI區域獲取程式碼如下
import cv2 import numpy as np import matplotlib.pyplot as plt # 讀取原始影象 img = cv2.imread('irving.jpg') # print(img.shape) # (458, 558, 3) # 我們自己計算要獲取的頭部的大小,以及左上角的座標 # 這裡左上角的座標為:w:h=250 7 區域為100*100 roi_zero = img[7:107, 250:350] # 顯示影象 cv2.imshow("Image", roi_zero) # 等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
結果如下:
6,影象寬,高,通道數獲取
img.shape 返回影象高(影象矩陣的行數),寬(影象矩陣的列數)和通道數3個屬性組成的元組,若影象是非彩色圖(即灰度圖,二值圖等),則只返回高和寬組成的元組。
import cv2 img = cv2.imread("1.jpg") imgGrey = cv2.imread("1.jpg", 0) sp1 = img.shape sp2 = imgGrey.shape print(sp1) print(sp2)# ======輸出=======#(1200, 1920, 3)#(1200, 1920)
7,影象畫素數目和影象資料類型的獲取
影象矩陣img 的 size屬性和 dtype 分別對應影象的畫素總數目和影象資料類型。一般情況下,影象的資料類型是 uint8。
通過size關鍵字獲取影象的畫素數目,其中灰度影象返回行數*列數,彩色影象返回行數*列數*通道數。
通過dtype關鍵字獲取影象的資料類型,通常返回 uint8
程式碼如下:
# -*- coding:utf-8 -*- import cv2 import numpy #讀取圖片 img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED) #獲取影象形狀 print(img.shape) #獲取畫素數目 print(img.size) #獲取影象類型 print(img.dtype)
結果如下:
(615, 327, 3) 603315 # 603315=615*327*3 uint8
注意1:如果影象是灰度圖,返回值僅有行數和列數,所以通過檢查這個返回值就可以知道載入的是灰度圖還是彩色圖。img.size可以返回影象的畫素數目。
注意2:在debug時, img.dtype 非常重要,因為在OpenCV Python程式碼中經常出現數據類型的不一致。
8,生成指定大小的空影象
生成指定大小的空圖形,方便我們後續填充,空圖形是黑色的圖(因為指定的是0)。
import cv2 import numpy as np img = cv2.imread("1.jpg") imgZero = np.zeros(img.shape, np.uint8) imgFix = np.zeros((300, 500, 3), np.uint8) # imgFix = np.zeros((300,500),np.uint8) cv2.imshow("img", img) cv2.imshow("imgZero", imgZero) cv2.imshow("imgFix", imgFix) cv2.waitKey()
9,訪問和操作影象畫素
OpenCV中影象矩陣的順序是 B,G,R。可以直接通過座標位置訪問和操作影象畫素。
import cv2 img = cv2.imread("01.jpg") numb = img[50,100] print(numb) img[50,100] = (0,0,255) cv2.imshow("img",img) cv2.waitKey()
分開訪問影象某一通道畫素值也非常方便(下面程式碼將影象變為白色,即255):
import cv2 img = cv2.imread("01.jpg") img[0:100,100:200,0] = 255 img[100:200,200:300,1] = 255 img[200:300,300:400,2] = 255 cv2.imshow("img",img) cv2.waitKey()
Python中,更改影象某一矩形區域的畫素值也很方便。
import cv2 img = cv2.imread("01.jpg") img[0:50,1:100] = (0,0,255) cv2.imshow("img",img) cv2.waitKey()
注意:優化
首先我們需要讀入一幅影象,然後根據畫素的行和列的座標獲取它的畫素值。對BGR影象而言,返回值為B,G,R的值,對灰度影象而言,會返回它的灰度值(亮度? intensity)
import cv2 import numpy as np img=cv2.imread('test.jpg') px=img[100,100] print(px) blue=img[100,100,0] print(blue) # 我們可以使用類似的方式修改畫素值 img[100,100]=[255,255,255] print(img[100,100]) ## [255 255 255]
注意1:Numpy 是經過優化了的進行快速矩陣運算的軟體包,所以我們不推薦逐個獲取畫素值並修改,這樣會很慢,能有矩陣運算就不要迴圈。
注意2:上面提到的方法被用來選取矩陣的一個區域,比如說 前 5行的後3列。對於獲取每一個畫素值,也許使用Numpy 的 array.item() 和 array.itemset() 會更好,但是返回是標量。如果你想獲得所有 B,G,R的值,你需要使用 array.item() 分割他們。
獲取畫素值及其修改的更好的方法
import cv2 import numpy as np img=cv2.imread('test.jpg') print(img.item(10,10,2)) img.itemset((10,10,2),100) print(img.item(10,10,2)) # 59 # 100
10,影象顏色通道分離與合併
分離影象通道可以使用 cv2中 split函數,合併則可以使用 merge函數。
import cv2 img = cv2.imread("01.jpg") b , g , r = cv2.split(img) # b = cv2.split(img)[0] # g = cv2.split(img)[1] # r = cv2.split(img)[2] merged = cv2.merge([b,g,r]) cv2.imshow("Blue",b) cv2.imshow("Green",g) cv2.imshow("Red",r) cv2.imshow("Merged",merged) cv2.waitKey()
有時候,我們需要對 BGR 三個通道分別進行操作,這時你就需要把BGR拆分成單個通道,有時你需要把獨立通道的圖片合成一個BGR影象。下面學習一下拆分及其合併影象通道的cv函數
程式碼如下:
# _*_coding:utf-8_*_ import cv2 import numpy as np def split_image(img_path): img = cv2.imread(img_path) print(img.shape) # (800, 800, 3) # b, g, r = cv2.split(img) b = img[:, :, 0] g = img[:, :, 1] r = img[:, :, 2] cv2.imshow('b', b) # cv2.imshow('g', g) # cv2.imshow('r', r) cv2.waitKey(0) cv2.destroyAllWindows() def merge_image(img_path): img = cv2.imread(img_path) b, g, r = cv2.split(img) img = cv2.merge([b, g, r]) cv2.imshow('merge', img) cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == '__main__': img_path = 'durant.jpg' split_image(img_path) # merge_image(img_path)
注意:這裡拆分寫了兩個方法,為什麼呢?就是因為 cv2.split()是一個比較耗時的操作,只有真正需要時才用它,能用Numpy索引就儘量使用索引。
原圖:
B,G,R 三種通道的圖片:
合併後的圖片
假設,我們想是所有畫素的紅色通道值都為0,我們不必先拆分再賦值,我們可以直接使用 Numpy 索引,這樣會更快:
def assign_image(img_path): img = cv2.imread(img_path) img[:, :, 1] = 0 cv2.imshow('assign', img) cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == '__main__': img_path = 'durant.jpg' assign_image(img_path)
結果如下:
11,在影象上輸出文字
使用putText函數在圖片上輸出文字,函數原型:
putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None)
參數意思:
- img: 影象
- text:要輸出的文字
- org: 文字的起點座標
- fontFace: 字型
- fontScale: 字型大小
- color: 字型顏色
- thickness: 字圖加粗
程式碼如下:
import cv2 img = cv2.imread("durant.jpg") cv2.putText(img, "durant is my favorite super star", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255)) cv2.imshow("img", img) cv2.waitKey()
圖如下:
12, 影象縮放
cv2.resize()函數是來調整圖片的大小,改變圖片尺寸。
注意:CV2是BGR,而我們讀取的圖片是RGB,所以要注意一下,變換的時候注意對應。
其函數原型如下:
def resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None)
對應的各個參數意思:
src:輸入,原影象,即待改變大小的影象;
dsize:輸出影象的大小。如果這個參數不為0,那麼就代表將原影象縮放到這個Size(width,height)指定的大小;如果這個參數為0,那麼原影象縮放之後的大小就要通過下面的公式來計算:
dsize = Size(round(fx*src.cols), round(fy*src.rows))
其中,fx和fy就是下面要說的兩個參數,是影象width方向和height方向的縮放比例。
fx:width方向的縮放比例,如果它是0,那麼它就會按照(double)dsize.width/src.cols來計算;
fy:height方向的縮放比例,如果它是0,那麼它就會按照(double)dsize.height/src.rows來計算;
interpolation:這個是指定插值的方式,影象縮放之後,肯定畫素要進行重新計算的,就靠這個參數來指定重新計算畫素的方式,有以下幾種:
- INTER_NEAREST - 最鄰近插值
- INTER_LINEAR - 雙線性插值,如果最後一個參數你不指定,預設使用這種方法
- INTER_AREA - 使用畫素區域關係進行重取樣 resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
- INTER_CUBIC - 4x4畫素鄰域內的雙立方插值
- INTER_LANCZOS4 - 8x8畫素鄰域內的Lanczos插值
對於插值方法,正常情況下使用預設的雙線性插值法就夠了。幾種常用方法的效率為:
最鄰近插值>雙線性插值>雙立方插值>Lanczos插值
但是效率和效果是反比的,所以根據自己的情況酌情使用。
注意:輸出的尺寸格式為(寬,高)
示例:
# _*_coding:utf-8_*_ import cv2 image = cv2.imread('TestDataarial_qz8Shv_10.png') # 對圖片進行灰度化,注意這裡變換!! gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) crop_img = cv2.resize(gray, (224, 224), interpolation=cv2.INTER_LANCZOS4)
程式碼如下:
import cv2 img = cv2.imread("1.jpg") cv2.imshow("img", img) imgg = cv2.resize(img, (200, 100)) cv2.imshow("imgg", imgg) cv2.waitKey()
13 cv2.cvtColor()函數用法介紹
在日常生活中,我們看到的大多數彩色影象都是RGB類型,但是在影象處理過程中,常常需要用到灰度影象、二值影象、HSV、HSI等顏色,OpenCV提供了cvtColor()函數實現這些功能。其函數原型如下所示:
cvtColor(src, code, dst=None, dstCn=None)
變數含義:
- src表示輸入影象,需要進行顏色空間變換的原影象
- dst表示輸出影象,其大小和深度與src一致
- code表示轉換的程式碼或標識
- dstCn表示目標影象通道數,其值為0時,則有src和code決定
該函數的作用是將一個影象從一個顏色空間轉換到另一個顏色空間,其中,RGB是指Red、Green和Blue,一副影象由這三個通道(channel)構成;Gray表示只有灰度值一個通道;HSV包含Hue(色調)、Saturation(飽和度)和Value(亮度)三個通道。在OpenCV中,常見的顏色空間轉換標識包括CV_BGR2BGRA、CV_RGB2GRAY、CV_GRAY2RGB、CV_BGR2HSV、CV_BGR2XYZ、CV_BGR2HLS等。
下面程式碼對比了九種常見的顏色空間,包括BGR、RGB、GRAY、HSV、YCrCb、HLS、XYZ、LAB和YUV,並迴圈顯示處理後的影象。
#encoding:utf-8 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始影象 img_BGR = cv2.imread('miao.png') #BGR轉換為RGB img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB) #灰度化處理 img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY) #BGR轉HSV img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV) #BGR轉YCrCb img_YCrCb = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb) #BGR轉HLS img_HLS = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HLS) #BGR轉XYZ img_XYZ = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2XYZ) #BGR轉LAB img_LAB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2LAB) #BGR轉YUV img_YUV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YUV) #呼叫matplotlib顯示處理結果 titles = ['BGR', 'RGB', 'GRAY', 'HSV', 'YCrCb', 'HLS', 'XYZ', 'LAB', 'YUV'] images = [img_BGR, img_RGB, img_GRAY, img_HSV, img_YCrCb, img_HLS, img_XYZ, img_LAB, img_YUV] for i in xrange(9): plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
如果想檢視參數的全部類型,請執行以下程式便可查閱,總共有274種空間轉換類型:
import cv2 flags = [i for i in dir(cv2) if i.startswith('COLOR_')] print(flags)
參考文獻:https://blog.csdn.net/woainishifu/article/details/53260546
https://blog.csdn.net/eastmount/article/details/82177300
https://www.cnblogs.com/Undo-self-blog/p/8434906.html
https://www.cnblogs.com/zlel/p/9267629.html
視訊讀取:https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_video_display/py_video_display.html
https://blog.csdn.net/qq_25436597/article/details/79621833
https://zhuanlan.zhihu.com/p/44255577
相關文章