深入解析opencv骨架提取的算法步驟
前言
個(gè)人感覺骨架提取提取的就是開運(yùn)算過程的不可逆。
一.算法步驟
1.算法步驟
首先上一下比較官方的算法步驟:
1.獲得原圖像的首地址及圖像的寬和高,并設(shè)置循環(huán)標(biāo)志1
2.用結(jié)構(gòu)元素腐蝕原圖像,并保存腐蝕結(jié)果
3.設(shè)置循環(huán)標(biāo)志為0,如果腐蝕結(jié)果中有一個(gè)點(diǎn)為255,即原圖像尚未被完全腐蝕成空集,則將循環(huán)標(biāo)志設(shè)為1.
4.用結(jié)構(gòu)元素對(duì)腐蝕后的圖像進(jìn)行開運(yùn)算(消除小的白色區(qū)域),并求取腐蝕運(yùn)算與開運(yùn)算的差(得到消除的白色區(qū)域)
5.用[4]中求得的結(jié)果與之前求得的骨架進(jìn)行并集運(yùn)算,以獲得本次循環(huán)求得的骨架
6.把本次循環(huán)中保存的腐蝕結(jié)果賦值給原圖像
7.重復(fù)步驟[2]-[6],直到將原圖像腐蝕成空集為止。
最終求得的骨架就是結(jié)果。
2.分析
作者的理解是這樣的:
輸入:img(二值圖) 輸出:out(和img一樣shape的圖像,初始化是全0) while img中有像素值為255(在這個(gè)循環(huán)里面,一直腐蝕我們的二值圖,直到全部為黑色): 腐蝕img圖像 對(duì)img開運(yùn)算 img2=開運(yùn)算前的圖像減去開運(yùn)算后的圖像 out+=img2 輸出out
首先說一下開運(yùn)算,就是對(duì)圖像先做腐蝕再做膨脹。上面一個(gè)核心點(diǎn)就是這一步(img2=開運(yùn)算前的圖像減去開運(yùn)算后的圖像),在這里為什么說個(gè)人感覺骨架提取提取的就是開運(yùn)算過程的不可逆呢?我們對(duì)這個(gè)開運(yùn)算過程分析一下:
1.假如開運(yùn)算后的圖像和開運(yùn)算前的圖像不一樣,比如下面這張圖片:
可以看到這張圖片中白色的大部分都比較細(xì)小,我們對(duì)這張圖片做開運(yùn)算的時(shí)候,我們先腐蝕,很容易就讓一部分的白色的部分消失掉,那么這個(gè)白色的部分消失掉之后對(duì)腐蝕后的圖片做膨脹消失的白色部分是膨脹不回來的。這些消失的部分就是開運(yùn)算過程中的不可逆的部分了。
然后我們?cè)诤竺?img2=開運(yùn)算前的圖像減去開運(yùn)算后的圖像),這一步當(dāng)中就是得到了開運(yùn)算中消失的那些白色部分了,這一部分就是開運(yùn)算過程中的不可逆的部分,然后將它疊加到out上。
然后我們通過對(duì)圖像不斷的腐蝕,開運(yùn)算,得到了所有這些圖像中在開運(yùn)算中不可逆的部分,就得到了我們的骨架了。
2.假如開運(yùn)算后的圖像和開運(yùn)算前的圖像不一樣,那這樣的話我們?cè)谶@一步(img2=開運(yùn)算前的圖像減去開運(yùn)算后的圖像)得到img2中的每一個(gè)元素就為0了,那在后面out+=img2這一步的時(shí)候就out相當(dāng)于不變,進(jìn)入下一步循環(huán)在繼續(xù)把白色部分腐蝕地更小,直到得到開運(yùn)算中出現(xiàn)了不可逆地部分再疊加到out上。
所以粗暴地來說,骨架提取就是對(duì)我們地前景區(qū)域,不斷地腐蝕,細(xì)化前景,直到將前景壓縮到細(xì)地不能再細(xì)了。我們的骨架提取提取的就是這一部分。
二.代碼實(shí)現(xiàn)
1.預(yù)處理
這里我們的圖片是以灰度圖片方式讀取進(jìn)來的,然后需要閾值處理轉(zhuǎn)換到二值圖。
然后我們的圖片可能會(huì)有一些其他的較大的噪聲的影響,我們首先對(duì)圖像先進(jìn)行腐蝕操作,手動(dòng)過濾掉一些濾波可能無法過濾的較大噪聲。
''' 用于挑選一個(gè)好的二值圖 ''' import cv2 import numpy as np import os def refine(img_path): img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) # thresh, img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) thresh, img = cv2.threshold(img, 50, 255, cv2.THRESH_BINARY) h, w = img.shape[0:2] #前景背景反轉(zhuǎn) for i in range(h): for j in range(w): if img[i, j] == 255: img[i, j] = 0 else: img[i, j] = 255 cv2.namedWindow("binary", 0) cv2.resizeWindow("binary", 640, 480) cv2.imshow('binary', img) dst = img.copy() num_erode = 0 while (True): if np.sum(dst) == 0: break kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) dst = cv2.erode(dst, kernel) cv2.namedWindow("z", 0) cv2.resizeWindow("z", 640, 480) cv2.imshow('z', dst) c = cv2.waitKey(0) if c == ord("q"): print("保存") cv2.imwrite("./refine.png", dst) break num_erode = num_erode + 1 if __name__ == '__main__': refine("input.png")
在這里需要注意的是我們對(duì)圖像進(jìn)行二值化可能會(huì)將我們的背景和前景反轉(zhuǎn),在這里我們需要反轉(zhuǎn)回來。否則的話把反轉(zhuǎn)的代碼注釋掉即可。
我的原圖如下:
然后經(jīng)過腐蝕的圖片如下:
2. 骨架提取實(shí)現(xiàn)
然后下面就是骨架提取的代碼了:
''' 骨架提取 ''' import cv2 import numpy as np #由于我們經(jīng)過之前的代碼轉(zhuǎn)換到了二值圖,所以這里不需要轉(zhuǎn)換 img = cv2.imread('refine.png', cv2.IMREAD_GRAYSCALE) dst = img.copy() skeleton = np.zeros(dst.shape, np.uint8) while (True): if np.sum(dst) == 0: break kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) dst = cv2.erode(dst, kernel, None, None, 1) open_dst = cv2.morphologyEx(dst, cv2.MORPH_OPEN, kernel) result = dst - open_dst skeleton = skeleton + result cv2.waitKey(1) cv2.namedWindow("result",0) cv2.resizeWindow("result",640,480) cv2.imshow('result', skeleton) cv2.imwrite("output.png",skeleton) cv2.waitKey(0) cv2.destroyAllWindows()
在這里我們可以通過開運(yùn)算的結(jié)果元大小來稍微調(diào)整一下提取的骨架粗細(xì)。
77開運(yùn)算結(jié)構(gòu)元提取的骨架如下:
55開運(yùn)算結(jié)構(gòu)元提取的骨架如下:
到此這篇關(guān)于深入解析opencv骨架提取的算法步驟的文章就介紹到這了,更多相關(guān)opencv骨架提取內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python將十六進(jìn)制值轉(zhuǎn)換為字符串的三種方法
這篇文章主要給大家介紹了關(guān)于python將十六進(jìn)制值轉(zhuǎn)換為字符串的三種方法,工作內(nèi)容的需要需求,經(jīng)常需要使用到字符同16進(jìn)制,以及各個(gè)進(jìn)制之間的轉(zhuǎn)換,需要的朋友可以參考下2023-07-07django美化后臺(tái)django-suit的安裝配置操作
這篇文章主要介紹了django美化后臺(tái)django-suit的安裝配置操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07Python安裝Imaging報(bào)錯(cuò):The _imaging C module is not installed問題解決
這篇文章主要介紹了Python安裝Imaging報(bào)錯(cuò):The _imaging C module is not installed問題解決方法,原來是PIL庫(kù)的庫(kù)文件沒有加到系統(tǒng)中導(dǎo)致老是提示這個(gè)錯(cuò)誤,需要的朋友可以參考下2014-08-08

python 網(wǎng)絡(luò)爬蟲初級(jí)實(shí)現(xiàn)代碼

python中文分詞,使用結(jié)巴分詞對(duì)python進(jìn)行分詞(實(shí)例講解)

Python+OpenCV實(shí)現(xiàn)圖像的全景拼接