在很多計算機視覺的應用裡,都需要處理大量的資料,耗時費記憶體。為了減少處理時間,降低記憶體占用,需要使用物體的緊湊表示,也就是物體的骨架(skeleton)。
物體的骨架要求能夠表示這個形狀的結構,刪除多餘的畫素點,下圖是字母b的骨架。
這篇文章介紹一種使用opencv庫計算生態骨架(morphological skeleton)的方法,這種方法簡單實用。維基百科中有介紹說通過腐蝕和膨脹操作就可以獲得morphological skeleton,偽**如下:
img = ...;
while (not_empty(img))
說明一下演算法的原理
每次迭代影象都會再次腐蝕,經過腐蝕後物體變得更窄細
對腐蝕後影象做開運算,經過開運算後處理後,影象有些畫素會被刪除,這些被刪除的畫素其實是骨架的一部分
將刪除的畫素,新增到骨架圖上
當腐蝕後影象沒有畫素後後,就結束跌打,這時候或生成的骨架圖也就完整了
import os
import numpy as np
import cv2
import sys
im_path = sys.argv[1]
im = cv2.imread(im_path, 0)
if im is none:
print im_path, " not exist"
sys.exit()
ret, im = cv2.threshold(im, 127, 255, cv2.thresh_binary)
element = cv2.getstructuringelement(cv2.morph_cross, (3,3))
skel = np.zeros(im.shape, np.uint8)
temp = np.zeros(im.shape, np.uint8)
i = 0
while true:
cv2.imshow('im %d'%(i), im)
#取開運算過程中消失的畫素,這些畫素便是skeleton的一部分
temp = cv2.morphologyex(im, cv2.morph_open, element)
temp = cv2.bitwise_not(temp)
temp = cv2.bitwise_and(im, temp)
cv2.imshow('skeleton part %d'%(i,), temp)
#將刪除的畫素新增skeleton圖中
skel = cv2.bitwise_or(skel, temp)
#再次腐蝕原圖,為進一步尋找skeleton做準備
im = cv2.erode(im, element)
min_val, max_val, min_loc, max_loc = cv2.minmaxloc(im)
#print min_val, max_val, min_loc, max_loc
if max_val==.0:
break
i += 1
cv2.imshow('skeleton', skel)
cv2.waitkey()
實驗效果:
上圖中im0 -4表示每輪迭代是經過腐蝕後的,skeleton part 0-4表示經過開源獲得的骨架畫素,最後這些畫素組合在一起獲得骨架圖skeleton,很神奇的。
之前的實現裡,使用openning運算,開運算後有對原圖做了erode操作。實際上opening運算是erode + dilate,所以進行了兩次腐蝕,有重複計算,可以只使用一次。另外minmaxloc()函式函式效率比countnonzero()要慢。優化後**如下:
import os
import numpy as np
import cv2
import sys
im_path = sys.argv[1]
im = cv2.imread(im_path, 0)
if im is none:
print im_path, " not exist"
sys.exit()
ret, im = cv2.threshold(im, 127, 255, cv2.thresh_binary)
element = cv2.getstructuringelement(cv2.morph_cross, (3,3))
skel = np.zeros(im.shape, np.uint8)
erode = np.zeros(im.shape, np.uint8)
temp = np.zeros(im.shape, np.uint8)
i = 0
while true:
cv2.imshow('im %d'%(i), im)
erode = cv2.erode(im,element)
temp = cv2.dilate(erode, element)
#消失的畫素是skeleton的一部分
temp = cv2.subtract(im, temp)
cv2.imshow('skeleton part %d' %(i,), temp)
skel = cv2.bitwise_or(skel, temp)
im = erode.copy()
if cv2.countnonzero(im)== 0:
break;
i += 1
cv2.imshow('skeleton', skel)
cv2.waitkey()
OpenCV中的HOG SVM物體分類
opencv官方的svm 在 在看到一段還不錯的 結構清楚,雖然注釋比較少,但很有參考價值,於是我新增了一些注釋,看著更舒服。廢話少說,直接上 cpp view plaincopyprint include cv.h include highgui.h include stdafx.h includ...
OpenCV中的HOG SVM物體分類
opencv官方的svm 在 在看到一段還不錯的 結構清楚,雖然注釋比較少,但很有參考價值,於是我新增了一些注釋,看著更舒服。廢話少說,直接上 include cv.h include highgui.h include stdafx.h include include include includ...
簡化的輪廓來獲取骨架資訊
這段時間對輪廓的分析與研究,主要目的是想提供乙個準確的人體骨架模型來方便特徵點的自動標註,第一步對於輪廓中u形端點的取得是很準確的,第二步我參考了孫怡的利用條形模型尋找條帶的演算法尋找四肢與軀幹,但是效果很差,主要原因是在向量化後的輪廓並不不是易於處理的結果,出現形態學操作後的干擾雜訊。不得不考慮其...