核心知識(shí)
(1)色彩空間變換
(2)像素訪問
(3)矩陣的 + -? * /
(4)基本圖形的繪制
以上的核心知識(shí)將會(huì)在接下來的部分給大家介紹清楚,并且有實(shí)戰(zhàn)代碼展示。
色彩空間
色彩空間基礎(chǔ)知識(shí)
(1)RGB:是通過對(duì)紅(R)、綠(G)、藍(lán)(B)三個(gè)顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,RGB即是代表紅、綠、藍(lán)三個(gè)通道的顏色。(簡單來說就是人對(duì)于顏色的一個(gè)識(shí)別,當(dāng)然機(jī)器也是這樣的)
(2)BGR:Opencv默認(rèn)使用BGR。
其實(shí)對(duì)于rgb和bgr來說,就是紅綠藍(lán)的排列順序不同,所以在編寫代碼時(shí),需要注意順序問題。
(3)HSV/HSB/HSL: Opencv最常用的就是HSV。H代表色相,S代表飽和度,V/B代表明亮度,HSV與HSB其實(shí)是一樣的,只是在翻譯時(shí)不同。
(4)YUV:主要用于視頻領(lǐng)域。
RGB和BGR
?
RGB:每一個(gè)方框都代表一個(gè)像素 ,每一個(gè)像素都是由RGB顯示出來的。
?
BGR:同樣與RGB類似,每一個(gè)方框都代表一個(gè)像素 ,每一個(gè)像素都是由BGR顯示出來的。
HSV與HSL
HSV相關(guān)知識(shí)
Hue:色相,即顏色,如紅色,藍(lán)色
Saturation:飽和度,顏色的純度(越大越純)
Value:明度(越明一點(diǎn)就代表黑色的部分少一點(diǎn))
?
?
?對(duì)于第一張圖,Hue是圓的一周,也就是在不同角度下顏色在發(fā)生變化。Saturation是從圓的平面看,從里到外值越來越高,顏色就越來越純(顏色中灰色的部分越來越少)。Value是從圓柱的高進(jìn)行觀察,從下到上,Value值越來越高,也就越來越亮(黑色的部分越來越少)。
為什么我們使用HSV?
因?yàn)橄鄬?duì)于RGB來說,HSV的參數(shù)更多,我們可以使用HSV來判斷色相,飽和度,亮度等等信息。使圖片描繪更加準(zhǔn)確。
HSL相關(guān)知識(shí)
Hue:色相,即顏色,如紅色,藍(lán)色
Saturation:飽和度,顏色的純度(越大越純)
ligthness:明度(越明一點(diǎn)就代表黑色的部分少一點(diǎn))
?
左邊的使HSL,我們可以發(fā)現(xiàn)Hue和Saturation都是相同的,并且高都是亮度,但是HSL從下到上出現(xiàn)最上面的顏色都是白色的現(xiàn)象,這個(gè)就是HSL。
相較于我們目前使用的HSV更加重要一點(diǎn)。
YUV
主要用于視頻中。
(1)YUV4:2:0
(2)YUV4:2:2
(3)YUV4:4:4
Y代表灰色的圖像,UV代表的是顏色 。YUV4:4:4其實(shí)就和RGB是一樣的,RGB是8:8:8
?
YUV4:2:0就是四個(gè)像素中有4個(gè)Y但是后面的2可能是U可能是V
色彩空間轉(zhuǎn)換實(shí)戰(zhàn)代碼
import cv2
def callback1(i):
pass
cv2.namedWindow('color', cv2.WINDOW_AUTOSIZE)
img = cv2.imread('E:\\pycharm\\PycharmFile\\opencv\\MM\\preview.jpg')
colorspaces = [cv2.COLOR_BGR2RGBA, cv2.COLOR_BGR2BGRA,
cv2.COLOR_BGR2GRAY, cv2.COLOR_BGR2HSV,
cv2.COLOR_BGR2YUV]
cv2.createTrackbar('curcolor', 'color', 0, 4, callback1)
while True:
index = cv2.getTrackbarPos('curcolor', 'color')
# print("11111")
# 色彩轉(zhuǎn)化api
cvt_img = cv2.cvtColor(img, colorspaces[index])
cv2.imshow('color', cvt_img)
key = cv2.waitKey(10)
if (key & 0xFF == ord('q')):
break
cv2.destroyAllWindows()
結(jié)果顯示如下:?
?
通過拖動(dòng)TrackBar改變顏色顯示,例如index為0的時(shí)候? cv2.COLOR_BGR2RGBA就是將原來的BGR圖片轉(zhuǎn)化為RGB。?其他情況和這種類似。
Numpy庫
圖像的加減乘除都與這個(gè)函數(shù)密切相關(guān)
Numpy庫的相關(guān)知識(shí)?
(1)Opencv中使用到的矩陣都需要轉(zhuǎn)化為Numpy數(shù)組
(2)Numpy是一個(gè)高度優(yōu)化的Python數(shù)值庫
Numpy基本操作
(1)創(chuàng)建矩陣:大家都知道圖形的處理其實(shí)就是矩陣的處理。說的簡單點(diǎn),就一個(gè)寬多少高多少的一個(gè)矩陣,每個(gè)矩陣值就是一個(gè)像素點(diǎn),那你只要改變其中的值,它這個(gè)顏色就發(fā)生變化。在它周圍做一些處理的話,就會(huì)形成一個(gè)形狀,如果把矩陣中的所有的位置都經(jīng)過特殊處理的話,那它就成了一幅圖片。如果把這些圖片再連在一起播放的話,它就成了視頻,這個(gè)就是一個(gè)基本的原理。
(2)檢索與賦值:我們要能夠知道如何獲取矩陣中某個(gè)元素的值。并且改變這個(gè)元素的值。
(3)獲取子數(shù)組:要獲取大的矩陣中的某一小塊兒矩陣,或者是給這一小塊矩陣賦值。
創(chuàng)建矩陣API:創(chuàng)建數(shù)組array(),創(chuàng)建全0或者全1的數(shù)組 zeros()/ones(),創(chuàng)建一個(gè)全值的數(shù)組 full()矩陣中所有的值都是指定的值,創(chuàng)建單位矩陣identity/eye()
檢索矩陣API:[y,x] 下標(biāo)是y和x,索引值是從0開始的。[y,x,channel]?channel通道數(shù),也可以認(rèn)為是層數(shù)。
獲取子矩陣API:[y1:y2,x1:x2] y1到y(tǒng)2范圍和x1到x2范圍。[:,:] 對(duì)整個(gè)矩陣進(jìn)行操作
Numpy實(shí)戰(zhàn)代碼
創(chuàng)建矩陣
array:a=array([2,3,4])這樣得到的就是一個(gè)一維的數(shù)組?
? ? ? ? ? ? b=array([[2,3,4],[1,2,3]])這樣得到了一個(gè)2x3的矩陣
import numpy as np
import cv2
# 通過array建立矩陣
a = np.array([1, 2, 3])
b = np.array([[1, 2, 3], [1, 2, 3]])
print(a)
print(b)
打印出的結(jié)果:
c=np.zeros((480,640,3),np.uint8) 打印出的是640x480
(480,640,3)(行的個(gè)數(shù),列的個(gè)數(shù),通道數(shù)/層數(shù))
np.uint8 矩陣中的數(shù)據(jù)類型
# 定義zeros矩陣
c = np.zeros((8, 8, 3), np.uint8) # ((行的個(gè)數(shù)(高),列的個(gè)數(shù)(寬),層數(shù)),np.uint8代表的是八位元素,最大值為255)
print(c)
d=np.ones((480,640,3),np.uint8) 打印出的是640x480
(480,640,3)(行的個(gè)數(shù),列的個(gè)數(shù),通道數(shù)/層數(shù))
np.uint8 矩陣中的數(shù)據(jù)類型
# 定義ones矩陣
d = np.ones((8, 8), np.uint8)
print(d)
e=np.full((480,640,3),255,np.uint8)? 其中255就是我們向矩陣中添加的值
(480,640,3)(行的個(gè)數(shù),列的個(gè)數(shù),通道數(shù)/層數(shù))
np.uint8 矩陣中的數(shù)據(jù)類型
# 定義full矩陣
e = np.full((8, 8), 255, np.uint8)
print(e)
?f=np.identity(3)
斜對(duì)角都是1,其余都是0 。括號(hào)中的3代表3x3的矩陣。
# 定義單位矩陣indentity
f = np.identity(4) # 4x4的單位矩陣
print(f)
打印出的結(jié)果:?
g=?np.eye((3,5),k=3) 與單位矩陣類似,但是可以說是長方形的
# 定義eye
g = np.eye(4) # 退化成identity矩陣了 4x4
h = np.eye(4, 5, k=2) # 4x5 第一個(gè)1是從第3列開始往下斜
print(g)
print(h)
打印出的結(jié)果 :
檢索矩陣?
在創(chuàng)建的矩陣中檢索出某個(gè)值
img = np.zeros((480, 640, 3), np.uint8) # 在(480,480)時(shí),打印的就是一個(gè)0 (480,480,3),打印是三個(gè)0
# 從矩陣中讀某個(gè)元素的值
print(img[100, 100])
也可以對(duì)這個(gè)檢索到的值進(jìn)行修改,如果修改的是一個(gè)范圍上的值,就可以清晰看出圖像出現(xiàn)變化,由于我們創(chuàng)建的是一個(gè)480x640的全0的圖,為黑色。對(duì)部分范圍值進(jìn)行修改,圖片出現(xiàn)變化。
count = 0
# 向矩陣中某個(gè)元素賦值
while count < 300:
# BGR
img[count, 100, 0] = 255 # 如果三次情況下[count,100]就是三層都變 [count,100,0]第一層變 按照bgr色彩變化
# img[count,100]=[255,0,0] #和上面賦值結(jié)果相同
count = count + 1
?運(yùn)行結(jié)果就是在黑色背景下,第一層顏色變化,第一層是藍(lán)色,所以出現(xiàn)下面的圖像。
獲取子矩陣?
roi = img[100:400, 100:600]
roi[:, :] = [0, 0, 255] # [:,:] 代表全部變化
# roi[:]=[0,0,255] 和上面的一樣 代表全部
roi[10:200, 10:300] = [0, 255, 0]
roi[200:280, 300:480] = [255, 0, 0]
cv2.imshow('roi', roi)
?首先我們?cè)谠瓉淼膱D片中取[100:400, 100:600]這個(gè)范圍變成我們的子矩陣,接著對(duì)子矩陣進(jìn)行全面的賦值,變成紅色,隨后在子矩陣中選擇兩個(gè)區(qū)域變換顏色,結(jié)果如下圖。
最重要的結(jié)構(gòu)體Mat
Mat的相關(guān)知識(shí)
Mat是什么?
從應(yīng)用的角度,實(shí)際上Mat就是一個(gè)矩陣。矩陣可能含有多個(gè)通道,如果是一個(gè)通道的話,它就是灰色的,只有黑白兩種顏色,就是一個(gè)二維矩陣。如果是全真色的,它就是一個(gè)三個(gè)通道的,矩陣包括了這個(gè)bgr 3種顏色,通過這種三種顏色可以組合中任何的顏色。
Mat有什么好處?
可以通過Numpy直接通過矩陣的形式對(duì)他進(jìn)行訪問。操作方便。
Mat的組成
?Mat由header和data組成,data中包含的就是存放圖像的具體數(shù)值。
header包括一些屬性,屬性包括:維數(shù),行列數(shù),存儲(chǔ)數(shù)據(jù)的指針,引用數(shù)據(jù)(也就是說。每一次就同一張圖片,通過不同的變量去引用它的時(shí)候呢,實(shí)際它修改的都是同一塊數(shù)據(jù)。)?
Mat的拷貝
從圖中了解,我們對(duì)MatA進(jìn)行拷貝為MatB,此時(shí)我們的數(shù)據(jù)其實(shí)沒有進(jìn)行拷貝的,只是將header部分進(jìn)行拷貝,當(dāng)我想調(diào)用data中的數(shù)據(jù)時(shí),可以使用MatB的header指向data得到想要的數(shù)據(jù),此種拷貝方式為淺拷貝(默認(rèn)拷貝就是淺拷貝)
淺拷貝
Mat A
A=imread(file,IMREAD_COLOR)
Mat B(A)
這樣就完成了對(duì)A的淺拷貝
深拷貝
cv::Mat:;clone()
cv::Mat::copyTo()
這樣就完成了對(duì)A的深拷貝
在python中的方法就是 copy()
Mat拷貝實(shí)戰(zhàn)代碼
import cv2
import numpy as np
img = cv2.imread('E:\\pycharm\\PycharmFile\\opencv\\MM\\preview.jpg')
# 淺拷貝
img2 = img
# 深拷貝
img3 = img.copy()
# 對(duì)圖像進(jìn)行修改
img[0:100, 0:100] = [0, 0, 255]
cv2.imshow('img', img)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
cv2.waitKey()
我們寫完代碼后思考,img我時(shí)拿到了一個(gè)圖片,通過img對(duì)img2進(jìn)行淺拷貝,那我如果對(duì)img圖片進(jìn)行修改的話,img2也會(huì)一起發(fā)生改變。而img3是深拷貝,應(yīng)該不會(huì)發(fā)生變化。接下來觀察結(jié)果。?
?
我們可以發(fā)現(xiàn),如我們想的那樣,img2和img發(fā)生了同樣的變化,而img3沒有發(fā)生變化。
訪問圖像(Mat)的屬性實(shí)戰(zhàn)代碼
訪問圖像的屬性在python直接使用shape就可以得到結(jié)果了。shape屬性中包括了高度,寬度,通道數(shù)三個(gè)屬性,size屬性可以知道圖像占用的空間大小,dtype屬性可以知道每個(gè)元素的位深。
import cv2
import numpy as np
img = cv2.imread('E:\\pycharm\\PycharmFile\\opencv\\MM\\preview.jpg')
# shape 屬性中包括了 高度 寬度 通道數(shù) 三個(gè)屬性
# 高度 寬度 通道數(shù)
print(img.shape)
# 圖像占用多大空間
# 高度*寬度*通道數(shù)
print(img.size)
# 圖像中每個(gè)元素的位深
print(img.dtype) # uint8
圖像通道分離與合并
圖像通道分離與合并API
分離:spit(mat)
?合并:merge((ch1,ch2,……))
圖像通道分離與合并實(shí)戰(zhàn)代碼
import cv2
import numpy as np
img = np.zeros((480, 460, 3), np.uint8)
b, g, r = cv2.split(img)
b[10:100, 10:100] = 255
g[60:150, 60:150] = 255
img2 = cv2.merge((b, g, r))
cv2.imshow('img', img)
cv2.imshow('b', b)
cv2.imshow('g', g)
cv2.imshow('img2', img2)
cv2.waitKey(0)
從代碼中可以思考,自己先創(chuàng)建了一個(gè)黑色的480x460的圖片,通過split對(duì)其進(jìn)行分離成3個(gè)圖,分別對(duì)其中兩個(gè)圖的部分進(jìn)行修改,變化的部分變成了白色。最后又將三張圖合并在一起,分別變化的部分依舊保留。結(jié)果如下顯示。?
文章來源:http://www.zghlxwxcb.cn/news/detail-775906.html
我們發(fā)現(xiàn),合并完后原先變化的部分是白色255,但是現(xiàn)在變成了藍(lán)色和綠色,并且相交的部分顏色變成青色,這個(gè)是因?yàn)楸旧砦覀冊(cè)O(shè)置圖片是三層的BGR,分別開處理時(shí)每一層就是一個(gè)單通道的0-255,但是合在一起又恢復(fù)成三通道了,顏色也就顯現(xiàn)出來了。文章來源地址http://www.zghlxwxcb.cn/news/detail-775906.html
到了這里,關(guān)于opencv必會(huì)基礎(chǔ)知識(shí)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!