openCV入門(mén)學(xué)習(xí)基礎(chǔ)教程第一篇
前言:計(jì)算機(jī)眼中的圖片
- 計(jì)算機(jī)中圖片由許多個(gè)像素點(diǎn)組成,如一個(gè)500x500的圖片,表示長(zhǎng)寬各由500個(gè)像素點(diǎn)組成。
- 計(jì)算機(jī)中一個(gè)像素點(diǎn)的值在0-255表示該點(diǎn)亮度 0暗(黑)-255亮(白)
- 一張彩圖通常是由RGB(red、green、blue)三個(gè)顏色通道所組成
- 一個(gè)500x500的圖片那他們的 RGB 矩陣也各是500x500。

上圖我們將一個(gè)大的圖片分割成許多如20x20的小圖片,同理每個(gè)小圖片它們的RGB矩陣也各自是20x20。
注:opencv默認(rèn)順序不是RBG 而是 BGR。
1. 圖片的讀取與顯示
1.1 圖片的讀取
import cv2
img = cv2.imread('./data/abv.jpg')img = cv2.imread('./data/abv.jpg')
比如我讀入這樣一張圖片,命名為img;

我們可以看到img是一個(gè)三維ndarray結(jié)構(gòu),內(nèi)部數(shù)據(jù)類(lèi)型dtype=unit8:

三維:(1080,1920,3)表示高度、寬度、顏色通道個(gè)數(shù)(cv彩圖BGR)ndarray結(jié)構(gòu):數(shù)據(jù)類(lèi)型dtype=unit8, 0-255。
1.2 顯示的圖片
1.2.1 顯示原始圖片
cv2.imshow('image',img) # 第一個(gè)參數(shù)表示窗口指定的名字 第二個(gè)為上方img
cv2.waitKey(5000) # 等待時(shí)間 如果是5000則在5s后圖片窗口自動(dòng)關(guān)閉 0表示任意鍵關(guān)閉
cv2.destroyAllWindows() # 時(shí)間一到關(guān)閉窗口ps: 圖像的顯示也可以是多個(gè)窗口
- cv2.imshow('image',img) 自己給將要彈出的窗口起個(gè)名 再加入變量img
- cv2.waitKey(5000) 等待時(shí)間 如果是5000則在5s后圖片窗口自動(dòng)關(guān)閉 0表示任意鍵關(guān)閉
- cv2.destroyAllWindows() 時(shí)間一到關(guān)閉窗口
為方便下面使用,我們自己定義一個(gè)函數(shù)cv_show():
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()執(zhí)行代碼,彈出窗口,顯示圖片:
cv_show('winName',img)
1.2.2 灰度圖
在之前的基礎(chǔ)之上加入?yún)?shù):cv2.IMREAD_GRAYSCALE
img2=cv2.imread('./data/abv.jpg',cv2.IMREAD_GRAYSCALE) # cv2.IMREAD_COLORimg2=cv2.imread('./data/abv.jpg',cv2.IMREAD_GRAYSCALE)
- cv2.IMREAD_GRAYSCALE 讀取為灰度圖,也可以寫(xiě)0。
- cv2.IMREAD_COLOR 讀取為彩圖
我們執(zhí)行:
cv_show('win2',img2) 
可以看到該圖片最終顯示結(jié)果為二維(1080,1920) :

ps: img.size 輸出像素點(diǎn)的個(gè)數(shù),可以看到同一張圖片BGR彩圖是灰度圖的三倍。

1.3 BGR轉(zhuǎn)換成灰度圖、RGB
當(dāng)然我們也可以把已經(jīng)讀取進(jìn)來(lái)的BGR彩圖轉(zhuǎn)換成灰度圖,或者轉(zhuǎn)換為RGB。
img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv_show('win3',img2)img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
- cv2.COLOR_BGR2RGB 將BGR格式轉(zhuǎn)換成RGB
- cv2.COLOR_BGR2GRAY 將BGR格式轉(zhuǎn)換成灰度圖片
2. 保存圖片
cv2.imwrite('./data/grayPhoto.jpg',img2)cv2.imwrite('./data/grayPhoto.jpg',img2)
此時(shí)我的data文件夾下就多了一張才處理好名為grayPhoto的灰度圖。

