日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

主动轮廓线模型Snake模型简介openCV中cvSnakeImage()函数代码分析

發(fā)布時間:2023/12/14 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 主动轮廓线模型Snake模型简介openCV中cvSnakeImage()函数代码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

主動輪廓線模型又稱為Snake模型,自Kass于1987年提出以來,已廣泛應(yīng)用于數(shù)字圖像分析和計算機視覺領(lǐng)域。由于Snake模型具有良好的提取和跟蹤特定區(qū)域內(nèi)目標輪廓的能力,因此非常適合于醫(yī)學(xué)圖像如CT和MR圖像的處理,以獲得特定器官及組織的輪廓。簡單的來講,Snake模型就是一條可變形的參數(shù)曲線及相應(yīng)的能量函數(shù),以最小化能量目標函數(shù)為目標,控制參數(shù)曲線變形,具有最小能量的閉合曲線就是目標輪廓。 Snake模型具有一些經(jīng)典方法所無法比擬的優(yōu)點:圖像數(shù)據(jù)、初始估計、目標輪廓及基于知識的約束統(tǒng)一于一個過程中;經(jīng)適當?shù)某跏蓟?#xff0c;它能自主地收斂于能量極小值狀態(tài);尺度空間中由初到精地極小化能量可以極大地擴展捕獲區(qū)域和降低復(fù)雜性。同時,Snake模型也有其自身的缺點:對初始位置敏感,需要依賴其他機制將Snake放置在感興趣的圖像特征附近;由于Snake模型的非凸性,它有可能收斂到局部極值點,甚至發(fā)散。

?

Snake模型稱為動態(tài)輪廓模型(Active Contour? Model)是Kass與1987年提出的,它對于在噪聲和對比度不敏感,能將目標從復(fù)雜背景中分割出來,并能有效的跟蹤目標的形變和非剛體的復(fù)雜運動而被廣泛用于圖像分割和物體跟蹤等圖像處理領(lǐng)域。

Snake主要原理是先提供待分割圖像的一個初始輪廓的位置,并對其定義個能量函數(shù),是輪廓沿能量降低的方向靠近。當能量函數(shù)達到最小的時候,提供的初始輪廓收斂到圖形中目標的真實輪廓。

Snake能量函數(shù)是有內(nèi)部能量函數(shù)和外部能量函數(shù)組成,內(nèi)部能量控制輪廓的平滑性和連續(xù)性,外部能量由圖像能量和約束能量組成,控制輪廓向著實際輪廓收斂,其中約束能量可根據(jù)具體的對象形態(tài)定義,使得snake具有很大的靈活性。

Snake模型發(fā)展10多年來,許多學(xué)者對于經(jīng)典的snake模型做了改進,提出各種改進的snake模型,其中梯度矢量流(Gradient Vector? Flow,GVF)模型擴大了經(jīng)典snake的外力作用范圍,加強了對目標凹輪廓邊緣的吸引力,提高了傳統(tǒng)的snake模型。

?

Snake模型主要研究的方面:

1.表示內(nèi)部能量的曲線演化??? 2.外力??? 3.能量最小化

Snake模型初始輪廓的選擇

由于snake模型對于初始位置比較敏感,因此要求初始輪廓盡可能的靠近真實輪廓,而當圖像邊緣模糊,目標比較復(fù)雜或與其他的物體靠的比較近時,其初始輪廓更不易確定。

現(xiàn)有的初始輪廓確定的方法有以下幾種:1.人工勾勒圖像的邊緣??? 2.序列圖像差分邊界??? 3.基于序列圖像的前一幀圖像邊界的預(yù)測? 4.基于傳統(tǒng)圖像分割結(jié)果進行邊界選取

分水嶺算法

分水嶺算法是由S.Beucher? F.Meyer最早引入圖像分割領(lǐng)域,它的基本思想是來源于測地學(xué)上的側(cè)線重構(gòu),其內(nèi)容是把圖像看做是測地學(xué)上的拓撲地貌。進行分水嶺模型計算的比較經(jīng)典的算法是L? Vincent提出的,在該算法中首先是對每個像素的灰度級進行從低到高排序,然后用等級對壘模擬淹沒,初始時,等級隊列中為淹沒的初始點,在從低到高實現(xiàn)淹沒的過程中,對每一個局部極小值在H階高度的影響域采用先進先出(FIFO)結(jié)構(gòu)進行判斷及標注,直到最后一個值被淹沒,從而正確劃分各個區(qū)域。

整個洪水淹沒的循環(huán)迭代過程可以通過以下兩個步驟表示:

分水嶺算法的優(yōu)點:

1.分水嶺算法對于圖像中由于像素差別較小而產(chǎn)生微弱邊緣具有良好的響應(yīng),可以得到封閉連續(xù)的邊緣,而且可以保證在照明,陰影等影響下分割邊緣的封閉性和連續(xù)性

分水嶺算法對于目標物體之間或者是目標物體同背景物體之間粘連的情況有較好的處理效果。能夠較好的分割這類目標物體。

3.圖像內(nèi)部的陰暗變化對于分水嶺算法影響較小,可以在一定程度上減小由于陰暗便哈帶來的圖像分割影響

與其他邊緣分割算子比較:

Canny算子可以很好的勾勒出物體的輪廓,過分的強調(diào)輪廓的特性,而沒有強調(diào)物體的輪廓必須是封閉的,在圖像中顯示的輪廓是不封閉的,物體內(nèi)部陰暗變化也被當做邊界檢測出來,形成大量的偽邊緣。

分水嶺算法分割得到的輪廓曲線時連續(xù)封閉的,圖像內(nèi)部的陰暗變化沒有生成獨立的輪廓線。

Snake模型的缺陷:

對初始位置敏感,易陷入局部極值,無法收斂到輪廓深度凹陷部分,不具備自動拓撲變換功能等。

Snake模型的改進算法:

