python?OpenCV圖像金字塔
1.圖像金字塔理論基礎(chǔ)
圖像金字塔是圖像多尺度表達(dá)的一種,是一種以多分辨率來(lái)解釋圖像的有效但概念簡(jiǎn)單的結(jié)構(gòu)。一幅圖像的金字塔是一系列以金字塔形狀排列的分辨率逐步降低,且來(lái)源于同一張?jiān)紙D的圖像集合。其通過(guò)梯次向下采樣獲得,直到達(dá)到某個(gè)終止條件才停止采樣。我們將一層一層的圖像比喻成金字塔,層級(jí)越高,則圖像越小,分辨率越低。
那我們?yōu)槭裁匆鰣D像金字塔呢?這就是因?yàn)楦淖兿袼卮笮∮袝r(shí)候并不會(huì)改變它的特征,比方說(shuō)給你看1000萬(wàn)像素的圖片,你能知道里面有個(gè)人,給你看十萬(wàn)像素的,你也能知道里面有個(gè)人,但是對(duì)計(jì)算機(jī)而言,處理十萬(wàn)像素可比處理1000萬(wàn)像素要容易太多了。就是為了讓計(jì)算機(jī)識(shí)別特征這個(gè)事變得更加簡(jiǎn)便,后期我們也會(huì)講到識(shí)別特征這個(gè)實(shí)戰(zhàn)項(xiàng)目,大概就是說(shuō)比如你在高中打籃球,遠(yuǎn)遠(yuǎn)的看見你班主任出來(lái)了,你們離500米,你依然可以根據(jù)特征取認(rèn)識(shí)出來(lái)你的老師,和你班主任離你2米的時(shí)候一樣。
也就是說(shuō)圖像金字塔式同一個(gè)圖像不同分辨率子圖的集合。在這里我們可以舉一個(gè)例子就是原始圖像是一個(gè)400400的圖像,那么向上取就可以是200200的一張圖像然后100*100,這樣分辨率降低,但是始終是同一個(gè)圖像。
那么從第i層到第i+1層,他具體是怎么做的呢?
1.計(jì)算輸入圖像減少的分辨率的近似值。這可以通過(guò)對(duì)輸入進(jìn)行濾波并以2為步長(zhǎng)進(jìn)行抽樣(即子抽樣)。可以采用的濾波操作有很多,如鄰域平均(可生成平均值金字塔),高斯低通濾波器(可生成高斯金字塔),或者不進(jìn)行濾波,生成子抽樣金字塔。生成近似值的質(zhì)量是所選濾波器的函數(shù)。沒(méi)有濾波器,在金字塔的上一層中的混淆變得很顯著,子抽樣點(diǎn)對(duì)所選取的區(qū)域沒(méi)有很好的代表性。
2.對(duì)上一步的輸出進(jìn)行內(nèi)插(因子仍為2)并進(jìn)行過(guò)濾。這將生成與輸入等分辨率的預(yù)測(cè)圖像。由于在步驟1的輸出像素之間進(jìn)行插值運(yùn)算,所以插入濾波器決定了預(yù)測(cè)值與步驟1的輸入之間的近似程度。如果插入濾波器被忽略了,則預(yù)測(cè)值將是步驟1輸出的內(nèi)插形式,復(fù)制像素的塊效應(yīng)將變得很明顯。
3.計(jì)算步驟2的預(yù)測(cè)值和步驟1的輸入之間的差異。以j級(jí)預(yù)測(cè)殘差進(jìn)行標(biāo)識(shí)的這個(gè)差異將用于原始圖像的重建。在沒(méi)有量化差異的情況下,預(yù)測(cè)殘差金字塔可以用于生成相應(yīng)的近似金字塔(包括原始圖像),而沒(méi)有誤差。
執(zhí)行上述過(guò)程P次將產(chǎn)生密切相關(guān)的P+1級(jí)近似值和預(yù)測(cè)殘差金字塔。j-1級(jí)近似值的輸出用于提供近似值金字塔,而j級(jí)預(yù)測(cè)殘差的輸出放在預(yù)測(cè)殘差金字塔中。如果不需要預(yù)測(cè)殘差金字塔,則步驟2和3、內(nèi)插器、插入濾波器以及圖中的加法器都可以省略。
這里面下取樣表示圖像的縮小。向上取樣表示的是圖像的增大。
1.對(duì)圖像Gi進(jìn)行高斯核卷積。
高斯核卷積就是我們所說(shuō)的高斯濾波操縱,我們之前就已經(jīng)講過(guò),使用一個(gè)高斯卷積核,讓臨近的像素值所占的權(quán)重較大,然后和目標(biāo)圖像做相關(guān)操作。
2.刪除所有的偶數(shù)行和列。
原始圖像 M * N 處理結(jié)果 M/2 * N/2。每次處理后,結(jié)果圖像是原來(lái)的1/4。這個(gè)操作被稱為Octave。重復(fù)執(zhí)行該過(guò)程,構(gòu)造圖像金字塔。直至圖像不能繼續(xù)下分為止。這個(gè)過(guò)程會(huì)丟失圖像信息。
而向上取樣恰恰和向下取樣相反,是在原始圖像上,**在每個(gè)方向上擴(kuò)大為原來(lái)的2倍,新增的行和列以0填充。使用與“向下采用”同樣的卷積核乘以4,獲取“新增像素”的新值。**經(jīng)過(guò)向上取樣后的圖像會(huì)模糊。
向上采樣、向下采樣不是互逆操作。經(jīng)過(guò)兩種操作后,無(wú)法恢復(fù)原有圖像。
2.向下取樣函數(shù)及使用
圖像金字塔向下取樣函數(shù):
dst=cv2.pyrDown(src)
import cv2 import numpy as np o=cv2.imread("image\\man.bmp") r1=cv2.pyrDown(o) r2=cv2.pyrDown(r1) r3=cv2.pyrDown(r2) cv2.imshow("original",o) cv2.imshow("PyrDown1",r1) cv2.imshow("PyrDown2",r2) cv2.imshow("PyrDown3",r3) cv2.waitKey() cv2.destroyAllWindows()
這里我們對(duì)圖像做三次向下取樣,結(jié)果為:
向下取樣會(huì)丟失信息?。?!
3.向上取樣函數(shù)及使用
圖像金字塔向上取樣函數(shù):
dst=cv2.pyrUp(src)
這里代碼我們就不做介紹了。
直接看一下我們的結(jié)果:
4.采樣可逆性研究
這里我們具體看一下圖像進(jìn)行向下取樣然后進(jìn)行向上取樣操作后,是不是一致的。還有就是圖像進(jìn)行向上取樣然后向下取樣后,是不是一致的呢?這里我們以小女孩的圖像做一下研究。
首先我們來(lái)分析一下:當(dāng)圖像做向下取樣一次之后,圖像由MN變成了M/2N/2,然后再次經(jīng)過(guò)向上取樣之后又變成了M*N。那么可以證明對(duì)于圖片的size是不發(fā)生變化的。
import cv2 o=cv2.imread("image\\girl.bmp") down=cv2.pyrDown(o) up=cv2.pyrUp(down) cv2.imshow("original",o) cv2.imshow("down",down) cv2.imshow("up",up) cv2.waitKey() cv2.destroyAllWindows()
那么我們來(lái)看一下到底發(fā)生了什么變化呢?
這里可以很清晰的看出來(lái)小女孩的照片變得模糊了,那么是為什么呢?因?yàn)槲覀兩厦嬲f(shuō)到了就是當(dāng)圖像變小的時(shí)候,那么就會(huì)損失一些信息,再次放大之后,由于卷積核變大了,那么圖像會(huì)變模糊。所以不會(huì)和原始圖像保持一致。
然后我們?cè)賮?lái)看一下先進(jìn)行向上取樣操作,然后進(jìn)行向下取樣操作會(huì)是什么樣子呢?由于圖像變大太大所以我們省去中間圖像向上取樣的圖片。
那么我們用肉眼也不是特別容易發(fā)現(xiàn)差異,那么我們用圖像減法去看一下。
import cv2 o=cv2.imread("image\\girl.bmp") up=cv2.pyrUp(o) down=cv2.pyrDown(up) diff=down-o #構(gòu)造diff圖像,查看down與o的區(qū)別 cv2.imshow("difference",diff) cv2.waitKey() cv2.destroyAllWindows()
5.拉普拉斯金字塔
我們先來(lái)看一下拉普拉斯金字塔是一個(gè)什么東西:
Li = Gi - PyrUp(PyrDown(Gi))
我們根據(jù)他這個(gè)式子可以知道,拉普拉斯金字塔就是使用原始圖像減去圖像向下取樣然后向上取樣的這樣一個(gè)過(guò)程。
展示在圖像當(dāng)中就是:
核心函數(shù)就是:
od=cv2.pyrDown(o) odu=cv2.pyrUp(od) lapPyr=o-odu
6.圖像輪廓介紹
首先我們先要說(shuō)明這樣一個(gè)事情就是彼圖像輪廓和圖像的邊緣是不一樣的,邊緣是零零散散的,但是輪廓是一個(gè)整體。
邊緣檢測(cè)能夠測(cè)出邊緣,但是邊緣是不連續(xù)的。將邊緣連接為一個(gè)整體,構(gòu)成輪廓。
注意:
對(duì)象是二值圖像。所以需要預(yù)先進(jìn)行閾值分割或者邊緣檢測(cè)處理。查找輪廓需要更改原始圖像。因此,通常使用原始圖像的一份拷貝操作。在OpenCV中,是從黑色背景中查找白色對(duì)象。因此,對(duì)象必須是白色的,背景必須是黑色的。
對(duì)于圖像輪廓的檢測(cè)需要的函數(shù)是:
cv2.findContours( )和cv2.drawContours( )
查找圖像輪廓的函數(shù)是cv2.findContours(),通過(guò)cv2.drawContours()將查找到的輪廓繪制到圖像上。
對(duì)于cv2.findContours( )函數(shù):
image, contours, hierarchy = cv2.findContours( image, mode, method)
這里需要注意在最新的版本中,查找輪廓中的返回函數(shù)只有兩個(gè)即可:
contours, hierarchy = cv2.findContours( image, mode, method)
contours ,輪廓
hierarchy ,圖像的拓?fù)湫畔?輪廓層次)
image ,原始圖像
mode ,輪廓檢索模式
method ,輪廓的近似方法
這里我們需要介紹mode:也就是輪廓檢索模式:
- cv2.RETR_EXTERNAL :表示只檢測(cè)外輪廓
- cv2.RETR_LIST :檢測(cè)的輪廓不建立等級(jí)關(guān)系
- cv2.RETR_CCOMP :建立兩個(gè)等級(jí)的輪廓,上面的一層為外邊界,里面的一層為內(nèi)孔的邊 界信息。如果內(nèi)孔內(nèi)還有一
個(gè)連通物體,這個(gè)物體的邊界也在頂層
- cv2.RETR_TREE :建立一個(gè)等級(jí)樹結(jié)構(gòu)的輪廓。
然后我們介紹一下method ,輪廓的近似方法:
- cv2.CHAIN_APPROX_NONE :存儲(chǔ)所有的輪廓點(diǎn),相鄰的兩個(gè)點(diǎn)的像素位置差不超過(guò)1, 即max(abs(x1-x2),abs(y2-y1))==1
- cv2.CHAIN_APPROX_SIMPLE:壓縮水平方向,垂直方向,對(duì)角線方向的元素, 只保留該方向的終點(diǎn)坐標(biāo),例如一個(gè)矩形輪廓只需4個(gè)點(diǎn)來(lái)保存輪廓信息
- cv2.CHAIN_APPROX_TC89_L1:使用teh-Chinl chain 近似算法
- cv2.CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain 近似算法
比如對(duì)一個(gè)矩形做輪廓檢測(cè),使用cv2.CHAIN_APPROX_NONE和cv2.CHAIN_APPROX_SIMPLE得結(jié)果是這樣:
可以看出后者省出來(lái)很多計(jì)算空間。
對(duì)于cv2.drawContours( ):
r=cv2.drawContours(o, contours, contourIdx, color[, thickness])
- r :目標(biāo)圖像,直接修改目標(biāo)的像素點(diǎn),實(shí)現(xiàn)繪制。
- o :原始圖像
- contours :需要繪制的邊緣數(shù)組。
- contourIdx :需要繪制的邊緣索引,如果全部繪制則為 -1。
- color :繪制的顏色,為 BGR 格式的 Scalar 。
- thickness :可選,繪制的密度,即描繪輪廓時(shí)所用的畫筆粗細(xì)。
import cv2 import numpy as np o = cv2.imread('image\\boyun.png') gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) image,contours, hierarchy =cv2.findContours(binary,cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) co=o.copy() r=cv2.drawContours(co,contours,-1,(0,0,255),1) cv2.imshow("original",o) cv2.imshow("result",r) cv2.waitKey() cv2.destroyAllWindows()
對(duì)于多個(gè)輪廓,我們也可以指定畫哪一個(gè)輪廓。
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) image,contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) co=o.copy() r=cv2.drawContours(co,contours,0,(0,0,255),6)
如果設(shè)置成-1,那么就是全部顯示!??!
輪廓近似
當(dāng)輪廓有毛刺的時(shí)候,我們希望能夠做輪廓近似,將毛刺去掉,大體思想是將曲線用直線代替,但是有個(gè)長(zhǎng)度的閾值需要自己設(shè)定。
我們還可以做額外的操作,比如外接矩形,外接圓,外界橢圓等等。
img = cv2.imread('contours.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) cnt = contours[0] x,y,w,h = cv2.boundingRect(cnt) img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) cv_show(img,'img') area = cv2.contourArea(cnt) x, y, w, h = cv2.boundingRect(cnt) rect_area = w * h extent = float(area) / rect_area print ('輪廓面積與邊界矩形比',extent) 外接圓 (x,y),radius = cv2.minEnclosingCircle(cnt) center = (int(x),int(y)) radius = int(radius) img = cv2.circle(img,center,radius,(0,255,0),2) cv_show(img,'img')
模板匹配和卷積原理很像,模板在原圖像上從原點(diǎn)開始滑動(dòng),計(jì)算模板與(圖像被模板覆蓋的地方)的差別程度,這個(gè)差別程度的計(jì)算方法在opencv里有六種,然后將每次計(jì)算的結(jié)果放入一個(gè)矩陣?yán)?,作為結(jié)果輸出。假如原圖形是AXB大小,而模板是axb大小,則輸出結(jié)果的矩陣是(A-a+1)x(B-b+1)。
- TM_SQDIFF:計(jì)算平方不同,計(jì)算出來(lái)的值越小,越相關(guān)
- TM_CCORR:計(jì)算相關(guān)性,計(jì)算出來(lái)的值越大,越相關(guān)
- TM_CCOEFF:計(jì)算相關(guān)系數(shù),計(jì)算出來(lái)的值越大,越相關(guān)
- TM_SQDIFF_NORMED:計(jì)算歸一化平方不同,計(jì)算出來(lái)的值越接近0,越相關(guān)
- TM_CCORR_NORMED:計(jì)算歸一化相關(guān)性,計(jì)算出來(lái)的值越接近1,越相關(guān)
- TM_CCOEFF_NORMED:計(jì)算歸一化相關(guān)系數(shù),計(jì)算出來(lái)的值越接近1,越相關(guān)
到此這篇關(guān)于python OpenCV圖像金字塔的文章就介紹到這了,更多相關(guān)python OpenCV金字塔內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實(shí)現(xiàn)按當(dāng)前日期(年、月、日)創(chuàng)建多級(jí)目錄的方法
這篇文章主要介紹了Python 按當(dāng)前日期(年、月、日)創(chuàng)建多級(jí)目錄的方法,實(shí)現(xiàn)代碼很簡(jiǎn)單,需要的朋友可以參考下2018-04-04python3中類的重點(diǎn)與難點(diǎn):類屬性和實(shí)例屬性的區(qū)別說(shuō)明
這篇文章主要介紹了python3中類的重點(diǎn)與難點(diǎn):類屬性和實(shí)例屬性的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Python requests上傳文件實(shí)現(xiàn)步驟
這篇文章主要介紹了Python requests上傳文件實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09Matlab中關(guān)于argmax、argmin函數(shù)的使用解讀
這篇文章主要介紹了Matlab中關(guān)于argmax、argmin函數(shù)的使用解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12