3. 視頻的讀取與顯示
視頻也是由圖像組成的,每一幀都可以當(dāng)作是一個(gè)靜止的圖像,把圖像連在一起看著就像是一個(gè)視頻了。 我們打游戲時(shí),也是追求一些更高的幀率。
vc = cv2.VideoCapture('./data/stu.mp4')vc = cv2.VideoCapture('./data/stu.mp4')
# 檢查是否正確打開(kāi)
if vc.isOpened():
open,frame = vc.read()
else:
open = Flasevc.read()
- 讀取視頻中的第一幀 ,再次執(zhí)行vc.read()的話讀取視頻第二幀
- 返回值中:第一個(gè):布爾類(lèi)型,能讀進(jìn)來(lái)就是True 第二個(gè)像是上面的img,這一幀圖片的ndarray矩陣
循環(huán)圖片播放視頻:
while open:
ret,frame = vc.read()
if frame is None:
break
if ret == True:
# 原本frame是(h,w,3)的BGR圖片矩陣 經(jīng)下方加入?yún)?shù)轉(zhuǎn)換成黑白gray
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
cv2.imshow('result',gray)
# cv2.waitKey(num) 該圖片顯示時(shí)間/速度 自己可以找一個(gè)合適的值
# 27指退出鍵ESC 退出窗口 當(dāng)然也可以是 =='q'等
if cv2.waitKey(20)&0xFF == 27:
break
vc.release()
cv2.destroyAllWindows()注:視頻放完 ret, frame = vc.read()返回False和None 再次進(jìn)行循環(huán)無(wú)法播放視頻,需要重新讀取。
if cv2.waitKey(20)&0xFF == 27:
- 不是新知識(shí)點(diǎn)了,表示每張圖片等20毫秒,如果按ESC鍵直接退出。
4. 截取圖像部分
我們上面介紹,img是一個(gè)ndarray矩陣,因此對(duì)其進(jìn)行切片操作:
pho = img[100:800,200:800] # 進(jìn)行切片 高100到800 寬200到800
cv_show('win2',pho)pho = img[100:800,200:800]

5. 顏色通道提取
b,g,r = cv2.split(img) # b.shape g.shape r.shape 都為 (1080, 1920)
執(zhí)行
cv_show('win3',g) # 或者填 b、r
結(jié)果就是單通道圖。
如果我們想顯示單一顏色,如紅色:
cur_img = img.copy()
cur_img[:,:,0] = 0 # B不要了 設(shè)置為0
cur_img[:,:,1] = 0 # G不要了 設(shè)置為0
#cur_img[:,:,2] = 0 # R不要了 設(shè)置為0
cv_show('winR',cur_img)
6. 邊界填充
這個(gè)一般用于卷積,在圖像周?chē)畛湟恍┫袼亍?/p>
我們以這個(gè)圖片為例:
img = cv2.imread('./data/gd01.jpg')
# img.shape 為 (300, 400, 3)
cv_show('win1',img)
在圖片的上下左右填充50個(gè)像素,介紹5種方法:
top_size,bottom_size,left_size,right_size=(50,50,50,50) # 不同的填充方法 最后參數(shù)改個(gè)type值就行 replicate = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REPLICATE) reflect = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT) reflect101=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT_101) wrap = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_WRAP) constant = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_CONSTANT,value=0)
plt.subplot(231),plt.imshow(img,'gray'),plt.title('ORIGINAL')
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')
# 注matplotlib默認(rèn)R G B本例只介紹邊界填充
plt.show()
- cv2.BORDER_REPLICATE
- 復(fù)制最邊緣的像素
- cv2.BORDER_REFLECT
- 反射法對(duì)感興趣的圖像中的像素在兩邊進(jìn)行復(fù)制 如fedcba|abcdefgh|hgfedcb 其中abcdefgh是圖像"|"外的是填充內(nèi)容
- cv2.BORDER_REFLECT_101
- 反射法,也就是以最邊緣的像素為軸,對(duì)稱(chēng),gfedcb|abcdefgh|gfedcba 上面是ba|ab 這個(gè)是bab。
- cv2.BORDER_WRAP
- 外包裝法 如:cdefgh|abcdefgh|abcdefg。
- cv2.BORDER_CONSTANT
- 常量法,常數(shù)值value填充。
7. 數(shù)值計(jì)算

由于是uint8類(lèi)型最大255 超過(guò)相當(dāng)于結(jié)果為 num%256了
我們使用以下方法保留最大值:
cv2.add(img,img2)
cv2.add(img,img2)

8. 圖像融合
效果如下:

我們導(dǎo)入寬高相同的2張圖片:
img = cv2.imread('./data/gd04.jpg')
img2 = cv2.imread('./data/gd05.jpg')
img3 = cv2.imread('./data/gd06.jpg')
print(img.shape,img2.shape,img3.shape) # (281, 600, 3) (281, 600, 3) (337, 600, 3)如果大小不同 需要手動(dòng)設(shè)置成一樣的
img3 = cv2.resize(img3,(600,281)) # img3.shape (281, 600, 3)
img3 = cv2.resize(img3,(600,281))
ps: cv2.resize()另一種操作
img4 = cv2.resize(img3,(0,0),fx=2,fy=1)
我們執(zhí)行:
res = cv2.addWeighted(img,0.6,img2,0.4,0) plt.imshow(res)
res = cv2.addWeighted(img,0.6,img2,0.4,0)