1.Cohen提出的氣球(balloon)理論模型:應(yīng)用壓力和高斯能力一起增大吸引范圍的方法,該壓力可使模型擴大或縮小,因此不再要求將模型初始化在所期望的對象邊界附近。在圖像的梯度力場上疊加氣球里,以使輪廓線作為一個整體進行膨脹或收縮,從而擴大了模型尋找圖像特證的范圍。

優(yōu)勢:對初始邊界不敏感????????????

存在的缺點:存在弱邊界,漏出邊界間隙等問題。

2.Xu提出梯度矢量流(GVF)概念,用GVF場代替經(jīng)典外力場,GVF場可以看做是對圖像梯度場得逼近,這不僅使模型捕捉的范圍得到了提高,而且能使活動輪廓進入凹陷區(qū)。

優(yōu)勢:有良好的收斂性,深入目標邊緣的凹陷區(qū)域???????????

存在的缺點:仍不能解決曲線的拓撲變化問題

局部優(yōu)化算法:

1.Amini提出基于動態(tài)規(guī)劃的snake算法。 2.變分法? 3.貪婪算法? 4.有限差分法?? 5.有限元法

全局優(yōu)化算法:

1.模擬退火???? 2.遺傳算法??? 3.神經(jīng)網(wǎng)絡(luò)

Snake模型的蟻群算法(Ant Colony Optimization)模型

蟻群算法是最近幾年有意大利學(xué)者M.Dorigo等人首次提出的一種新型的模擬進化算法,稱為蟻群系統(tǒng),蟻群算法通過候選解組成的群體的進化過程來尋求最優(yōu)解,該過程包括兩個基本階段:適應(yīng)階段和協(xié)同工作階段,算法本身采用正反饋原理,加快了進化過程,不易陷入局部最優(yōu)解,而且個體之間不斷進行信息交流和傳遞,有利于對解空間的進一步探索,因此有很強的發(fā)展解的能力。

?

?

Snake的進化模型

1.McInerney 提出一種拓撲自適應(yīng)snake模型(Topology Adaptive? Snake,T-Snake)

該算法基于仿射細胞圖像分解(Affine Cell Image? Decomposition,ACID)先在待分割圖像上加以三角網(wǎng)格,然后在圖像區(qū)域的適當位置做一條初始曲線,最后取曲線與網(wǎng)格的交點作為snake的初始離散點,其第i個snake的離散點的坐標為其中,相鄰兩點,之間由一條彈性樣條連接而成

由于T-Snake模型可借助三角形網(wǎng)格和網(wǎng)格點的特征函數(shù)來確定邊界三角形,可促使snake模型演化過程中的分裂和合并,從而保證了其具有能夠處理拓撲結(jié)果復(fù)雜圖像的能力,因此能夠很好的滿足醫(yī)學(xué)圖像拓撲結(jié)果復(fù)雜的特點。此算法用于腦部MR切片有良好的性能。

2.雙T-Snake模型

雙T-Snake模型(Dual-T-Snakes)是在T-Snake模型的基礎(chǔ)上產(chǎn)生的,其主要思想是采用內(nèi)外兩個初始輪廓,其中一個輪廓從目標外向內(nèi)收縮和分裂,另一個輪廓從目標內(nèi)部向外膨脹,兩個初始輪廓可以離目標邊界較遠,迭代的過程中對能量較大的輪廓增加驅(qū)動力,使其靠近與之相對應(yīng)的輪廓,直到連個輪廓收斂到同一個為止

3.Loop? Snake 模型

Loop? Snake模型是一種加強了拓撲控制的T-Snake模型,這種方法的關(guān)鍵集中在曲線的每一步進化中都要形成循環(huán),其基本思想是,確保圖像輪廓曲線精確地線性地映射到適當?shù)姆诸愔?#xff0c;然后在額外的記過loop-Tree的幫助下,盡可能少的時間內(nèi)運用已經(jīng)被snake探究的循環(huán)來決定是否進行區(qū)域劃分,這種模型的實質(zhì)是對T-Snake模型的一種改進。由于加強了拓撲控制,使得Loop Snake模型既可以忽略背景中強噪聲又可以在演化過程中進行多次分裂。

4.連續(xù)snake模型

在Snake模型中,輪廓曲線由一條給定容許誤差范圍的光滑曲線組成,相對于離散snake來說,連續(xù)snake模型所需要的控制點少,比離散的更具優(yōu)越性。

5.B-Snake模型

B-Snake模型是通過B樣條曲線來定義的,其輪廓曲線由各曲線段光滑相連而成,每一個曲線段都是由一個給定次數(shù)多項式表示,這種多項式是B樣條曲度函數(shù)的一種線性組合,并以控制點為系數(shù)。在有些B-Snake模型中并沒有明確應(yīng)用內(nèi)部能量,這是因為B樣條本身就含有內(nèi)部能量,snake輪廓曲線只受外力影響著圖像邊緣移動。可用于對圖像切片分割區(qū)域的描述與跟蹤而用于器官的三維重建。

?

應(yīng)用snake的優(yōu)勢:由于生物或人體組織解剖結(jié)構(gòu)的復(fù)雜性,以及軟組織形狀的易變性,那些僅依賴于圖像本身的灰度,紋理屬性等低層次視覺屬性來進行分割的圖像分割方法難以獲得理想的分割效果,因此醫(yī)學(xué)圖像分割迫切需要有一種靈活的框架,能將基于圖像本身低層次視覺屬性(邊緣,紋理,灰度,色彩)和人們對于待分割目標的知識經(jīng)驗,如目標形狀的描述,亮度,色彩的經(jīng)驗統(tǒng)計,醫(yī)生的經(jīng)驗等,可以一種有機的方式整合起來,得到待分割區(qū)域的完整表達。

?

Opencv中snake函數(shù)解析及例子:

?

