影象的骨架似乎沒有嚴格的數學定義,可認為是影象細化(thinning)的產物(中軸可以看作一種骨架,其有嚴格的數學定義)。目前已經有許多細化演算法,這些演算法得到的骨架可能略有差異。本文實現了khalid sheed 的 k3m演算法。該演算法屬於迭代腐蝕邊界的一類演算法,該類演算法的思想是,假定從二值影象中物體的邊界處同時開始燃燒,物體就會被逐步細化,但在燃燒過程中要保證滿足一定條件的點被保留或者被「燒掉」,以確定燃燒結束後,剩下的最後一畫素寬的影象為影象的骨架。這些條件的確定沒有統一的標準,各個演算法採取了不同的方案。一般來講,為了滿足計算的速度要求和演算法的準確,迭代中演算法會對影象邊界上某點的3*3鄰域內進行檢查,判斷是否滿足要求。
k3m演算法在每次迭代中需要進行六次檢查
phase 0. 標記出影象的邊界,
phase 1. 如果該點的鄰域中有3個點(非零,以下皆如此)相鄰,刪除該點
phase 2. 如果該點的鄰域中有3或4個點相鄰,刪除該點。
phase 3. 如果該點的鄰域中有3,4,5個點相鄰,刪除該點。
phase 4. 如果該點的鄰域中有3,4,5,6個點相鄰,刪除該點。
phase 5. 如果該點的鄰域中有3,4,5,6,7個點相鄰,刪除該點。
phase 6. 剩餘的邊界點取消標記,如果phase 5中沒有點被修改,停止迭代,否則返回phase 0。
具體的步驟可以閱讀**:**中演算法實現的乙個小技巧是,對鄰域中的8個點的值看作二進位制,即二進位制編碼,這樣不同的值就對應鄰域中不同的狀態。迭代中通過計算即可判斷該點是否滿足條件,是否可以刪除。具體細節請移步閱讀**。
演算法的測試結果如下:
參考:[cpp]view plain
copy
#include
#include
#include
#include
#include
#include
using
std::vector;
vector
> getflags(
inta,
intlength)
; for
(int
i=0;i
} std::cout
vec;
} void
skeleton(cv::mat &input)
//input-binary image
; int
a1=;
inta2=;
inta3=;
inta4=;
inta5=;
vector
> a0=getflags(a0,6);
vector
> a1=getflags(a1,1);
vector
> a2=getflags(a2,2);
vector
> a3=getflags(a3,3);
vector
> a4=getflags(a4,4);
vector
> a5=getflags(a5,5);
vectorborder;
bool
modify=
true
; int
neighbour[3][3]=,
,
};
introw=input.rows;
intcol=input.cols;
while
(modify)
} if(std::find(a0.begin(),a0.end(),weight)!=a0.end())
border.push_back(cv::point2i(m,n));
} }
//pharse 1
vector::iterator first=border.begin();
while
(first!=border.end())
} if(std::find(a1.begin(),a1.end(),weight)!=a1.end())
else
++first;
} //pharse2
first=border.begin();
while
(first!=border.end())
} if(std::find(a2.begin(),a2.end(),weight)!=a2.end())
else
++first;
} //pharse3
first=border.begin();
while
(first!=border.end())
} if(std::find(a3.begin(),a3.end(),weight)!=a3.end())
else
++first;
} //pharse4
first=border.begin();
while
(first!=border.end())
} if(std::find(a4.begin(),a4.end(),weight)!=a4.end())
else
++first;
} //pharse5
first=border.begin();
while
(first!=border.end())
} if(std::find(a5.begin(),a5.end(),weight)!=a5.end())
else
++first;
} //pharse6
border.clear();
} for
(int
m=1;m
} if(std::find(a0.begin(),a0.end(),weight)!=a0.end())
input.at(m,n)=0;;
} }
} int
main()
} cv::imshow("output"
,binaryimage);
cv::waitkey(0);
return
0;
}
提取骨架 細化
bool iscontourp int x,int y,iplimage src img int linebytes src img widthstep byte lpptr byte src img imagedata linebytes y x p 2 lpptr linebytes true ...
骨架提取演算法應用
1 引言 根據個人理解,骨架提取 顧名思義 就是根據各個連通區域,將其抽離出與其輪廓近似的單畫素表示形態。以便於直觀觀察 影象的後繼處理。因此可以將其視為影象處理中的預處理,其操作是基於二值圖。為了更好的提取影象骨架,必要時需要對影象進行相應的預處理 比如去噪 濾波 形態學變換等 我的應用主要集中在...
視覺組學習內容 Zhang Suen骨架提取演算法
封裝 這是視覺組dalao給大家布置的學期末學習任務。因為之前沒有接觸過linux,環境也沒有配置好,對很多操作不夠熟悉,做這個任務從頭到尾大約花了兩天合計15個小時的時間,中間還問過dalao兩個小時左右的問題 此處給大佬比心 雖然和大佬說的三個小時相去甚遠但是最後還是趕在ddl之前完成了任務。總...