R = ax1 + bx2 + c a、b為權(quán)重 c為偏置 這里意為在原亮度上變化多少
9. 知識(shí)點(diǎn)總結(jié)*
讀取圖片:
import cv2
img = cv2.imread('./data/abv.jpg')
img2 = cv2.imread('./data/abv.jpg',cv2.IMREAD_GRAYSCALE)
img3 = cv2.imread('./data/abv.jpg',cv2.IMREAD_COLOR) 顯示圖片:
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()BGR轉(zhuǎn)換成灰度圖、RGB:
img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) img3 = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
保存圖片:
cv2.imwrite('./data/grayPhoto.jpg',img2)視頻的讀取與顯示:
vc = cv2.VideoCapture('./data/stu.mp4')
# 檢查是否正確打開(kāi)
if vc.isOpened():
open,frame = vc.read()
else:
open = Flase
while open:
ret,frame = vc.read()
if frame is None:
break
if ret == True:
# 原本frame是(h,w,3)的BGR圖片矩陣 經(jīng)下方加入?yún)?shù)轉(zhuǎn)換成黑白gray
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
cv2.imshow('result',gray)
# cv2.waitKey(num) 該圖片顯示時(shí)間/速度 自己可以找一個(gè)合適的值
# 27指退出鍵ESC 退出窗口 當(dāng)然也可以是 =='q'等
if cv2.waitKey(20)&0xFF == 27:
break
vc.release()
cv2.destroyAllWindows()截取圖片部分:
pho = img[100:800,200:800] # 進(jìn)行切片 高100到800 寬200到800
顏色通道提?。?/p>
b,g,r = cv2.split(img)
cur_img = img.copy()
cur_img[:,:,0] = 0 # B不要了 設(shè)置為0
cur_img[:,:,1] = 0 # G不要了 設(shè)置為0
#cur_img[:,:,2] = 0 # R不要了 設(shè)置為0
cv_show('winR',cur_img)邊界填充:
top_size,bottom_size,left_size,right_size=(50,50,50,50) # 不同的填充方法 最后參數(shù)改個(gè)type值就行 replicate = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REPLICATE) reflect = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT) reflect101=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT_101) wrap = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_WRAP) constant = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_CONSTANT,value=0)
數(shù)值計(jì)算:
cv2.add(img,img2)
圖像融合:
img3 = cv2.resize(img3,(600,281)) res = cv2.addWeighted(img,0.6,img2,0.4,0)
總結(jié)
到此這篇關(guān)于openCV入門(mén)學(xué)習(xí)基礎(chǔ)教程的文章就介紹到這了,更多相關(guān)openCV第一篇內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python實(shí)現(xiàn)生成Word、docx文件的方法分析
這篇文章主要介紹了python實(shí)現(xiàn)生成Word、docx文件的方法,結(jié)合實(shí)例形式分析了Python使用docx模塊操作word文件與docx文件的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-08-08
windows下安裝python的C擴(kuò)展編譯環(huán)境(解決Unable to find vcvarsall.bat)
這篇文章主要介紹了windows下安裝python的C擴(kuò)展編譯環(huán)境(解決Unable to find vcvarsall.bat),需要的朋友可以參考下2018-02-02
python操作MySQL數(shù)據(jù)庫(kù)具體方法
堅(jiān)持每天學(xué)一點(diǎn),每天積累一點(diǎn)點(diǎn),作為自己每天的業(yè)余收獲,這個(gè)文章是我在吃飯的期間寫(xiě)的,利用自己零散的時(shí)間學(xué)了一下python操作MYSQL,所以整理一下。我采用的是MySQLdb操作的MYSQL數(shù)據(jù)庫(kù)。先來(lái)一個(gè)簡(jiǎn)單的例子吧2013-10-10
Python中計(jì)算三角函數(shù)之cos()方法的使用簡(jiǎn)介
這篇文章主要介紹了Python中計(jì)算三角函數(shù)之cos()方法的使用簡(jiǎn)介,是Python入門(mén)的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-05-05
PyTorch?Dataset與DataLoader使用超詳細(xì)講解
用于處理數(shù)據(jù)樣本的代碼可能會(huì)變得凌亂且難以維護(hù);理想情況下,我們希望數(shù)據(jù)集代碼與模型訓(xùn)練代碼解耦,以獲得更好的可讀性和模塊化。PyTorch提供的torch.utils.data.DataLoader和torch.utils.data.Dataset允許你使用預(yù)下載的數(shù)據(jù)集或自己制作的數(shù)據(jù)2022-10-10
python3 使用函數(shù)求兩個(gè)數(shù)的和與差
這篇文章主要介紹了python3 使用函數(shù)求兩個(gè)數(shù)的和與差,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2021-05-05
python數(shù)據(jù)分析apply(),map(),applymap()用法
這篇文章主要介紹了python數(shù)據(jù)分析apply(),map(),applymap()用法,可以方便地實(shí)現(xiàn)對(duì)批量數(shù)據(jù)的自定義操作。用法歸納如下,需要的朋友可以參考一下2022-03-03