[cpp]?view plain?copy

  • /*M///?
  • //?
  • //??IMPORTANT:?READ?BEFORE?DOWNLOADING,?COPYING,?INSTALLING?OR?USING.?
  • //?
  • //??By?downloading,?copying,?installing?or?using?the?software?you?agree?to?this?license.?
  • //??If?you?do?not?agree?to?this?license,?do?not?download,?install,?
  • //??copy?or?use?the?software.?
  • //?
  • //?
  • //????????????????????????Intel?License?Agreement?
  • //????????????????For?Open?Source?Computer?Vision?Library?
  • //?
  • //?Copyright?(C)?2000,?Intel?Corporation,?all?rights?reserved.?
  • //?Third?party?copyrights?are?property?of?their?respective?owners.?
  • //?
  • //?Redistribution?and?use?in?source?and?binary?forms,?with?or?without?modification,?
  • //?are?permitted?provided?that?the?following?conditions?are?met:?
  • //?
  • //???*?Redistribution's?of?source?code?must?retain?the?above?copyright?notice,?
  • //?????this?list?of?conditions?and?the?following?disclaimer.?
  • //?
  • //???*?Redistribution's?in?binary?form?must?reproduce?the?above?copyright?notice,?
  • //?????this?list?of?conditions?and?the?following?disclaimer?in?the?documentation?
  • //?????and/or?other?materials?provided?with?the?distribution.?
  • //?
  • //???*?The?name?of?Intel?Corporation?may?not?be?used?to?endorse?or?promote?products?
  • //?????derived?from?this?software?without?specific?prior?written?permission.?
  • //?
  • //?This?software?is?provided?by?the?copyright?holders?and?contributors?"as?is"?and?
  • //?any?express?or?implied?warranties,?including,?but?not?limited?to,?the?implied?
  • //?warranties?of?merchantability?and?fitness?for?a?particular?purpose?are?disclaimed.?
  • //?In?no?event?shall?the?Intel?Corporation?or?contributors?be?liable?for?any?direct,?
  • //?indirect,?incidental,?special,?exemplary,?or?consequential?damages?
  • //?(including,?but?not?limited?to,?procurement?of?substitute?goods?or?services;?
  • //?loss?of?use,?data,?or?profits;?or?business?interruption)?however?caused?
  • //?and?on?any?theory?of?liability,?whether?in?contract,?strict?liability,?
  • //?or?tort?(including?negligence?or?otherwise)?arising?in?any?way?out?of?
  • //?the?use?of?this?software,?even?if?advised?of?the?possibility?of?such?damage.?
  • //?
  • //M*/??
  • #include?"_cv.h"??
  • ???
  • #define?_CV_SNAKE_BIG?2.e+38f??
  • #define?_CV_SNAKE_IMAGE?1??
  • #define?_CV_SNAKE_GRAD??2??
  • ???
  • ???
  • /*F///?
  • //????Name:??????icvSnake8uC1R?????
  • //????Purpose:???
  • //????Context:???
  • //????Parameters:?
  • //???????????????src?-?source?image,?
  • //???????????????srcStep?-?its?step?in?bytes,?
  • //???????????????roi?-?size?of?ROI,?
  • //???????????????pt?-?pointer?to?snake?points?array?
  • //???????????????n?-?size?of?points?array,?
  • //???????????????alpha?-?pointer?to?coefficient?of?continuity?energy,?
  • //???????????????beta?-?pointer?to?coefficient?of?curvature?energy,??
  • //???????????????gamma?-?pointer?to?coefficient?of?image?energy,??
  • //???????????????coeffUsage?-?if?CV_VALUE?-?alpha,?beta,?gamma?point?to?single?value?
  • //????????????????????????????if?CV_MATAY?-?point?to?arrays?
  • //???????????????criteria?-?termination?criteria.?
  • //???????????????scheme?-?image?energy?scheme?
  • //?????????????????????????if?_CV_SNAKE_IMAGE?-?image?intensity?is?energy?
  • //?????????????????????????if?_CV_SNAKE_GRAD??-?magnitude?of?gradient?is?energy?
  • //????Returns:???
  • //F*/??
  • ???
  • static?CvStatus??
  • icvSnake8uC1R(?unsigned?char?*src,???//原始圖像數(shù)據(jù)??
  • ???????????????int?srcStep,?????????//每行的字節(jié)數(shù)??
  • ???????????????CvSize?roi,?????????//圖像尺寸??
  • ???????????????CvPoint?*?pt,???????//輪廓點(變形對象)??
  • ???????????????int?n,????????????//輪廓點的個數(shù)??
  • ???????????????float?*alpha,???????//指向α的指針,α可以是單個值,也可以是與輪廓點個數(shù)一致的數(shù)組??
  • ???????????????float?*beta,????????//β的值,同α??
  • ???????????????float?*gamma,???????//γ的值,同α??
  • ???????????????int?coeffUsage,???//確定αβγ是用作單個值還是個數(shù)組??
  • ????????CvSize?win,???????//每個點用于搜索的最小的領(lǐng)域大小,寬度為奇數(shù)??
  • ?????????????CvTermCriteria?criteria,???//遞歸迭代終止的條件準則??
  • int?scheme?)?????????//確定圖像能量場的數(shù)據(jù)選擇,1為灰度,2為灰度梯度??
  • {??
  • ????int?i,?j,?k;??
  • ????int?neighbors?=?win.height?*?win.width;????//當前點領(lǐng)域中點的個數(shù)??
  • ???
  • ???//當前點的位置??
  • ????int?centerx?=?win.width?>>?1;????????????
  • ????int?centery?=?win.height?>>?1;???????????
  • ???
  • ????float?invn;????????//n?的倒數(shù)???
  • ????int?iteration?=?0;?????//迭代次數(shù)??
  • ????int?converged?=?0;??????//收斂標志,0為非收斂??
  • ??????
  • ??//能量??
  • ????float?*Econt;????//??
  • ????float?*Ecurv;???//輪廓曲線能量??
  • ????float?*Eimg;????//圖像能量??
  • ????float?*E;??????//??
  • ????
  • ???//αβγ的副本??
  • ????float?_alpha,?_beta,?_gamma;??
  • ???
  • ????/*#ifdef?GRAD_SNAKE?*/??
  • ????float?*gradient?=?NULL;??
  • ????uchar?*map?=?NULL;??
  • ????int?map_width?=?((roi.width?-?1)?>>?3)?+?1;??
  • ????int?map_height?=?((roi.height?-?1)?>>?3)?+?1;??
  • ????CvSepFilter?pX,?pY;??
  • ????#define?WTILE_SIZE?8??
  • ????#define?TILE_SIZE?(WTILE_SIZE?+?2)?????????
  • ????short?dx[TILE_SIZE*TILE_SIZE],?dy[TILE_SIZE*TILE_SIZE];??
  • ????CvMat?_dx?=?cvMat(?TILE_SIZE,?TILE_SIZE,?CV_16SC1,?dx?);??
  • ????CvMat?_dy?=?cvMat(?TILE_SIZE,?TILE_SIZE,?CV_16SC1,?dy?);??
  • ????CvMat?_src?=?cvMat(?roi.height,?roi.width,?CV_8UC1,?src?);??
  • ???
  • ????/*?inner?buffer?of?convolution?process?*/??
  • ????//char?ConvBuffer[400];??
  • ???
  • ????/*#endif?*/??
  • ???
  • ?????//檢點參數(shù)的合理性??
  • ????/*?check?bad?arguments?*/??
  • ????if(?src?==?NULL?)??
  • ????????return?CV_NULLPTR_ERR;??
  • ????if(?(roi.height?<=?0)?||?(roi.width?<=?0)?)??
  • ????????return?CV_BADSIZE_ERR;??
  • ????if(?srcStep?<?roi.width?)??
  • ????????return?CV_BADSIZE_ERR;??
  • ????if(?pt?==?NULL?)??
  • ????????return?CV_NULLPTR_ERR;??
  • ????if(?n?<?3?)?????????????????????????//輪廓點至少要三個??
  • ????????return?CV_BADSIZE_ERR;??
  • ????if(?alpha?==?NULL?)??
  • ????????return?CV_NULLPTR_ERR;??
  • ????if(?beta?==?NULL?)??
  • ????????return?CV_NULLPTR_ERR;??
  • ????if(?gamma?==?NULL?)??
  • ????????return?CV_NULLPTR_ERR;??
  • ????if(?coeffUsage?!=?CV_VALUE?&&?coeffUsage?!=?CV_ARRAY?)??
  • ????????return?CV_BADFLAG_ERR;??
  • ????if(?(win.height?<=?0)?||?(!(win.height?&?1)))???//鄰域搜索窗口得是奇數(shù)??
  • ????????return?CV_BADSIZE_ERR;??
  • ????if(?(win.width?<=?0)?||?(!(win.width?&?1)))??
  • ????????return?CV_BADSIZE_ERR;??
  • ???
  • ????invn?=?1?/?((float)?n);????????//輪廓點數(shù)n的倒數(shù),用于求平均???
  • ???
  • ????if(?scheme?==?_CV_SNAKE_GRAD?)??
  • {??
  • ?????//X方向上和Y方向上的Scoble梯度算子,用于求圖像的梯度,??
  • //處理的圖像最大尺寸為TILE_SIZE+2,此例為12,算子半長為3即{-3,-2,-1,0,1,2,3}??
  • //處理后的數(shù)據(jù)類型為16位符號數(shù),分別存放在_dx,_dy矩陣中,長度為10??
  • ????????pX.init_deriv(?TILE_SIZE+2,?CV_8UC1,?CV_16SC1,?1,?0,?3?);??
  • ????????pY.init_deriv(?TILE_SIZE+2,?CV_8UC1,?CV_16SC1,?0,?1,?3?);??
  • ???????//圖像梯度存放緩沖區(qū)??
  • ????????gradient?=?(float?*)?cvAlloc(?roi.height?*?roi.width?*?sizeof(?float?));??
  • ???
  • ????????if(?!gradient?)??
  • ????????????return?CV_OUTOFMEM_ERR;??
  • ???????//map用于標志相應(yīng)位置的分塊的圖像能量是否已經(jīng)求得??
  • ????????map?=?(uchar?*)?cvAlloc(?map_width?*?map_height?);??
  • ????????if(?!map?)??
  • ????????{??
  • ????????????cvFree(?&gradient?);??
  • ????????????return?CV_OUTOFMEM_ERR;??
  • ????????}??
  • ????????/*?clear?map?-?no?gradient?computed?*/??
  • ???????//清除map標志??
  • ????????memset(?(void?*)?map,?0,?map_width?*?map_height?);??
  • }??
  • //各種能量的存放處,取每點的鄰域的能量??
  • ????Econt?=?(float?*)?cvAlloc(?neighbors?*?sizeof(?float?));??
  • ????Ecurv?=?(float?*)?cvAlloc(?neighbors?*?sizeof(?float?));??
  • ????Eimg?=?(float?*)?cvAlloc(?neighbors?*?sizeof(?float?));??
  • ????E?=?(float?*)?cvAlloc(?neighbors?*?sizeof(?float?));??
  • ???//開始迭代??
  • ????while(?!converged?)????//收斂標志無效時進行??
  • ????{??
  • ????????float?ave_d?=?0;??//輪廓各點的平均距離??
  • ????????int?moved?=?0;??????//輪廓變形時,發(fā)生移動的數(shù)量??
  • ???
  • ????????converged?=?0;???????//標志未收斂??
  • ????????iteration++;????????//更新迭代次數(shù)+1??
  • ???
  • //計算輪廓中各點的平均距離??
  • ????????/*?compute?average?distance?*/??
  • ??????//從點0到點n-1的距離和??
  • ????????for(?i?=?1;?i?<?n;?i++?)??
  • ????????{??
  • ????????????int?diffx?=?pt[i?-?1].x?-?pt[i].x;??
  • ????????????int?diffy?=?pt[i?-?1].y?-?pt[i].y;??
  • ???
  • ????????????ave_d?+=?cvSqrt(?(float)?(diffx?*?diffx?+?diffy?*?diffy)?);???
  • ????????}??
  • ?????//再加上從點n-1到點0的距離,形成回路輪廓??
  • ????????ave_d?+=?cvSqrt(?(float)?((pt[0].x?-?pt[n?-?1].x)?*??
  • ??????????????????????????????????(pt[0].x?-?pt[n?-?1].x)?+??
  • ??????????????????????????????????(pt[0].y?-?pt[n?-?1].y)?*?(pt[0].y?-?pt[n?-?1].y)));??
  • ????//求平均,得出平均距離??
  • ????????ave_d?*=?invn;??
  • ????????/*?average?distance?computed?*/??
  • ???
  • ???
  • ??????//對于每個輪廓點進行特定循環(huán)迭代求解??
  • ????????for(?i?=?0;?i?<?n;?i++?)??
  • ????????{??
  • ????????????/*?Calculate?Econt?*/??
  • ??????????//初始化各個能量??
  • ????????????float?maxEcont?=?0;??
  • ????????????float?maxEcurv?=?0;??
  • ????????????float?maxEimg?=?0;??
  • ????????????float?minEcont?=?_CV_SNAKE_BIG;??
  • ????????????float?minEcurv?=?_CV_SNAKE_BIG;??
  • ????????????float?minEimg?=?_CV_SNAKE_BIG;??
  • ????????????float?Emin?=?_CV_SNAKE_BIG;??
  • ?????????//初始化變形后輪廓點的偏移量??
  • ????????????int?offsetx?=?0;??
  • ????????????int?offsety?=?0;??
  • ????????????float?tmp;??
  • ???
  • ????????//計算邊界??
  • ????????????/*?compute?bounds?*/??
  • ???????????//計算合理的搜索邊界,以防領(lǐng)域搜索超過ROI圖像的范圍??
  • ????????????int?left?=?MIN(?pt[i].x,?win.width?>>?1?);??
  • ????????????int?right?=?MIN(?roi.width?-?1?-?pt[i].x,?win.width?>>?1?);??
  • ????????????int?upper?=?MIN(?pt[i].y,?win.height?>>?1?);??
  • ????????????int?bottom?=?MIN(?roi.height?-?1?-?pt[i].y,?win.height?>>?1?);??
  • ??????????//初始化Econt??
  • ????????????maxEcont?=?0;??
  • ????????????minEcont?=?_CV_SNAKE_BIG;??
  • ?????????//在合理的搜索范圍內(nèi)進行Econt的計算??
  • ????????????for(?j?=?-upper;?j?<=?bottom;?j++?)??
  • ????????????{??
  • ????????????????for(?k?=?-left;?k?<=?right;?k++?)??
  • ????????????????{??
  • ????????????????????int?diffx,?diffy;??
  • ????????????????????float?energy;??
  • ?????????????//在輪廓點集的首尾相接處作相應(yīng)處理,求輪廓點差分??
  • ????????????????????if(?i?==?0?)??
  • ????????????????????{??
  • ????????????????????????diffx?=?pt[n?-?1].x?-?(pt[i].x?+?k);??
  • ????????????????????????diffy?=?pt[n?-?1].y?-?(pt[i].y?+?j);??
  • ????????????????????}??
  • ????????????????????else??
  • ?????????????//在其他地方作一般處理??
  • ???
  • ????????????????????{??
  • ????????????????????????diffx?=?pt[i?-?1].x?-?(pt[i].x?+?k);??
  • ????????????????????????diffy?=?pt[i?-?1].y?-?(pt[i].y?+?j);??
  • ????????????????????}??
  • ?????????????//將鄰域陳列坐標轉(zhuǎn)成Econt數(shù)組的下標序號,計算鄰域中每點的Econt??
  • ??????????????//Econt的值等于平均距離和此點和上一點的距離的差的絕對值(這是怎么來的?)??
  • ????????????????????Econt[(j?+?centery)?*?win.width?+?k?+?centerx]?=?energy?=??
  • ????????????????????????(float)?fabs(?ave_d?-??
  • ??????????????????????????????????????cvSqrt(?(float)?(diffx?*?diffx?+?diffy?*?diffy)?));??
  • ?????????????//求出所有鄰域點中的Econt的最大值和最小值??
  • ????????????????????maxEcont?=?MAX(?maxEcont,?energy?);??
  • ????????????????????minEcont?=?MIN(?minEcont,?energy?);??
  • ????????????????}??
  • ????????????}??
  • ???????????//求出鄰域點中最大值和最小值之差,并對所有的鄰域點的Econt進行標準歸一化,若最大值最小??
  • ???????????//相等,則鄰域中的點Econt全相等,Econt歸一化束縛為0??
  • ????????????tmp?=?maxEcont?-?minEcont;??
  • ????????????tmp?=?(tmp?==?0)???0?:?(1?/?tmp);??
  • ????????????for(?k?=?0;?k?<?neighbors;?k++?)??
  • ????????????{??
  • ????????????????Econt[k]?=?(Econt[k]?-?minEcont)?*?tmp;??
  • ????????????}??
  • ???
  • ???
  • ???????????//計算每點的Ecurv??
  • ????????????/*??Calculate?Ecurv?*/??
  • ????????????maxEcurv?=?0;??
  • ????????????minEcurv?=?_CV_SNAKE_BIG;??
  • ????????????for(?j?=?-upper;?j?<=?bottom;?j++?)??
  • ????????????{??
  • ????????????????for(?k?=?-left;?k?<=?right;?k++?)??
  • ????????????????{??
  • ????????????????????int?tx,?ty;??
  • ????????????????????float?energy;??
  • ????????????????????//第一個點的二階差分??
  • ????????????????????if(?i?==?0?)??
  • ????????????????????{??
  • ????????????????????????tx?=?pt[n?-?1].x?-?2?*?(pt[i].x?+?k)?+?pt[i?+?1].x;??
  • ????????????????????????ty?=?pt[n?-?1].y?-?2?*?(pt[i].y?+?j)?+?pt[i?+?1].y;??
  • ????????????????????}??
  • ???????????????????//最后一個點的二階差分??
  • ????????????????????else?if(?i?==?n?-?1?)??
  • ????????????????????{??
  • ????????????????????????tx?=?pt[i?-?1].x?-?2?*?(pt[i].x?+?k)?+?pt[0].x;??
  • ????????????????????????ty?=?pt[i?-?1].y?-?2?*?(pt[i].y?+?j)?+?pt[0].y;??
  • ????????????????????}??
  • ???????????????????//其余點的二階差分??
  • ????????????????????else??
  • ????????????????????{??
  • ????????????????????????tx?=?pt[i?-?1].x?-?2?*?(pt[i].x?+?k)?+?pt[i?+?1].x;??
  • ????????????????????????ty?=?pt[i?-?1].y?-?2?*?(pt[i].y?+?j)?+?pt[i?+?1].y;??
  • ????????????????????}??
  • ??????????????????//轉(zhuǎn)換坐標為數(shù)組序號,并求各點的Ecurv的值,二階差分后取平方??
  • ????????????????????Ecurv[(j?+?centery)?*?win.width?+?k?+?centerx]?=?energy?=??
  • ????????????????????????(float)?(tx?*?tx?+?ty?*?ty);??
  • ??????????????????//取最小的Ecurv和最大的Ecurv??
  • ????????????????????maxEcurv?=?MAX(?maxEcurv,?energy?);??
  • ????????????????????minEcurv?=?MIN(?minEcurv,?energy?);??
  • ????????????????}??
  • ????????????}??
  • ???????????????//對Ecurv進行標準歸一化??
  • ????????????tmp?=?maxEcurv?-?minEcurv;??
  • ????????????tmp?=?(tmp?==?0)???0?:?(1?/?tmp);??
  • ????????????for(?k?=?0;?k?<?neighbors;?k++?)??
  • ????????????{??
  • ????????????????Ecurv[k]?=?(Ecurv[k]?-?minEcurv)?*?tmp;??
  • ????????????}??
  • ???????????
  • ???????????//求Eimg??
  • ????????????/*?Calculate?Eimg?*/??
  • ????????????for(?j?=?-upper;?j?<=?bottom;?j++?)??
  • ????????????{??
  • ????????????????for(?k?=?-left;?k?<=?right;?k++?)??
  • ????????????????{??
  • ????????????????????float?energy;??
  • ???????????????//若采用灰度梯度數(shù)據(jù)??
  • ????????????????????if(?scheme?==?_CV_SNAKE_GRAD?)??
  • ????????????????????{??
  • ????????????????????????/*?look?at?map?and?check?status?*/??
  • ????????????????????????int?x?=?(pt[i].x?+?k)/WTILE_SIZE;??
  • ????????????????????????int?y?=?(pt[i].y?+?j)/WTILE_SIZE;??
  • ????????????????????????//若此處的圖像能量還沒有獲取,則對此處對應(yīng)的圖像分塊進行圖像能量的求解??
  • ????????????????????????if(?map[y?*?map_width?+?x]?==?0?)??
  • ????????????????????????{??
  • ????????????????????????????int?l,?m;?????????????????????????????
  • ???
  • ????????????????????????????/*?evaluate?block?location?*/??
  • ???????????????????????????//計算要進行梯度算子處理的圖像塊的位置??
  • ????????????????????????????int?upshift?=?y???1?:?0;??
  • ????????????????????????????int?leftshift?=?x???1?:?0;??
  • ????????????????????????????int?bottomshift?=?MIN(?1,?roi.height?-?(y?+?1)*WTILE_SIZE?);??
  • ????????????????????????????int?rightshift?=?MIN(?1,?roi.width?-?(x?+?1)*WTILE_SIZE?);??
  • ??????????????????????????//圖像塊的位置大小(由于原ROI不一定是8的倍數(shù),所以圖像塊會大小不一)??
  • ????????????????????????????CvRect?g_roi?=?{?x*WTILE_SIZE?-?leftshift,?y*WTILE_SIZE?-?upshift,??
  • ????????????????????????????????leftshift?+?WTILE_SIZE?+?rightshift,?upshift?+?WTILE_SIZE?+?bottomshift?};??
  • ????????????????????????????CvMat?_src1;??
  • ????????????????????????????cvGetSubArr(?&_src,?&_src1,?g_roi?);??//得到圖像塊的數(shù)據(jù)??
  • ????????????????????????????//分別對圖像的X方向和Y方向進行梯度算子??
  • ????????????????????????????pX.process(?&_src1,?&_dx?);??
  • ????????????????????????????pY.process(?&_src1,?&_dy?);??
  • ?????????????????????????//求分塊區(qū)域中的每個點的梯度??
  • ????????????????????????????for(?l?=?0;?l?<?WTILE_SIZE?+?bottomshift;?l++?)??
  • ????????????????????????????{??
  • ????????????????????????????????for(?m?=?0;?m?<?WTILE_SIZE?+?rightshift;?m++?)??
  • ????????????????????????????????{??
  • ????????????????????????????????????gradient[(y*WTILE_SIZE?+?l)?*?roi.width?+?x*WTILE_SIZE?+?m]?=??
  • ????????????????????????????????????????(float)?(dx[(l?+?upshift)?*?TILE_SIZE?+?m?+?leftshift]?*??
  • ?????????????????????????????????????????????????dx[(l?+?upshift)?*?TILE_SIZE?+?m?+?leftshift]?+??
  • ?????????????????????????????????????????????????dy[(l?+?upshift)?*?TILE_SIZE?+?m?+?leftshift]?*??
  • ?????????????????????????????????????????????????dy[(l?+?upshift)?*?TILE_SIZE?+?m?+?leftshift]);??
  • ????????????????????????????????}??
  • ????????????????????????????}??
  • ????????????????????????????//map相應(yīng)位置置1表示此處圖像能量已經(jīng)獲取??
  • ????????????????????????????map[y?*?map_width?+?x]?=?1;??
  • ????????????????????????}??
  • ??????????????????????//以梯度數(shù)據(jù)作為圖像能量??
  • ????????????????????????Eimg[(j?+?centery)?*?win.width?+?k?+?centerx]?=?energy?=??
  • ????????????????????????????gradient[(pt[i].y?+?j)?*?roi.width?+?pt[i].x?+?k];??
  • ????????????????????}??
  • ????????????????????else??
  • ????????????????????{??
  • ???????????????????????//以灰度作為圖像能量??
  • ????????????????????????Eimg[(j?+?centery)?*?win.width?+?k?+?centerx]?=?energy?=??
  • ????????????????????????????src[(pt[i].y?+?j)?*?srcStep?+?pt[i].x?+?k];??
  • ????????????????????}??
  • ???????????????????//獲得鄰域中最大和最小的圖像能量??
  • ????????????????????maxEimg?=?MAX(?maxEimg,?energy?);??
  • ????????????????????minEimg?=?MIN(?minEimg,?energy?);??
  • ????????????????}??
  • ????????????}??
  • ??????????????//Eimg的標準歸一化??
  • ????????????tmp?=?(maxEimg?-?minEimg);??
  • ????????????tmp?=?(tmp?==?0)???0?:?(1?/?tmp);??
  • ???
  • ????????????for(?k?=?0;?k?<?neighbors;?k++?)??
  • ????????????{??
  • ????????????????Eimg[k]?=?(minEimg?-?Eimg[k])?*?tmp;??
  • ????????????}??
  • ????????????//加入系數(shù)??
  • ????????????/*?locate?coefficients?*/??
  • ????????????if(?coeffUsage?==?CV_VALUE)??
  • ????????????{??
  • ????????????????_alpha?=?*alpha;??
  • ????????????????_beta?=?*beta;??
  • ????????????????_gamma?=?*gamma;??
  • ????????????}??
  • ????????????else??
  • ????????????{????????????????????
  • ????????????????_alpha?=?alpha[i];??
  • ????????????????_beta?=?beta[i];??
  • ????????????????_gamma?=?gamma[i];??
  • ????????????}??
  • ???
  • ????????????/*?Find?Minimize?point?in?the?neighbors?*/??
  • ????????????//求得每個鄰域點的Snake能量??
  • ????????????for(?k?=?0;?k?<?neighbors;?k++?)??
  • ????????????{??
  • ????????????????E[k]?=?_alpha?*?Econt[k]?+?_beta?*?Ecurv[k]?+?_gamma?*?Eimg[k];??
  • ????????????}??
  • ????????????Emin?=?_CV_SNAKE_BIG;??
  • ????????//獲取最小的能量,以及對應(yīng)的鄰域中的相對位置??
  • ????????????for(?j?=?-upper;?j?<=?bottom;?j++?)??
  • ????????????{??
  • ????????????????for(?k?=?-left;?k?<=?right;?k++?)??
  • ????????????????{??
  • ???
  • ????????????????????if(?E[(j?+?centery)?*?win.width?+?k?+?centerx]?<?Emin?)??
  • ????????????????????{??
  • ????????????????????????Emin?=?E[(j?+?centery)?*?win.width?+?k?+?centerx];??
  • ????????????????????????offsetx?=?k;??
  • ????????????????????????offsety?=?j;??
  • ????????????????????}??
  • ????????????????}??
  • ????????????}??
  • ?????????//如果輪廓點發(fā)生改變,則記得移動次數(shù)??
  • ????????????if(?offsetx?||?offsety?)??
  • ????????????{??
  • ????????????????pt[i].x?+=?offsetx;??
  • ????????????????pt[i].y?+=?offsety;??
  • ????????????????moved++;??
  • ????????????}??
  • ????????}??
  • ???
  • ??????//各個輪廓點迭代計算完成后,如果沒有移動的點了,則收斂標志位有效,停止迭代??
  • ????????converged?=?(moved?==?0);??
  • ?????//達到最大迭代次數(shù)時,收斂標志位有效,停止迭代??
  • ????????if(?(criteria.type?&?CV_TERMCRIT_ITER)?&&?(iteration?>=?criteria.max_iter)?)??
  • ????????????converged?=?1;??
  • ??//到大相應(yīng)精度時,停止迭代(與第一個條件有相同效果)??
  • ????????if(?(criteria.type?&?CV_TERMCRIT_EPS)?&&?(moved?<=?criteria.epsilon)?)??
  • ????????????converged?=?1;??
  • ????}??
  • ???
  • ??//釋放各個緩沖區(qū)??
  • ????cvFree(?&Econt?);??
  • ????cvFree(?&Ecurv?);??
  • ????cvFree(?&Eimg?);??
  • ????cvFree(?&E?);??
  • ???
  • ????if(?scheme?==?_CV_SNAKE_GRAD?)??
  • ????{??
  • ????????cvFree(?&gradient?);??
  • ????????cvFree(?&map?);??
  • ????}??
  • ????return?CV_OK;??
  • }??
  • ???
  • ???
  • CV_IMPL?void??
  • cvSnakeImage(?const?IplImage*?src,?CvPoint*?points,??
  • ??????????????int?length,?float?*alpha,??
  • ??????????????float?*beta,?float?*gamma,??
  • ??????????????int?coeffUsage,?CvSize?win,??
  • ??????????????CvTermCriteria?criteria,?int?calcGradient?)??
  • {??
  • ???
  • ????CV_FUNCNAME(?"cvSnakeImage"?);??
  • ???
  • ????__BEGIN__;??
  • ???
  • ????uchar?*data;??
  • ????CvSize?size;??
  • ????int?step;??
  • ???
  • ????if(?src->nChannels?!=?1?)??
  • ????????CV_ERROR(?CV_BadNumChannels,?"input?image?has?more?than?one?channel"?);??
  • ???
  • ????if(?src->depth?!=?IPL_DEPTH_8U?)??
  • ????????CV_ERROR(?CV_BadDepth,?cvUnsupportedFormat?);??
  • ???
  • ????cvGetRawData(?src,?&data,?&step,?&size?);??
  • ???
  • ????IPPI_CALL(?icvSnake8uC1R(?data,?step,?size,?points,?length,??
  • ??????????????????????????????alpha,?beta,?gamma,?coeffUsage,?win,?criteria,??
  • ??????????????????????????????calcGradient???_CV_SNAKE_GRAD?:?_CV_SNAKE_IMAGE?));??
  • ????__END__;??
  • }??
  • ???
  • /*?end?of?file?*/??
  • ???
  • ???
  • ???
  • ???
  • ???
  • 測試應(yīng)用程序??
  • ???
  • #include?"stdafx.h"??
  • #include?<iostream>??
  • #include?<string.h>??
  • #include?<cxcore.h>??
  • #include?<cv.h>??
  • #include?<highgui.h>??
  • #include?<fstream>??
  • ???
  • ???
  • IplImage?*image?=?0?;?//原始圖像??
  • IplImage?*image2?=?0?;?//原始圖像copy??
  • ???
  • using?namespace?std;??
  • int?Thresholdness?=?141;??
  • int?ialpha?=?20;??
  • int?ibeta=20;??
  • int?igamma=20;??
  • ???
  • void?onChange(int?pos)??
  • {??
  • ?????
  • ????if(image2)?cvReleaseImage(&image2);??
  • ????if(image)?cvReleaseImage(&image);??
  • ???
  • ????image2?=?cvLoadImage("grey.bmp",1);?//顯示圖片??
  • ????image=?cvLoadImage("grey.bmp",0);??
  • ???
  • ????cvThreshold(image,image,Thresholdness,255,CV_THRESH_BINARY);?//分割域值?????
  • ???
  • ????CvMemStorage*?storage?=?cvCreateMemStorage(0);??
  • ????CvSeq*?contours?=?0;??
  • ???
  • ????cvFindContours(?image,?storage,?&contours,?sizeof(CvContour),?//尋找初始化輪廓??
  • ????????CV_RETR_EXTERNAL?,?CV_CHAIN_APPROX_SIMPLE?);??
  • ???
  • ????if(!contours)?return?;??
  • ????int?length?=?contours->total;?????
  • ????if(length<10)?return?;??
  • ????CvPoint*?point?=?new?CvPoint[length];?//分配輪廓點??
  • ???
  • ????CvSeqReader?reader;??
  • ????CvPoint?pt=?cvPoint(0,0);;?????
  • ????CvSeq?*contour2=contours;?????
  • ???
  • ????cvStartReadSeq(contour2,?&reader);??
  • ????for?(int?i?=?0;?i?<?length;?i++)??
  • ????{??
  • ????????CV_READ_SEQ_ELEM(pt,?reader);??
  • ????????point[i]=pt;??
  • ????}??
  • ????cvReleaseMemStorage(&storage);??
  • ???
  • ????//顯示輪廓曲線??
  • ????for(int?i=0;i<length;i++)??
  • ????{??
  • ????????int?j?=?(i+1)%length;??
  • ????????cvLine(?image2,?point[i],point[j],CV_RGB(?0,?0,?255?),1,8,0?);??
  • ????}??
  • ???
  • ????float?alpha=ialpha/100.0f;??
  • ????float?beta=ibeta/100.0f;??
  • ????float?gamma=igamma/100.0f;??
  • ???
  • ????CvSize?size;??
  • ????size.width=3;??
  • ????size.height=3;??
  • ????CvTermCriteria?criteria;??
  • ????criteria.type=CV_TERMCRIT_ITER;??
  • ????criteria.max_iter=1000;??
  • ????criteria.epsilon=0.1;??
  • ????cvSnakeImage(?image,?point,length,&alpha,&beta,&gamma,CV_VALUE,size,criteria,0?);??
  • ???
  • ????//顯示曲線??
  • ????for(int?i=0;i<length;i++)??
  • ????{??
  • ????????int?j?=?(i+1)%length;??
  • ????????cvLine(?image2,?point[i],point[j],CV_RGB(?0,?255,?0?),1,8,0?);??
  • ????}??
  • ????delete?[]point;??
  • ???
  • }??
  • ???
  • int?main(int?argc,?char*?argv[])??
  • {??
  • ???
  • ?????
  • ????cvNamedWindow("win1",0);??
  • ????cvCreateTrackbar("Thd",?"win1",?&Thresholdness,?255,?onChange);??
  • ????cvCreateTrackbar("alpha",?"win1",?&ialpha,?100,?onChange);??
  • ????cvCreateTrackbar("beta",?"win1",?&ibeta,?100,?onChange);??
  • ????cvCreateTrackbar("gamma",?"win1",?&igamma,?100,?onChange);??
  • ????cvResizeWindow("win1",300,500);??
  • ????onChange(0);??
  • ???
  • ????for(;;)??
  • ????{??
  • ????????if(cvWaitKey(40)==27)?break;??
  • ????????cvShowImage("win1",image2);??
  • ????}??
  • ?????
  • ????return?0;??
  • }?
  • ?

    ?

    ?

    本文由以下兩篇博客整理得到:

    http://blog.csdn.net/lbd2008/article/details/7180506

    http://chyyeng.blog.163.com/blog/static/16918230201272724529214/

    總結(jié)

    以上是生活随笔為你收集整理的主动轮廓线模型Snake模型简介openCV中cvSnakeImage()函数代码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。