msImageProcessor.cpp 145 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711
  1. /*******************************************************
  2. Mean Shift Analysis Library
  3. =============================================
  4. The mean shift library is a collection of routines
  5. that use the mean shift algorithm. Using this algorithm,
  6. the necessary output will be generated needed
  7. to analyze a given input set of data.
  8. Mean Shift Image Processor Class:
  9. ================================
  10. The following class inherits from the mean shift library
  11. in order to perform the specialized tasks of image
  12. segmentation and filtering.
  13. The definition of the Mean Shift Image Processor Class
  14. is provided below. Its prototype is provided in
  15. 'msImageProcessor.h'.
  16. The theory is described in the papers:
  17. D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature
  18. space analysis.
  19. C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision.
  20. and they are is available at:
  21. http://www.caip.rutgers.edu/riul/research/papers/
  22. Implemented by Chris M. Christoudias, Bogdan Georgescu
  23. ********************************************************/
  24. #ifdef NICE_USELIB_OPENMP
  25. #include <omp.h>
  26. #endif
  27. //include image processor class prototype
  28. #include "msImageProcessor.h"
  29. //include needed libraries
  30. #include <math.h>
  31. #include <stdio.h>
  32. #include <assert.h>
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <iostream>
  36. using namespace std;
  37. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  38. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  39. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  40. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  41. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  42. /*/\/\/\/\/\/\/\/\/\/\/\/\*/
  43. /* Constructor/Destructor */
  44. /*\/\/\/\/\/\/\/\/\/\/\/\/*/
  45. /*******************************************************/
  46. /*Class Constructor */
  47. /*******************************************************/
  48. /*Post: */
  49. /* The msImageProcessor class has been properly */
  50. /* initialized. */
  51. /*******************************************************/
  52. msImageProcessor::msImageProcessor ( void )
  53. {
  54. clog << "[log] msImageProcessor::msImageProcessor: use Edison ";
  55. #ifdef NICE_USELIB_OPENMP
  56. clog << "parallel!" << endl;
  57. omp_set_dynamic ( 0 );
  58. #else
  59. clog << "seriell!" << endl;
  60. #endif
  61. //intialize basin of attraction structure
  62. //used by the filtering algorithm
  63. modeTable = NULL;
  64. pointList = NULL;
  65. pointCount = 0;
  66. //initialize region list
  67. regionList = NULL;
  68. //initialize output structures...
  69. msRawData = NULL;
  70. labels = NULL;
  71. modes = NULL;
  72. modePointCounts = NULL;
  73. regionCount = 0;
  74. //intialize temporary buffers used for
  75. //performing connected components
  76. indexTable = NULL;
  77. LUV_data = NULL;
  78. //initialize region adjacency matrix
  79. raList = NULL;
  80. freeRAList = NULL;
  81. raPool = NULL;
  82. //intialize visit table to having NULL entries
  83. visitTable = NULL;
  84. //initialize epsilon such that transitive closure
  85. //does not take edge strength into consideration when
  86. //fusing regions of similar color
  87. epsilon = 1.0;
  88. //initialize class state to indicate that
  89. //an output data structure has not yet been
  90. //created...
  91. class_state.OUTPUT_DEFINED = false;
  92. //Changed by Sushil from 1.0 to 0.1, 11/11/2008
  93. LUV_treshold = 0.1;
  94. }
  95. /*******************************************************/
  96. /*Class Destructor */
  97. /*******************************************************/
  98. /*Post: */
  99. /* The msImageProcessor class has been properly */
  100. /* destroyed. */
  101. /*******************************************************/
  102. msImageProcessor::~msImageProcessor ( void )
  103. {
  104. //de-allocate memory
  105. if ( class_state.OUTPUT_DEFINED ) DestroyOutput();
  106. if ( regionList ) delete regionList;
  107. regionList = NULL;
  108. //done.
  109. }
  110. /*/\/\/\/\/\/\/\/\/\/\/\/\/\*/
  111. /* Input Image Declaration */
  112. /*\/\/\/\/\/\/\/\/\/\/\/\/\/*/
  113. /*******************************************************/
  114. /*Define Image */
  115. /*******************************************************/
  116. /*Uploads an image into the image segmenter class to */
  117. /*be segmented. */
  118. /*******************************************************/
  119. /*Pre: */
  120. /* - data_ is a one dimensional array of unsigned */
  121. /* char RGB vectors */
  122. /* - type is the type of the image: COLOR or */
  123. /* GREYSCALE */
  124. /* - height_ and width_ define the dimension of */
  125. /* the image */
  126. /* - if the image is of type GREYSCALE then */
  127. /* data containes only one number per pixel */
  128. /* location, where a pixel location is defined */
  129. /* by the index into the data array */
  130. /*Post: */
  131. /* - the image specified has been uploaded into */
  132. /* the image segmenter class to be segmented. */
  133. /*******************************************************/
  134. void msImageProcessor::DefineImage ( byte *data_, imageType type, int height_, int width_ )
  135. {
  136. /* Ein neuer LUV-Vektor wird angelegt. In diesen wird der Inhalt von data_ gespeichert. Kann data_ auch mit 'const' Qualifier definiert werden ?
  137. */
  138. //obtain image dimension from image type
  139. int dim;
  140. if ( type == COLOR )
  141. dim = 3;
  142. else
  143. dim = 1;
  144. //perfor rgb to luv conversion
  145. int i;
  146. float *luv = new float [height_*width_*dim];
  147. if ( dim == 1 )
  148. {
  149. for ( i = 0; i < height_*width_; i++ )
  150. luv[i] = ( float ) ( data_[i] );
  151. }
  152. else
  153. {
  154. for ( i = 0; i < height_*width_; i++ )
  155. {
  156. RGBtoLUV ( &data_[dim*i], &luv[dim*i] );
  157. }
  158. }
  159. //define input defined on a lattice using mean shift base class
  160. DefineLInput ( luv, height_, width_, dim );
  161. //Define a default kernel if it has not been already
  162. //defined by user
  163. if ( !h )
  164. {
  165. //define default kernel paramerters...
  166. kernelType k[2] = {Uniform, Uniform};
  167. int P[2] = {2, N};
  168. float tempH[2] = {1.0 , 1.0};
  169. //define default kernel in mean shift base class
  170. DefineKernel ( k, tempH, P, 2 );
  171. }
  172. //de-allocate memory
  173. delete [] luv;
  174. //done.
  175. return;
  176. }
  177. void msImageProcessor::DefineBgImage ( byte* data_, imageType type, int height_, int width_ )
  178. {
  179. //obtain image dimension from image type
  180. int dim;
  181. if ( type == COLOR )
  182. dim = 3;
  183. else
  184. dim = 1;
  185. //perform texton classification
  186. int i;
  187. float *luv = new float [height_*width_*dim];
  188. if ( dim == 1 )
  189. {
  190. for ( i = 0; i < height_*width_; i++ )
  191. luv[i] = ( float ) ( data_[i] );
  192. }
  193. else
  194. {
  195. for ( i = 0; i < height_*width_; i++ )
  196. RGBtoLUV ( &data_[dim*i], &luv[dim*i] );
  197. }
  198. //define input defined on a lattice using mean shift base class
  199. DefineLInput ( luv, height_, width_, dim );
  200. //Define a default kernel if it has not been already
  201. //defined by user
  202. if ( !h )
  203. {
  204. //define default kernel paramerters...
  205. kernelType k[2] = {Uniform, Uniform};
  206. int P[2] = {2, N};
  207. float tempH[2] = {1.0 , 1.0};
  208. //define default kernel in mean shift base class
  209. DefineKernel ( k, tempH, P, 2 );
  210. }
  211. //de-allocate memory
  212. delete [] luv;
  213. //done.
  214. return;
  215. }
  216. /*/\/\/\/\/\/\/\/\*/
  217. /* Weight Map */
  218. /*\/\/\/\/\/\/\/\/*/
  219. /*******************************************************/
  220. /*Set Weight Map */
  221. /*******************************************************/
  222. /*Populates the weight map with specified edge */
  223. /*strengths. */
  224. /*******************************************************/
  225. /*Pre: */
  226. /* - wm is a floating point array of size */
  227. /* (height x width) specifying for each pixel */
  228. /* edge strength. */
  229. /* - eps is a threshold used to fuse similar */
  230. /* regions during transitive closure. */
  231. /*Post: */
  232. /* - wm has been used to populate the weight */
  233. /* map. */
  234. /* - the threshold used during transitive closure */
  235. /* is taken as eps. */
  236. /*******************************************************/
  237. void msImageProcessor::SetWeightMap ( float *wm, float eps )
  238. {
  239. //initlaize confmap using wm
  240. SetLatticeWeightMap ( wm );
  241. //set threshold value
  242. if ( ( epsilon = eps ) < 0 )
  243. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "SetWeightMap", ( char* ) "Threshold is negative." );
  244. //done.
  245. return;
  246. }
  247. /*******************************************************/
  248. /*Remove Weight Map */
  249. /*******************************************************/
  250. /*Removes the weight map. */
  251. /*******************************************************/
  252. /*Post: */
  253. /* - the weight map has been removed. */
  254. /* - if a weight map did not exist NO error */
  255. /* is flagged. */
  256. /*******************************************************/
  257. void msImageProcessor::RemoveWeightMap ( void )
  258. {
  259. //remove confmap
  260. RemoveLatticeWeightMap();
  261. //set threshold value to zero
  262. epsilon = 0;
  263. //done.
  264. return;
  265. }
  266. /*/\/\/\/\/\/\/\/\/\*/
  267. /* Image Filtering */
  268. /*\/\/\/\/\/\/\/\/\/*/
  269. /*******************************************************/
  270. /*Filter */
  271. /*******************************************************/
  272. /*Performs mean shift filtering on the specified input */
  273. /*image using a user defined kernel. */
  274. /*******************************************************/
  275. /*Pre: */
  276. /* - the user defined kernel used to apply mean */
  277. /* shift filtering to the defined input image */
  278. /* has spatial bandwidth sigmaS and range band- */
  279. /* width sigmaR */
  280. /* - speedUpLevel determines whether or not the */
  281. /* filtering should be optimized for faster */
  282. /* execution: a value of NO_SPEEDUP turns this */
  283. /* optimization off and a value SPEEDUP turns */
  284. /* this optimization on */
  285. /* - a data set has been defined */
  286. /* - the height and width of the lattice has been */
  287. /* specified using method DefineLattice() */
  288. /*Post: */
  289. /* - mean shift filtering has been applied to the */
  290. /* input image using a user defined kernel */
  291. /* - the filtered image is stored in the private */
  292. /* data members of the msImageProcessor class. */
  293. /*******************************************************/
  294. void msImageProcessor::Filter ( int sigmaS, float sigmaR, SpeedUpLevel speedUpLevel )
  295. {
  296. //Check Class consistency...
  297. //check:
  298. // (1) if this operation is consistent
  299. // (2) if kernel was created
  300. // (3) if data set is defined
  301. // (4) if the dimension of the kernel agrees with that
  302. // of the defined data set
  303. // if not ... flag an error!
  304. classConsistencyCheck ( N + 2, true );
  305. if ( ErrorStatus == EL_ERROR )
  306. return;
  307. //If the algorithm has been halted, then exit
  308. if ( ( ErrorStatus = msSys.Progress ( ( float ) ( 0.0 ) ) ) == EL_HALT )
  309. {
  310. return;
  311. }
  312. //If the image has just been read then allocate memory
  313. //for and initialize output data structure used to store
  314. //image modes and their corresponding regions...
  315. if ( class_state.OUTPUT_DEFINED == false )
  316. {
  317. InitializeOutput();
  318. //check for errors...
  319. if ( ErrorStatus == EL_ERROR )
  320. return;
  321. }
  322. //****************** Allocate Memory ******************
  323. //Allocate memory for basin of attraction mode structure...
  324. if ( ( ! ( modeTable = new unsigned char [L] ) ) || ( ! ( pointList = new int [L] ) ) )
  325. {
  326. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Allocate", ( char* ) "Not enough memory." );
  327. return;
  328. }
  329. //start timer
  330. #ifdef PROMPT
  331. double timer;
  332. msSys.StartTimer();
  333. #endif
  334. //*****************************************************
  335. // Parallelisieren !!!
  336. //filter image according to speedup level...
  337. switch ( speedUpLevel )
  338. {
  339. //no speedup...
  340. case NO_SPEEDUP:
  341. //NonOptimizedFilter((float)(sigmaS), sigmaR); break;
  342. NewNonOptimizedFilter ( ( float ) ( sigmaS ), sigmaR );
  343. break;
  344. //medium speedup
  345. case MED_SPEEDUP:
  346. //OptimizedFilter1((float)(sigmaS), sigmaR); break;
  347. NewOptimizedFilter1 ( ( float ) ( sigmaS ), sigmaR );
  348. break;
  349. //high speedup
  350. case HIGH_SPEEDUP:
  351. //OptimizedFilter2((float)(sigmaS), sigmaR); break;
  352. NewOptimizedFilter2 ( ( float ) ( sigmaS ), sigmaR );
  353. break;
  354. // new speedup
  355. }
  356. //****************** Deallocate Memory ******************
  357. //de-allocate memory used by basin of attraction mode structure
  358. delete [] modeTable;
  359. delete [] pointList;
  360. //re-initialize structure
  361. modeTable = NULL;
  362. pointList = NULL;
  363. pointCount = 0;
  364. //*******************************************************
  365. //If the algorithm has been halted, then de-allocate the output
  366. //and exit
  367. if ( ( ErrorStatus = msSys.Progress ( ( float ) ( 0.8 ) ) ) == EL_HALT )
  368. {
  369. DestroyOutput();
  370. return;
  371. }
  372. //Label image regions, also if segmentation is not to be
  373. //performed use the resulting classification structure to
  374. //calculate the image boundaries...
  375. /*
  376. //copy msRawData into LUV_data, rounding each component of each
  377. //LUV value stored by msRawData to the nearest integer
  378. int i;
  379. for(i = 0; i < L*N; i++)
  380. {
  381. if(msRawData[i] < 0)
  382. LUV_data[i] = (int)(msRawData[i] - 0.5);
  383. else
  384. LUV_data[i] = (int)(msRawData[i] + 0.5);
  385. }
  386. */
  387. // Parallelisieren !!!
  388. int i;
  389. for ( i = 0; i < L*N; i++ )
  390. {
  391. LUV_data[i] = msRawData[i];
  392. }
  393. #ifdef PROMPT
  394. timer = msSys.ElapsedTime();
  395. printf ( ( char* ) "(%6.2f sec)\nConnecting regions ...", timer );
  396. msSys.StartTimer();
  397. #endif
  398. //Perform connecting (label image regions) using LUV_data
  399. Connect();
  400. #ifdef PROMPT
  401. timer = msSys.ElapsedTime();
  402. printf ( ( char* ) "done. (%6.2f seconds, numRegions = %6d)\n", timer, regionCount );
  403. msSys.StartTimer();
  404. #endif
  405. //done.
  406. return;
  407. }
  408. /*/\/\/\/\/\/\/\/\/\/\/\*/
  409. /* Image Region Fusing */
  410. /*\/\/\/\/\/\/\/\/\/\/\/*/
  411. /*******************************************************/
  412. /*Fuse Regions */
  413. /*******************************************************/
  414. /*Fuses the regions of a filtered image. */
  415. /*******************************************************/
  416. /*Pre: */
  417. /* - the range radius is specified by sigmaR */
  418. /* - minRegion is the minimum point density that */
  419. /* a region may have in the resulting segment- */
  420. /* ed image */
  421. /* - a data set has been defined */
  422. /* - the height and width of the lattice has been */
  423. /* specified using method DefineLattice() */
  424. /*Post: */
  425. /* - the image regions have been fused. */
  426. /* - if an result is stored by this class then */
  427. /* this result is used as input to this method. */
  428. /* - if no result is stored by this class, */
  429. /* the input image defined by calling the */
  430. /* method DefineImage is used. */
  431. /*******************************************************/
  432. void msImageProcessor::FuseRegions ( float sigmaS, int minRegion )
  433. {
  434. //Check Class consistency...
  435. //check:
  436. // (1) if this operation is consistent
  437. // (2) if kernel was created
  438. // (3) if data set is defined
  439. // (4) if the dimension of the kernel agrees with that
  440. // of the defined data set
  441. // if not ... flag an error!
  442. classConsistencyCheck ( N + 2, true );
  443. if ( ErrorStatus == EL_ERROR )
  444. return;
  445. //Check to see if the algorithm is to be halted, if so then
  446. //destroy output and exit
  447. if ( ( ErrorStatus = msSys.Progress ( ( float ) ( 0.8 ) ) ) == EL_HALT )
  448. {
  449. if ( class_state.OUTPUT_DEFINED ) DestroyOutput();
  450. return;
  451. }
  452. //obtain sigmaS (make sure it is not zero or negative, if not
  453. //flag an error)
  454. if ( ( h[1] = sigmaS ) <= 0 )
  455. {
  456. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "FuseRegions", ( char* ) "The feature radius must be greater than or equal to zero." );
  457. return;
  458. }
  459. //if output has not yet been generated then classify the input
  460. //image regions to be fused...
  461. if ( ! ( class_state.OUTPUT_DEFINED ) )
  462. {
  463. //Initialize output data structure used to store
  464. //image modes and their corresponding regions...
  465. InitializeOutput();
  466. //check for errors...
  467. if ( ErrorStatus == EL_ERROR )
  468. return;
  469. //copy data into LUV_data used to classify
  470. //image regions
  471. /*
  472. int i;
  473. for(i = 0; i < L*N; i++)
  474. {
  475. if(data[i] < 0)
  476. LUV_data[i] = (int)(data[i] - 0.5);
  477. else
  478. LUV_data[i] = (int)(data[i] + 0.5);
  479. }
  480. */
  481. int i;
  482. for ( i = 0; i < L*N; i++ )
  483. {
  484. LUV_data[i] = data[i];
  485. }
  486. #ifdef PROMPT
  487. printf ( ( char* ) "Connecting regions ..." );
  488. msSys.StartTimer();
  489. #endif
  490. //Perform connecting (label image regions) using LUV_data
  491. Connect();
  492. //check for errors
  493. if ( ErrorStatus == EL_ERROR )
  494. return;
  495. #ifdef PROMPT
  496. double timer = msSys.ElapsedTime();
  497. printf ( ( char* ) "done. (%6.2f seconds, numRegions = %6d)\n", timer, regionCount );
  498. #endif
  499. }
  500. //Check to see if the algorithm is to be halted, if so then
  501. //destroy output and exit
  502. if ( ( ErrorStatus = msSys.Progress ( ( float ) ( 0.85 ) ) ) == EL_HALT )
  503. {
  504. DestroyOutput();
  505. return;
  506. }
  507. #ifdef PROMPT
  508. printf ( ( char* ) "Applying transitive closure..." );
  509. msSys.StartTimer();
  510. #endif
  511. //allocate memory visit table
  512. visitTable = new unsigned char [L];
  513. //Apply transitive closure iteratively to the regions classified
  514. //by the RAM updating labels and modes until the color of each neighboring
  515. //region is within sqrt(rR2) of one another.
  516. rR2 = ( float ) ( h[1] * h[1] * 0.25 );
  517. TransitiveClosure();
  518. int oldRC = regionCount;
  519. int deltaRC, counter = 0;
  520. do {
  521. TransitiveClosure();
  522. deltaRC = oldRC - regionCount;
  523. oldRC = regionCount;
  524. counter++;
  525. } while ( ( deltaRC <= 0 ) && ( counter < 10 ) );
  526. //de-allocate memory for visit table
  527. delete [] visitTable;
  528. visitTable = NULL;
  529. //Check to see if the algorithm is to be halted, if so then
  530. //destroy output and region adjacency matrix and exit
  531. if ( ( ErrorStatus = msSys.Progress ( ( float ) ( 1.0 ) ) ) == EL_HALT )
  532. {
  533. DestroyRAM();
  534. DestroyOutput();
  535. return;
  536. }
  537. #ifdef PROMPT
  538. double timer = msSys.ElapsedTime();
  539. printf ( ( char* ) "done. (%6.2f seconds, numRegions = %6d)\nPruning spurious regions ...", timer, regionCount );
  540. msSys.StartTimer();
  541. #endif
  542. //Prune spurious regions (regions whose area is under
  543. //minRegion) using RAM
  544. Prune ( minRegion );
  545. #ifdef PROMPT
  546. timer = msSys.ElapsedTime();
  547. printf ( ( char* ) "done. (%6.2f seconds, numRegions = %6d)\n", timer, regionCount );
  548. msSys.StartTimer();
  549. #endif
  550. //Check to see if the algorithm is to be halted, if so then
  551. //destroy output and region adjacency matrix and exit
  552. if ( ( ErrorStatus = msSys.Progress ( ( float ) ( 1.0 ) ) ) == EL_HALT )
  553. {
  554. DestroyRAM();
  555. DestroyOutput();
  556. return;
  557. }
  558. //de-allocate memory for region adjacency matrix
  559. DestroyRAM();
  560. //output to msRawData
  561. int i, j, label;
  562. for ( i = 0; i < L; i++ )
  563. {
  564. label = labels[i];
  565. for ( j = 0; j < N; j++ )
  566. {
  567. msRawData[N*i+j] = modes[N*label+j];
  568. }
  569. }
  570. //done.
  571. return;
  572. }
  573. /*/\/\/\/\/\/\/\/\/\/\*/
  574. /* Image Segmentation */
  575. /*\/\/\/\/\/\/\/\/\/\/*/
  576. /*******************************************************/
  577. /*Segment */
  578. /*******************************************************/
  579. /*Segments the defined image. */
  580. /*******************************************************/
  581. /*Pre: */
  582. /* - sigmaS and sigmaR are the spatial and range */
  583. /* radii of the search window respectively */
  584. /* - minRegion is the minimum point density that */
  585. /* a region may have in the resulting segment- */
  586. /* ed image */
  587. /* - speedUpLevel determines whether or not the */
  588. /* filtering should be optimized for faster */
  589. /* execution: a value of NO_SPEEDUP turns this */
  590. /* optimization off and a value SPEEDUP turns */
  591. /* this optimization on */
  592. /*Post: */
  593. /* - the defined image is segmented and the */
  594. /* resulting segmented image is stored in the */
  595. /* private data members of the image segmenter */
  596. /* class. */
  597. /* - any regions whose point densities are less */
  598. /* than or equal to minRegion have been pruned */
  599. /* from the segmented image. */
  600. /*******************************************************/
  601. void msImageProcessor::Segment ( int sigmaS, float sigmaR, int minRegion, SpeedUpLevel speedUpLevel )
  602. {
  603. //make sure kernel is properly defined...
  604. if ( ( !h ) || ( kp < 2 ) )
  605. {
  606. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Segment", ( char* ) "Kernel corrupt or undefined." );
  607. return;
  608. }
  609. //Apply mean shift to data set using sigmaS and sigmaR...
  610. Filter ( sigmaS, sigmaR, speedUpLevel );
  611. //check for errors
  612. if ( ErrorStatus == EL_ERROR )
  613. return;
  614. //check to see if the system has been halted, if so exit
  615. if ( ErrorStatus == EL_HALT )
  616. return;
  617. //Check to see if the algorithm is to be halted, if so then
  618. //destroy output and exit
  619. if ( ( ErrorStatus = msSys.Progress ( ( float ) ( 0.85 ) ) ) == EL_HALT )
  620. {
  621. DestroyOutput();
  622. return;
  623. }
  624. #ifdef PROMPT
  625. printf ( ( char* ) "Applying transitive closure..." );
  626. msSys.StartTimer();
  627. #endif
  628. //allocate memory visit table
  629. visitTable = new unsigned char [L];
  630. //Apply transitive closure iteratively to the regions classified
  631. //by the RAM updating labels and modes until the color of each neighboring
  632. //region is within sqrt(rR2) of one another.
  633. rR2 = ( float ) ( h[1] * h[1] * 0.25 );
  634. TransitiveClosure();
  635. int oldRC = regionCount;
  636. int deltaRC, counter = 0;
  637. do {
  638. TransitiveClosure();
  639. deltaRC = oldRC - regionCount;
  640. oldRC = regionCount;
  641. counter++;
  642. } while ( ( deltaRC <= 0 ) && ( counter < 10 ) );
  643. //de-allocate memory for visit table
  644. delete [] visitTable;
  645. visitTable = NULL;
  646. //Check to see if the algorithm is to be halted, if so then
  647. //destroy output and regions adjacency matrix and exit
  648. if ( ( ErrorStatus = msSys.Progress ( ( float ) ( 0.95 ) ) ) == EL_HALT )
  649. {
  650. DestroyRAM();
  651. DestroyOutput();
  652. return;
  653. }
  654. #ifdef PROMPT
  655. double timer = msSys.ElapsedTime();
  656. printf ( ( char* ) "done. (%6.2f seconds, numRegions = %6d).\nPruning spurious regions\t... ", timer, regionCount );
  657. msSys.StartTimer();
  658. #endif
  659. //Prune spurious regions (regions whose area is under
  660. //minRegion) using RAM
  661. Prune ( minRegion );
  662. #ifdef PROMPT
  663. timer = msSys.ElapsedTime();
  664. printf ( ( char* ) "done. (%6.2f seconds, numRegions = %6d)\nPruning spurious regions ...", timer, regionCount );
  665. msSys.StartTimer();
  666. #endif
  667. //Check to see if the algorithm is to be halted, if so then
  668. //destroy output and regions adjacency matrix and exit
  669. if ( ( ErrorStatus = msSys.Progress ( 1.0 ) ) == EL_HALT )
  670. {
  671. DestroyRAM();
  672. DestroyOutput();
  673. return;
  674. }
  675. //de-allocate memory for region adjacency matrix
  676. DestroyRAM();
  677. // Parallelisieren !!!
  678. //output to msRawData
  679. int j, i, label;
  680. for ( i = 0; i < L; i++ )
  681. {
  682. label = labels[i];
  683. for ( j = 0; j < N; j++ )
  684. {
  685. msRawData[N*i+j] = modes[N*label+j];
  686. }
  687. }
  688. //done.
  689. return;
  690. }
  691. /*/\/\/\/\/\/\/\/\/\/\/\/\*/
  692. /* Data Space Conversion */
  693. /*\/\/\/\/\/\/\/\/\/\/\/\/*/
  694. /*******************************************************/
  695. /*RGB To LUV */
  696. /*******************************************************/
  697. /*Converts an RGB vector to LUV. */
  698. /* */
  699. /*See: */
  700. /* G. Wyszecki and W.S. Stiles: Color Science: */
  701. /* Concepts and Methods, Quantitative Data and */
  702. /* Formulae, Wiley, New York, 1982. */
  703. /*******************************************************/
  704. /*Pre: */
  705. /* - rgbVal is an unsigned char array containing */
  706. /* the RGB vector */
  707. /* - luvVal is a floating point array containing */
  708. /* the resulting LUV vector */
  709. /*Post: */
  710. /* - rgbVal has been converted to LUV and the */
  711. /* result has been stored in luvVal. */
  712. /*******************************************************/
  713. void msImageProcessor::RGBtoLUV ( byte *rgbVal, float *luvVal )
  714. {
  715. //delcare variables
  716. double x, y, z, L0, u_prime, v_prime, constant;
  717. //convert RGB to XYZ...
  718. x = XYZ[0][0] * rgbVal[0] + XYZ[0][1] * rgbVal[1] + XYZ[0][2] * rgbVal[2];
  719. y = XYZ[1][0] * rgbVal[0] + XYZ[1][1] * rgbVal[1] + XYZ[1][2] * rgbVal[2];
  720. z = XYZ[2][0] * rgbVal[0] + XYZ[2][1] * rgbVal[1] + XYZ[2][2] * rgbVal[2];
  721. //convert XYZ to LUV...
  722. //compute L*
  723. L0 = y / ( 255.0 * Yn );
  724. if ( L0 > Lt )
  725. luvVal[0] = ( float ) ( 116.0 * ( pow ( L0, 1.0 / 3.0 ) ) - 16.0 );
  726. else
  727. luvVal[0] = ( float ) ( 903.3 * L0 );
  728. //compute u_prime and v_prime
  729. constant = x + 15 * y + 3 * z;
  730. if ( constant != 0 )
  731. {
  732. u_prime = ( 4 * x ) / constant;
  733. v_prime = ( 9 * y ) / constant;
  734. }
  735. else
  736. {
  737. u_prime = 4.0;
  738. v_prime = 9.0 / 15.0;
  739. }
  740. //compute u* and v*
  741. luvVal[1] = ( float ) ( 13 * luvVal[0] * ( u_prime - Un_prime ) );
  742. luvVal[2] = ( float ) ( 13 * luvVal[0] * ( v_prime - Vn_prime ) );
  743. //done.
  744. return;
  745. }
  746. /*******************************************************/
  747. /*LUV To RGB */
  748. /*******************************************************/
  749. /*Converts an LUV vector to RGB. */
  750. /*******************************************************/
  751. /*Pre: */
  752. /* - luvVal is a floating point array containing */
  753. /* the LUV vector */
  754. /* - rgbVal is an unsigned char array containing */
  755. /* the resulting RGB vector */
  756. /*Post: */
  757. /* - luvVal has been converted to RGB and the */
  758. /* result has been stored in rgbVal. */
  759. /*******************************************************/
  760. //define inline rounding function...
  761. inline int my_round ( double in_x )
  762. {
  763. if ( in_x < 0 )
  764. return ( int ) ( in_x - 0.5 );
  765. else
  766. return ( int ) ( in_x + 0.5 );
  767. }
  768. void msImageProcessor::LUVtoRGB ( float *luvVal, byte *rgbVal )
  769. {
  770. //declare variables...
  771. int r, g, b;
  772. double x, y, z, u_prime, v_prime;
  773. //perform conversion
  774. if ( luvVal[0] < 0.1 )
  775. r = g = b = 0;
  776. else
  777. {
  778. //convert luv to xyz...
  779. if ( luvVal[0] < 8.0 )
  780. y = Yn * luvVal[0] / 903.3;
  781. else
  782. {
  783. y = ( luvVal[0] + 16.0 ) / 116.0;
  784. y *= Yn * y * y;
  785. }
  786. u_prime = luvVal[1] / ( 13 * luvVal[0] ) + Un_prime;
  787. v_prime = luvVal[2] / ( 13 * luvVal[0] ) + Vn_prime;
  788. x = 9 * u_prime * y / ( 4 * v_prime );
  789. z = ( 12 - 3 * u_prime - 20 * v_prime ) * y / ( 4 * v_prime );
  790. //convert xyz to rgb...
  791. //[r, g, b] = RGB*[x, y, z]*255.0
  792. r = my_round ( ( RGB[0][0] * x + RGB[0][1] * y + RGB[0][2] * z ) * 255.0 );
  793. g = my_round ( ( RGB[1][0] * x + RGB[1][1] * y + RGB[1][2] * z ) * 255.0 );
  794. b = my_round ( ( RGB[2][0] * x + RGB[2][1] * y + RGB[2][2] * z ) * 255.0 );
  795. //check bounds...
  796. if ( r < 0 ) r = 0;
  797. if ( r > 255 ) r = 255;
  798. if ( g < 0 ) g = 0;
  799. if ( g > 255 ) g = 255;
  800. if ( b < 0 ) b = 0;
  801. if ( b > 255 ) b = 255;
  802. }
  803. //assign rgb values to rgb vector rgbVal
  804. rgbVal[0] = r;
  805. rgbVal[1] = g;
  806. rgbVal[2] = b;
  807. //done.
  808. return;
  809. }
  810. /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
  811. /* Filtered and Segmented Image Output */
  812. /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/
  813. /*******************************************************/
  814. /*Get Raw Data */
  815. /*******************************************************/
  816. /*The output image data is returned. */
  817. /*******************************************************/
  818. /*Pre: */
  819. /* - outputImageData is a pre-allocated floating */
  820. /* point array used to store the filtered or */
  821. /* segmented image pixels. */
  822. /*Post: */
  823. /* - the filtered or segmented image data is */
  824. /* stored by outputImageData. */
  825. /*******************************************************/
  826. void msImageProcessor::GetRawData ( float *outputImageData )
  827. {
  828. //make sure that outputImageData is not NULL
  829. if ( !outputImageData )
  830. {
  831. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "GetRawData", ( char* ) "Output image data buffer is NULL." );
  832. return;
  833. }
  834. //copy msRawData to outputImageData
  835. int i;
  836. for ( i = 0; i < L*N; i++ )
  837. outputImageData[i] = msRawData[i];
  838. //done.
  839. return;
  840. }
  841. /*******************************************************/
  842. /*Get Results */
  843. /*******************************************************/
  844. /*The output image is returned. */
  845. /*******************************************************/
  846. /*Pre: */
  847. /* - outputImage is a pre-allocated unsinged char */
  848. /* array used to store the filtered or segment- */
  849. /* ed image pixels */
  850. /*Post: */
  851. /* - the filtered or segmented image is stored by */
  852. /* outputImage. */
  853. /*******************************************************/
  854. void msImageProcessor::GetResults ( byte *outputImage )
  855. {
  856. //make sure that outpuImage is not NULL
  857. if ( !outputImage )
  858. {
  859. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "GetResults", ( char* ) "Output image buffer is NULL." );
  860. return;
  861. }
  862. //if the image type is GREYSCALE simply
  863. //copy it over to the segmentedImage
  864. if ( N == 1 )
  865. {
  866. //copy over msRawData to segmentedImage checking
  867. //bounds
  868. int i, pxValue;
  869. for ( i = 0; i < L; i++ )
  870. {
  871. //get value
  872. pxValue = ( int ) ( msRawData[i] + 0.5 );
  873. //store into segmented image checking bounds...
  874. if ( pxValue < 0 )
  875. outputImage[i] = ( byte ) ( 0 );
  876. else if ( pxValue > 255 )
  877. outputImage[i] = ( byte ) ( 255 );
  878. else
  879. outputImage[i] = ( byte ) ( pxValue );
  880. }
  881. }
  882. else if ( N == 3 )
  883. {
  884. //otherwise convert msRawData from LUV to RGB
  885. //storing the result in segmentedImage
  886. int i;
  887. for ( i = 0; i < L; i++ )
  888. LUVtoRGB ( &msRawData[N*i], &outputImage[N*i] );
  889. }
  890. else
  891. //Unknown image type: should use MeanShift::GetRawData()...
  892. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "GetResults", ( char* ) "Unknown image type. Try using MeanShift::GetRawData()." );
  893. //done.
  894. return;
  895. }
  896. /*******************************************************/
  897. /*Get Boundaries */
  898. /*******************************************************/
  899. /*A region list containing the boundary locations for */
  900. /*each region is returned. */
  901. /*******************************************************/
  902. /*Post: */
  903. /* - a region list object containing the boundary */
  904. /* locations for each region is constructed */
  905. /* - the region list is returned */
  906. /* - NULL is returned if the image has not been */
  907. /* filtered or segmented */
  908. /*******************************************************/
  909. RegionList *msImageProcessor::GetBoundaries ( void )
  910. {
  911. //define bounds using label information
  912. if ( class_state.OUTPUT_DEFINED )
  913. DefineBoundaries();
  914. //return region list structure
  915. return regionList;
  916. }
  917. /*******************************************************/
  918. /*Get Regions */
  919. /*******************************************************/
  920. /*Returns the regions of the processed image. */
  921. /*******************************************************/
  922. /*Pre: */
  923. /* - labels_out is an integer array of size */
  924. /* height*width that stores for each pixel a */
  925. /* label relating that pixel to a corresponding */
  926. /* region in the image */
  927. /* - modes_out is floating point array of size */
  928. /* regionCount*N storing the feature component */
  929. /* of each region, and indexed by region label */
  930. /* - modePointCounts is an integer array of size */
  931. /* regionCount, indexed by region label, that */
  932. /* stores the area of each region in pixels. */
  933. /*Post: */
  934. /* If an input image was defined and processed, */
  935. /* - memory has been allocated for labels_out, */
  936. /* modes_out and MPC_out. */
  937. /* - labels_out, modes_out, and MPC_out have been */
  938. /* populated. */
  939. /* - the number of regions contained by the segm- */
  940. /* ented image has been returned. */
  941. /* If the image has not been defined or processed */
  942. /* or if there is in-sufficient memory, */
  943. /* - no memory has been allocated for labels_out, */
  944. /* modes_out, and MPC_out. */
  945. /* - -1 is returned for regionCount. */
  946. /*******************************************************/
  947. int msImageProcessor::GetRegions ( int **labels_out, float **modes_out, int **MPC_out )
  948. {
  949. //check to see if output has been defined for the given input image...
  950. if ( class_state.OUTPUT_DEFINED == false )
  951. return -1;
  952. //allocate memory for labels_out, modes_out and MPC_out based
  953. //on output storage structure
  954. int *labels_ = *labels_out, *MPC_out_ = *MPC_out;
  955. float *modes_ = *modes_out;
  956. if ( ! ( labels_ = new int [L] ) )
  957. {
  958. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "GetRegions", ( char* ) "Not enough memory." );
  959. return -1;
  960. }
  961. if ( ! ( modes_ = new float [regionCount*N] ) )
  962. {
  963. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "GetRegions", ( char* ) "Not enough memory." );
  964. return -1;
  965. }
  966. if ( ! ( MPC_out_ = new int [regionCount] ) )
  967. {
  968. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "GetRegions", ( char* ) "Not enough memory." );
  969. return -1;
  970. }
  971. //populate labels_out with image labels
  972. int i;
  973. for ( i = 0; i < L; i++ )
  974. labels_[i] = labels[i];
  975. //populate modes_out and MPC_out with the color and point
  976. //count of each region
  977. for ( i = 0; i < regionCount*N; i++ )
  978. modes_[i] = modes[i];
  979. for ( i = 0; i < regionCount; i++ )
  980. MPC_out_[i] = modePointCounts[i];
  981. //done. Return the number of regions resulting from filtering or segmentation.
  982. return regionCount;
  983. }
  984. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  985. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  986. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PRIVATE METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  987. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  988. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  989. /*/\/\/\/\/\/\/\/\/\*/
  990. /* Image Filtering */
  991. /*\/\/\/\/\/\/\/\/\/*/
  992. /*******************************************************/
  993. /*Non Optimized Filter */
  994. /*******************************************************/
  995. /*Performs mean shift filtering on the specified input */
  996. /*image using a user defined kernel. */
  997. /*******************************************************/
  998. /*Pre: */
  999. /* - the user defined kernel used to apply mean */
  1000. /* shift filtering to the defined input image */
  1001. /* has spatial bandwidth sigmaS and range band- */
  1002. /* width sigmaR */
  1003. /* - a data set has been defined */
  1004. /* - the height and width of the lattice has been */
  1005. /* specified using method DefineLattice() */
  1006. /*Post: */
  1007. /* - mean shift filtering has been applied to the */
  1008. /* input image using a user defined kernel */
  1009. /* - the filtered image is stored in the private */
  1010. /* data members of the msImageProcessor class. */
  1011. /*******************************************************/
  1012. void msImageProcessor::NonOptimizedFilter ( float sigmaS, float sigmaR )
  1013. {
  1014. // Declare Variables
  1015. int iterationCount, i, j;
  1016. double mvAbs;
  1017. //make sure that a lattice height and width have
  1018. //been defined...
  1019. if ( !height )
  1020. {
  1021. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "LFilter", ( char* ) "Lattice height and width are undefined." );
  1022. return;
  1023. }
  1024. //re-assign bandwidths to sigmaS and sigmaR
  1025. if ( ( ( h[0] = sigmaS ) <= 0 ) || ( ( h[1] = sigmaR ) <= 0 ) )
  1026. {
  1027. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Segment", ( char* ) "sigmaS and/or sigmaR is zero or negative." );
  1028. return;
  1029. }
  1030. //define input data dimension with lattice
  1031. int lN = N + 2;
  1032. // Traverse each data point applying mean shift
  1033. // to each data point
  1034. // Allcocate memory for yk
  1035. double *yk = new double [lN];
  1036. // Allocate memory for Mh
  1037. double *Mh = new double [lN];
  1038. // proceed ...
  1039. #ifdef PROMPT
  1040. printf ( ( char* ) "done.\nApplying mean shift (Using Lattice)... " );
  1041. #ifdef SHOW_PROGRESS
  1042. printf ( ( char* ) "\n 0%%" );
  1043. #endif
  1044. #endif
  1045. // Parallelisieren !!!
  1046. for ( i = 0; i < L; i++ )
  1047. {
  1048. // Assign window center (window centers are
  1049. // initialized by createLattice to be the point
  1050. // data[i])
  1051. yk[0] = i % width;
  1052. yk[1] = i / width;
  1053. for ( j = 0; j < N; j++ )
  1054. yk[j+2] = data[N*i+j];
  1055. // Calculate the mean shift vector using the lattice
  1056. LatticeMSVector ( Mh, yk );
  1057. // Calculate its magnitude squared
  1058. mvAbs = 0;
  1059. for ( j = 0; j < lN; j++ )
  1060. mvAbs += Mh[j] * Mh[j];
  1061. // Keep shifting window center until the magnitude squared of the
  1062. // mean shift vector calculated at the window center location is
  1063. // under a specified threshold (Epsilon)
  1064. // NOTE: iteration count is for speed up purposes only - it
  1065. // does not have any theoretical importance
  1066. iterationCount = 1;
  1067. while ( ( mvAbs >= EPSILON2 ) && ( iterationCount < LIMIT ) )
  1068. {
  1069. // Shift window location
  1070. for ( j = 0; j < lN; j++ )
  1071. yk[j] += Mh[j];
  1072. // Calculate the mean shift vector at the new
  1073. // window location using lattice
  1074. LatticeMSVector ( Mh, yk );
  1075. // Calculate its magnitude squared
  1076. mvAbs = 0;
  1077. for ( j = 0; j < lN; j++ )
  1078. mvAbs += Mh[j] * Mh[j];
  1079. // Increment interation count
  1080. iterationCount++;
  1081. }
  1082. // Shift window location
  1083. for ( j = 0; j < lN; j++ )
  1084. yk[j] += Mh[j];
  1085. //store result into msRawData...
  1086. for ( j = 0; j < N; j++ )
  1087. msRawData[N*i+j] = ( float ) ( yk[j+2] );
  1088. // Prompt user on progress
  1089. #ifdef SHOW_PROGRESS
  1090. percent_complete = ( float ) ( i / ( float ) ( L ) ) * 100;
  1091. printf ( ( char* ) "\r%2d%%", ( int ) ( percent_complete + 0.5 ) );
  1092. #endif
  1093. // Check to see if the algorithm has been halted
  1094. if ( ( i % PROGRESS_RATE == 0 ) && ( ( ErrorStatus = msSys.Progress ( ( float ) ( i / ( float ) ( L ) ) * ( float ) ( 0.8 ) ) ) ) == EL_HALT )
  1095. break;
  1096. }
  1097. // Prompt user that filtering is completed
  1098. #ifdef PROMPT
  1099. #ifdef SHOW_PROGRESS
  1100. printf ( ( char* ) "\r" );
  1101. #endif
  1102. printf ( ( char* ) "done." );
  1103. #endif
  1104. // de-allocate memory
  1105. delete [] yk;
  1106. delete [] Mh;
  1107. // done.
  1108. return;
  1109. }
  1110. /*******************************************************/
  1111. /*Optimized Filter 1 */
  1112. /*******************************************************/
  1113. /*Performs mean shift filtering on the specified input */
  1114. /*image using a user defined kernel. Previous mode */
  1115. /*information is used to avoid re-applying mean shift */
  1116. /*on certain data points to improve performance. */
  1117. /*******************************************************/
  1118. /*Pre: */
  1119. /* - the user defined kernel used to apply mean */
  1120. /* shift filtering to the defined input image */
  1121. /* has spatial bandwidth sigmaS and range band- */
  1122. /* width sigmaR */
  1123. /* - a data set has been defined */
  1124. /* - the height and width of the lattice has been */
  1125. /* specified using method DefineLattice() */
  1126. /*Post: */
  1127. /* - mean shift filtering has been applied to the */
  1128. /* input image using a user defined kernel */
  1129. /* - the filtered image is stored in the private */
  1130. /* data members of the msImageProcessor class. */
  1131. /*******************************************************/
  1132. void msImageProcessor::OptimizedFilter1 ( float sigmaS, float sigmaR )
  1133. {
  1134. // Declare Variables
  1135. int iterationCount, i, j, k, s, p, modeCandidateX, modeCandidateY, modeCandidate_i;
  1136. float *modeCandidatePoint;
  1137. double mvAbs, diff, el;
  1138. //make sure that a lattice height and width have
  1139. //been defined...
  1140. if ( !height )
  1141. {
  1142. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "LFilter", ( char* ) "Lattice height and width are undefined." );
  1143. return;
  1144. }
  1145. //re-assign bandwidths to sigmaS and sigmaR
  1146. if ( ( ( h[0] = sigmaS ) <= 0 ) || ( ( h[1] = sigmaR ) <= 0 ) )
  1147. {
  1148. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Segment", ( char* ) "sigmaS and/or sigmaR is zero or negative." );
  1149. return;
  1150. }
  1151. //define input data dimension with lattice
  1152. int lN = N + 2;
  1153. // Traverse each data point applying mean shift
  1154. // to each data point
  1155. // Allcocate memory for yk
  1156. double *yk = new double [lN];
  1157. // Allocate memory for Mh
  1158. double *Mh = new double [lN];
  1159. // Initialize mode table used for basin of attraction
  1160. memset ( modeTable, 0, width*height );
  1161. // Allocate memory mode candidate data point...
  1162. //floating point version
  1163. modeCandidatePoint = new float [N];
  1164. // proceed ...
  1165. #ifdef PROMPT
  1166. printf ( ( char* ) "done.\nApplying mean shift (Using Lattice) ... " );
  1167. #ifdef SHOW_PROGRESS
  1168. printf ( ( char* ) "\n 0%%" );
  1169. #endif
  1170. #endif
  1171. // Parallelisieren !!!
  1172. for ( i = 0; i < L; i++ )
  1173. {
  1174. // if a mode was already assigned to this data point
  1175. // then skip this point, otherwise proceed to
  1176. // find its mode by applying mean shift...
  1177. if ( modeTable[i] == 1 )
  1178. continue;
  1179. // initialize point list...
  1180. pointCount = 0;
  1181. // Assign window center (window centers are
  1182. // initialized by createLattice to be the point
  1183. // data[i])
  1184. yk[0] = i % width;
  1185. yk[1] = i / width;
  1186. for ( j = 0; j < N; j++ )
  1187. yk[j+2] = data[N*i+j];
  1188. // Calculate the mean shift vector using the lattice
  1189. LatticeMSVector ( Mh, yk );
  1190. // Calculate its magnitude squared
  1191. mvAbs = 0;
  1192. for ( j = 0; j < lN; j++ )
  1193. mvAbs += Mh[j] * Mh[j];
  1194. // Keep shifting window center until the magnitude squared of the
  1195. // mean shift vector calculated at the window center location is
  1196. // under a specified threshold (Epsilon)
  1197. // NOTE: iteration count is for speed up purposes only - it
  1198. // does not have any theoretical importance
  1199. iterationCount = 1;
  1200. while ( ( mvAbs >= EPSILON2 ) && ( iterationCount < LIMIT ) )
  1201. {
  1202. // Shift window location
  1203. for ( j = 0; j < lN; j++ )
  1204. yk[j] += Mh[j];
  1205. // check to see if the current mode location is in the
  1206. // basin of attraction...
  1207. // calculate the location of yk on the lattice
  1208. modeCandidateX = ( int ) ( yk[0] + 0.5 );
  1209. modeCandidateY = ( int ) ( yk[1] + 0.5 );
  1210. modeCandidate_i = modeCandidateY * width + modeCandidateX;
  1211. // if mvAbs != 0 (yk did indeed move) then check
  1212. // location basin_i in the mode table to see if
  1213. // this data point either:
  1214. // (1) has not been associated with a mode yet
  1215. // (modeTable[basin_i] = 0), so associate
  1216. // it with this one
  1217. //
  1218. // (2) it has been associated with a mode other
  1219. // than the one that this data point is converging
  1220. // to (modeTable[basin_i] = 1), so assign to
  1221. // this data point the same mode as that of basin_i
  1222. if ( ( modeTable[modeCandidate_i] != 2 ) && ( modeCandidate_i != i ) )
  1223. {
  1224. // obtain the data point at basin_i to
  1225. // see if it is within h*TC_DIST_FACTOR of
  1226. // of yk
  1227. for ( j = 0; j < N; j++ )
  1228. modeCandidatePoint[j] = data[N*modeCandidate_i + j];
  1229. // check basin on non-spatial data spaces only
  1230. k = 1;
  1231. s = 0;
  1232. diff = 0;
  1233. while ( ( diff < TC_DIST_FACTOR ) && ( k < kp ) )
  1234. {
  1235. diff = 0;
  1236. for ( p = 0; p < P[k]; p++ )
  1237. {
  1238. el = ( modeCandidatePoint[p+s] - yk[p+s+2] ) / h[k];
  1239. diff += el * el;
  1240. }
  1241. s += P[k];
  1242. k++;
  1243. }
  1244. // if the data point at basin_i is within
  1245. // a distance of h*TC_DIST_FACTOR of yk
  1246. // then depending on modeTable[basin_i] perform
  1247. // either (1) or (2)
  1248. if ( diff < TC_DIST_FACTOR )
  1249. {
  1250. // if the data point at basin_i has not
  1251. // been associated to a mode then associate
  1252. // it with the mode that this one will converge
  1253. // to
  1254. if ( modeTable[modeCandidate_i] == 0 )
  1255. {
  1256. // no mode associated yet so associate
  1257. // it with this one...
  1258. pointList[pointCount++] = modeCandidate_i;
  1259. modeTable[modeCandidate_i] = 2;
  1260. } else
  1261. {
  1262. // the mode has already been associated with
  1263. // another mode, thererfore associate this one
  1264. // mode and the modes in the point list with
  1265. // the mode associated with data[basin_i]...
  1266. // store the mode info into yk using msRawData...
  1267. for ( j = 0; j < N; j++ )
  1268. yk[j+2] = msRawData[modeCandidate_i*N+j];
  1269. // update mode table for this data point
  1270. // indicating that a mode has been associated
  1271. // with it
  1272. modeTable[i] = 1;
  1273. // indicate that a mode has been associated
  1274. // to this data point (data[i])
  1275. mvAbs = -1;
  1276. // stop mean shift calculation...
  1277. break;
  1278. }
  1279. }
  1280. }
  1281. // Calculate the mean shift vector at the new
  1282. // window location using lattice
  1283. LatticeMSVector ( Mh, yk );
  1284. // Calculate its magnitude squared
  1285. mvAbs = 0;
  1286. for ( j = 0; j < lN; j++ )
  1287. mvAbs += Mh[j] * Mh[j];
  1288. // Increment iteration count
  1289. iterationCount++;
  1290. }
  1291. // if a mode was not associated with this data point
  1292. // yet associate it with yk...
  1293. if ( mvAbs >= 0 )
  1294. {
  1295. // Shift window location
  1296. for ( j = 0; j < lN; j++ )
  1297. yk[j] += Mh[j];
  1298. // update mode table for this data point
  1299. // indicating that a mode has been associated
  1300. // with it
  1301. modeTable[i] = 1;
  1302. }
  1303. // associate the data point indexed by
  1304. // the point list with the mode stored
  1305. // by yk
  1306. for ( j = 0; j < pointCount; j++ )
  1307. {
  1308. // obtain the point location from the
  1309. // point list
  1310. modeCandidate_i = pointList[j];
  1311. // update the mode table for this point
  1312. modeTable[modeCandidate_i] = 1;
  1313. //store result into msRawData...
  1314. for ( k = 0; k < N; k++ )
  1315. msRawData[N*modeCandidate_i+k] = ( float ) ( yk[k+2] );
  1316. }
  1317. //store result into msRawData...
  1318. for ( j = 0; j < N; j++ )
  1319. msRawData[N*i+j] = ( float ) ( yk[j+2] );
  1320. // Prompt user on progress
  1321. #ifdef SHOW_PROGRESS
  1322. percent_complete = ( float ) ( i / ( float ) ( L ) ) * 100;
  1323. printf ( ( char* ) "\r%2d%%", ( int ) ( percent_complete + 0.5 ) );
  1324. #endif
  1325. // Check to see if the algorithm has been halted
  1326. if ( ( i % PROGRESS_RATE == 0 ) && ( ( ErrorStatus = msSys.Progress ( ( float ) ( i / ( float ) ( L ) ) * ( float ) ( 0.8 ) ) ) ) == EL_HALT )
  1327. break;
  1328. }
  1329. // Prompt user that filtering is completed
  1330. #ifdef PROMPT
  1331. #ifdef SHOW_PROGRESS
  1332. printf ( ( char* ) "\r" );
  1333. #endif
  1334. printf ( ( char* ) "done." );
  1335. #endif
  1336. // de-allocate memory
  1337. delete [] modeCandidatePoint;
  1338. delete [] yk;
  1339. delete [] Mh;
  1340. // done.
  1341. return;
  1342. }
  1343. /*******************************************************/
  1344. /*Optimized Filter 2 */
  1345. /*******************************************************/
  1346. /*Performs mean shift filtering on the specified input */
  1347. /*image using a user defined kernel. Previous mode */
  1348. /*information is used to avoid re-applying mean shift */
  1349. /*on certain data points to improve performance. To */
  1350. /*further improve perfmance (during segmentation) poi- */
  1351. /*nts within h of a window center during the window */
  1352. /*center's traversal to a mode are associated with the */
  1353. /*mode that the window converges to. */
  1354. /*******************************************************/
  1355. /*Pre: */
  1356. /* - the user defined kernel used to apply mean */
  1357. /* shift filtering to the defined input image */
  1358. /* has spatial bandwidth sigmaS and range band- */
  1359. /* width sigmaR */
  1360. /* - a data set has been defined */
  1361. /* - the height and width of the lattice has been */
  1362. /* specified using method DefineLattice() */
  1363. /*Post: */
  1364. /* - mean shift filtering has been applied to the */
  1365. /* input image using a user defined kernel */
  1366. /* - the filtered image is stored in the private */
  1367. /* data members of the msImageProcessor class. */
  1368. /*******************************************************/
  1369. void msImageProcessor::OptimizedFilter2 ( float sigmaS, float sigmaR )
  1370. {
  1371. //if confidence map is null set it to zero
  1372. if ( !weightMap )
  1373. {
  1374. weightMap = new float [L];
  1375. int i;
  1376. for ( i = 0; i < L; i++ )
  1377. weightMap[i] = 0;
  1378. }
  1379. // Declare Variables
  1380. int iterationCount, i, j, k, s, p, modeCandidateX, modeCandidateY, modeCandidate_i;
  1381. float *modeCandidatePoint;
  1382. double mvAbs, diff, el;
  1383. //make sure that a lattice height and width have
  1384. //been defined...
  1385. if ( !height )
  1386. {
  1387. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "LFilter", ( char* ) "Lattice height and width are undefined." );
  1388. return;
  1389. }
  1390. //re-assign bandwidths to sigmaS and sigmaR
  1391. if ( ( ( h[0] = sigmaS ) <= 0 ) || ( ( h[1] = sigmaR ) <= 0 ) )
  1392. {
  1393. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Segment", ( char* ) "sigmaS and/or sigmaR is zero or negative." );
  1394. return;
  1395. }
  1396. //define input data dimension with lattice
  1397. int lN = N + 2;
  1398. // Traverse each data point applying mean shift
  1399. // to each data point
  1400. // Allcocate memory for yk
  1401. double *yk = new double [lN];
  1402. // Allocate memory for Mh
  1403. double *Mh = new double [lN];
  1404. // Initialize mode table used for basin of attraction
  1405. memset ( modeTable, 0, width*height );
  1406. // Allocate memory mode candidate data point...
  1407. //floating point version
  1408. modeCandidatePoint = new float [N];
  1409. // proceed ...
  1410. #ifdef PROMPT
  1411. printf ( ( char* ) "done.\nApplying mean shift (Using Lattice)... " );
  1412. #ifdef SHOW_PROGRESS
  1413. printf ( ( char* ) "\n 0%%" );
  1414. #endif
  1415. #endif
  1416. // Parallelisieren !!!
  1417. for ( i = 0; i < L; i++ )
  1418. {
  1419. // if a mode was already assigned to this data point
  1420. // then skip this point, otherwise proceed to
  1421. // find its mode by applying mean shift...
  1422. if ( modeTable[i] == 1 )
  1423. continue;
  1424. // initialize point list...
  1425. pointCount = 0;
  1426. // Assign window center (window centers are
  1427. // initialized by createLattice to be the point
  1428. // data[i])
  1429. yk[0] = i % width;
  1430. yk[1] = i / width;
  1431. for ( j = 0; j < N; j++ )
  1432. yk[j+2] = data[N*i+j];
  1433. // Calculate the mean shift vector using the lattice
  1434. OptLatticeMSVector ( Mh, yk );
  1435. // Calculate its magnitude squared
  1436. mvAbs = 0;
  1437. for ( j = 0; j < lN; j++ )
  1438. mvAbs += Mh[j] * Mh[j];
  1439. // Keep shifting window center until the magnitude squared of the
  1440. // mean shift vector calculated at the window center location is
  1441. // under a specified threshold (Epsilon)
  1442. // NOTE: iteration count is for speed up purposes only - it
  1443. // does not have any theoretical importance
  1444. iterationCount = 1;
  1445. while ( ( mvAbs >= EPSILON2 ) && ( iterationCount < LIMIT ) )
  1446. {
  1447. // Shift window location
  1448. for ( j = 0; j < lN; j++ )
  1449. yk[j] += Mh[j];
  1450. // check to see if the current mode location is in the
  1451. // basin of attraction...
  1452. // calculate the location of yk on the lattice
  1453. modeCandidateX = ( int ) ( yk[0] + 0.5 );
  1454. modeCandidateY = ( int ) ( yk[1] + 0.5 );
  1455. modeCandidate_i = modeCandidateY * width + modeCandidateX;
  1456. // if mvAbs != 0 (yk did indeed move) then check
  1457. // location basin_i in the mode table to see if
  1458. // this data point either:
  1459. // (1) has not been associated with a mode yet
  1460. // (modeTable[basin_i] = 0), so associate
  1461. // it with this one
  1462. //
  1463. // (2) it has been associated with a mode other
  1464. // than the one that this data point is converging
  1465. // to (modeTable[basin_i] = 1), so assign to
  1466. // this data point the same mode as that of basin_i
  1467. if ( ( modeTable[modeCandidate_i] != 2 ) && ( modeCandidate_i != i ) )
  1468. {
  1469. // obtain the data point at basin_i to
  1470. // see if it is within h*TC_DIST_FACTOR of
  1471. // of yk
  1472. for ( j = 0; j < N; j++ )
  1473. modeCandidatePoint[j] = data[N*modeCandidate_i + j];
  1474. // check basin on non-spatial data spaces only
  1475. k = 1;
  1476. s = 0;
  1477. diff = 0;
  1478. while ( ( diff < TC_DIST_FACTOR ) && ( k < kp ) )
  1479. {
  1480. diff = 0;
  1481. for ( p = 0; p < P[k]; p++ )
  1482. {
  1483. el = ( modeCandidatePoint[p+s] - yk[p+s+2] ) / h[k];
  1484. diff += el * el;
  1485. }
  1486. s += P[k];
  1487. k++;
  1488. }
  1489. // if the data point at basin_i is within
  1490. // a distance of h*TC_DIST_FACTOR of yk
  1491. // then depending on modeTable[basin_i] perform
  1492. // either (1) or (2)
  1493. if ( diff < TC_DIST_FACTOR )
  1494. {
  1495. // if the data point at basin_i has not
  1496. // been associated to a mode then associate
  1497. // it with the mode that this one will converge
  1498. // to
  1499. if ( modeTable[modeCandidate_i] == 0 )
  1500. {
  1501. // no mode associated yet so associate
  1502. // it with this one...
  1503. pointList[pointCount++] = modeCandidate_i;
  1504. modeTable[modeCandidate_i] = 2;
  1505. } else
  1506. {
  1507. // the mode has already been associated with
  1508. // another mode, thererfore associate this one
  1509. // mode and the modes in the point list with
  1510. // the mode associated with data[basin_i]...
  1511. // store the mode infor int yk using msRawData...
  1512. for ( j = 0; j < N; j++ )
  1513. yk[j+2] = msRawData[modeCandidate_i*N+j];
  1514. // update mode table for this data point
  1515. // indicating that a mode has been associated
  1516. // with it
  1517. modeTable[i] = 1;
  1518. // indicate that a mode has been associated
  1519. // to this data point (data[i])
  1520. mvAbs = -1;
  1521. // stop mean shift calculation...
  1522. break;
  1523. }
  1524. }
  1525. }
  1526. // Calculate the mean shift vector at the new
  1527. // window location using lattice
  1528. OptLatticeMSVector ( Mh, yk );
  1529. // Calculate its magnitude squared
  1530. mvAbs = 0;
  1531. for ( j = 0; j < lN; j++ )
  1532. mvAbs += Mh[j] * Mh[j];
  1533. // Increment interation count
  1534. iterationCount++;
  1535. }
  1536. // if a mode was not associated with this data point
  1537. // yet then perform a shift the window center yk one
  1538. // last time using the mean shift vector...
  1539. if ( mvAbs >= 0 )
  1540. {
  1541. // Shift window location
  1542. for ( j = 0; j < lN; j++ )
  1543. yk[j] += Mh[j];
  1544. // update mode table for this data point
  1545. // indicating that a mode has been associated
  1546. // with it
  1547. modeTable[i] = 1;
  1548. }
  1549. // associate the data point indexed by
  1550. // the point list with the mode stored
  1551. // by yk
  1552. for ( j = 0; j < pointCount; j++ )
  1553. {
  1554. // obtain the point location from the
  1555. // point list
  1556. modeCandidate_i = pointList[j];
  1557. // update the mode table for this point
  1558. modeTable[modeCandidate_i] = 1;
  1559. //store result into msRawData...
  1560. for ( k = 0; k < N; k++ )
  1561. msRawData[N*modeCandidate_i+k] = ( float ) ( yk[k+2] );
  1562. }
  1563. //store result into msRawData...
  1564. for ( j = 0; j < N; j++ )
  1565. msRawData[N*i+j] = ( float ) ( yk[j+2] );
  1566. // Prompt user on progress
  1567. #ifdef SHOW_PROGRESS
  1568. percent_complete = ( float ) ( i / ( float ) ( L ) ) * 100;
  1569. printf ( ( char* ) "\r%2d%%", ( int ) ( percent_complete + 0.5 ) );
  1570. #endif
  1571. // Check to see if the algorithm has been halted
  1572. if ( ( i % PROGRESS_RATE == 0 ) && ( ( ErrorStatus = msSys.Progress ( ( float ) ( i / ( float ) ( L ) ) * ( float ) ( 0.8 ) ) ) ) == EL_HALT )
  1573. break;
  1574. }
  1575. // Prompt user that filtering is completed
  1576. #ifdef PROMPT
  1577. #ifdef SHOW_PROGRESS
  1578. printf ( ( char* ) "\r" );
  1579. #endif
  1580. printf ( ( char* ) "done." );
  1581. #endif
  1582. // de-allocate memory
  1583. delete [] modeCandidatePoint;
  1584. delete [] yk;
  1585. delete [] Mh;
  1586. // done.
  1587. return;
  1588. }
  1589. /*/\/\/\/\/\/\/\/\/\/\/\*/
  1590. /* Image Classification */
  1591. /*\/\/\/\/\/\/\/\/\/\/\/*/
  1592. /*******************************************************/
  1593. /*Connect */
  1594. /*******************************************************/
  1595. /*Classifies the regions of the mean shift filtered */
  1596. /*image. */
  1597. /*******************************************************/
  1598. /*Post: */
  1599. /* - the regions of the mean shift image have been*/
  1600. /* classified using the private classification */
  1601. /* structure of the msImageProcessor Class. */
  1602. /* Namely, each region uniquely identified by */
  1603. /* its LUV color (stored by LUV_data) and loc- */
  1604. /* ation has been labeled and its area computed */
  1605. /* via an eight-connected fill. */
  1606. /*******************************************************/
  1607. void msImageProcessor::Connect ( void )
  1608. {
  1609. //define eight connected neighbors
  1610. neigh[0] = 1;
  1611. neigh[1] = 1 - width;
  1612. neigh[2] = -width;
  1613. neigh[3] = - ( 1 + width );
  1614. neigh[4] = -1;
  1615. neigh[5] = width - 1;
  1616. neigh[6] = width;
  1617. neigh[7] = width + 1;
  1618. //initialize labels and modePointCounts
  1619. int i;
  1620. for ( i = 0; i < width*height; i++ )
  1621. {
  1622. labels[i] = -1;
  1623. modePointCounts[i] = 0;
  1624. }
  1625. //Traverse the image labeling each new region encountered
  1626. int k, label = -1;
  1627. for ( i = 0; i < height*width; i++ )
  1628. {
  1629. //if this region has not yet been labeled - label it
  1630. if ( labels[i] < 0 )
  1631. {
  1632. //assign new label to this region
  1633. labels[i] = ++label;
  1634. //copy region color into modes
  1635. for ( k = 0; k < N; k++ )
  1636. modes[ ( N*label ) +k] = LUV_data[ ( N*i ) +k];
  1637. // modes[(N*label)+k] = (float)(LUV_data[(N*i)+k]);
  1638. //populate labels with label for this specified region
  1639. //calculating modePointCounts[label]...
  1640. Fill ( i, label );
  1641. }
  1642. }
  1643. //calculate region count using label
  1644. regionCount = label + 1;
  1645. //done.
  1646. return;
  1647. }
  1648. /*******************************************************/
  1649. /*Fill */
  1650. /*******************************************************/
  1651. /*Given a region seed and a region label, Fill uses */
  1652. /*the region seed to perform an eight-connected fill */
  1653. /*for the specified region, labeling all pixels con- */
  1654. /*tained by the region with the specified label: */
  1655. /*label. */
  1656. /*******************************************************/
  1657. /*Pre: */
  1658. /* - regionLoc is a region seed - a pixel that is */
  1659. /* identified as being part of the region */
  1660. /* labled using the label, label. */
  1661. /*Post: */
  1662. /* - all pixels belonging to the region specified */
  1663. /* by regionLoc (having the same integer LUV */
  1664. /* value specified by LUV_data) are classified */
  1665. /* as one region by labeling each pixel in the */
  1666. /* image clasification structure using label */
  1667. /* via an eight-connected fill. */
  1668. /*******************************************************/
  1669. void msImageProcessor::Fill ( int regionLoc, int label )
  1670. {
  1671. //declare variables
  1672. int i, k, neighLoc, neighborsFound, imageSize = width * height;
  1673. //Fill region starting at region location
  1674. //using labels...
  1675. //initialzie indexTable
  1676. int index = 0;
  1677. indexTable[0] = regionLoc;
  1678. //increment mode point counts for this region to
  1679. //indicate that one pixel belongs to this region
  1680. modePointCounts[label]++;
  1681. while ( true )
  1682. {
  1683. //assume no neighbors will be found
  1684. neighborsFound = 0;
  1685. //check the eight connected neighbors at regionLoc -
  1686. //if a pixel has similar color to that located at
  1687. //regionLoc then declare it as part of this region
  1688. for ( i = 0; i < 8; i++ )
  1689. {
  1690. // no need
  1691. /*
  1692. //if at boundary do not check certain neighbors because
  1693. //they do not exist...
  1694. if((regionLoc%width == 0)&&((i == 3)||(i == 4)||(i == 5)))
  1695. continue;
  1696. if((regionLoc%(width-1) == 0)&&((i == 0)||(i == 1)||(i == 7)))
  1697. continue;
  1698. */
  1699. //check bounds and if neighbor has been already labeled
  1700. neighLoc = regionLoc + neigh[i];
  1701. if ( ( neighLoc >= 0 ) && ( neighLoc < imageSize ) && ( labels[neighLoc] < 0 ) )
  1702. {
  1703. for ( k = 0; k < N; k++ )
  1704. {
  1705. // if(LUV_data[(regionLoc*N)+k] != LUV_data[(neighLoc*N)+k])
  1706. if ( fabs ( LUV_data[ ( regionLoc*N ) +k] - LUV_data[ ( neighLoc*N ) +k] ) >= LUV_treshold )
  1707. break;
  1708. }
  1709. //neighbor i belongs to this region so label it and
  1710. //place it onto the index table buffer for further
  1711. //processing
  1712. if ( k == N )
  1713. {
  1714. //assign label to neighbor i
  1715. labels[neighLoc] = label;
  1716. //increment region point count
  1717. modePointCounts[label]++;
  1718. //place index of neighbor i onto the index tabel buffer
  1719. indexTable[++index] = neighLoc;
  1720. //indicate that a neighboring region pixel was
  1721. //identified
  1722. neighborsFound = 1;
  1723. }
  1724. }
  1725. }
  1726. //check the indexTable to see if there are any more
  1727. //entries to be explored - if so explore them, otherwise
  1728. //exit the loop - we are finished
  1729. if ( neighborsFound )
  1730. regionLoc = indexTable[index];
  1731. else if ( index > 1 )
  1732. regionLoc = indexTable[--index];
  1733. else
  1734. break; //fill complete
  1735. }
  1736. //done.
  1737. return;
  1738. }
  1739. /*/\/\/\/\/\/\/\/\*/
  1740. /* Image Pruning */
  1741. /*\/\/\/\/\/\/\/\/*/
  1742. /*******************************************************/
  1743. /*Build Region Adjacency Matrix */
  1744. /*******************************************************/
  1745. /*Constructs a region adjacency matrix. */
  1746. /*******************************************************/
  1747. /*Pre: */
  1748. /* - the classification data structure has been */
  1749. /* constructed. */
  1750. /*Post: */
  1751. /* - a region adjacency matrix has been built */
  1752. /* using the classification data structure. */
  1753. /*******************************************************/
  1754. void msImageProcessor::BuildRAM ( void )
  1755. {
  1756. //Allocate memory for region adjacency matrix if it hasn't already been allocated
  1757. if ( ( !raList ) && ( ( ! ( raList = new RAList [regionCount] ) ) || ( ! ( raPool = new RAList [NODE_MULTIPLE*regionCount] ) ) ) )
  1758. {
  1759. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Allocate", ( char* ) "Not enough memory." );
  1760. return;
  1761. }
  1762. //initialize the region adjacency list
  1763. int i;
  1764. for ( i = 0; i < regionCount; i++ )
  1765. {
  1766. raList[i].edgeStrength = 0;
  1767. raList[i].edgePixelCount = 0;
  1768. raList[i].label = i;
  1769. raList[i].next = NULL;
  1770. }
  1771. //initialize RAM free list
  1772. freeRAList = raPool;
  1773. for ( i = 0; i < NODE_MULTIPLE*regionCount - 1; i++ )
  1774. {
  1775. raPool[i].edgeStrength = 0;
  1776. raPool[i].edgePixelCount = 0;
  1777. raPool[i].next = &raPool[i+1];
  1778. }
  1779. raPool[NODE_MULTIPLE*regionCount-1].next = NULL;
  1780. //traverse the labeled image building
  1781. //the RAM by looking to the right of
  1782. //and below the current pixel location thus
  1783. //determining if a given region is adjacent
  1784. //to another
  1785. int j, curLabel, rightLabel, bottomLabel, exists;
  1786. RAList *raNode1, *raNode2, *oldRAFreeList;
  1787. for ( i = 0; i < height - 1; i++ )
  1788. {
  1789. //check the right and below neighbors
  1790. //for pixel locations whose x < width - 1
  1791. for ( j = 0; j < width - 1; j++ )
  1792. {
  1793. //calculate pixel labels
  1794. curLabel = labels[i*width+j ]; //current pixel
  1795. rightLabel = labels[i*width+j+1 ]; //right pixel
  1796. bottomLabel = labels[ ( i+1 ) *width+j]; //bottom pixel
  1797. //check to the right, if the label of
  1798. //the right pixel is not the same as that
  1799. //of the current one then region[j] and region[j+1]
  1800. //are adjacent to one another - update the RAM
  1801. if ( curLabel != rightLabel )
  1802. {
  1803. //obtain RAList object from region adjacency free
  1804. //list
  1805. raNode1 = freeRAList;
  1806. raNode2 = freeRAList->next;
  1807. //keep a pointer to the old region adj. free
  1808. //list just in case nodes already exist in respective
  1809. //region lists
  1810. oldRAFreeList = freeRAList;
  1811. //update region adjacency free list
  1812. freeRAList = freeRAList->next->next;
  1813. //populate RAList nodes
  1814. raNode1->label = curLabel;
  1815. raNode2->label = rightLabel;
  1816. //insert nodes into the RAM
  1817. exists = 0;
  1818. raList[curLabel ].Insert ( raNode2 );
  1819. exists = raList[rightLabel].Insert ( raNode1 );
  1820. //if the node already exists then place
  1821. //nodes back onto the region adjacency
  1822. //free list
  1823. if ( exists )
  1824. freeRAList = oldRAFreeList;
  1825. }
  1826. //check below, if the label of
  1827. //the bottom pixel is not the same as that
  1828. //of the current one then region[j] and region[j+width]
  1829. //are adjacent to one another - update the RAM
  1830. if ( curLabel != bottomLabel )
  1831. {
  1832. //obtain RAList object from region adjacency free
  1833. //list
  1834. raNode1 = freeRAList;
  1835. raNode2 = freeRAList->next;
  1836. //keep a pointer to the old region adj. free
  1837. //list just in case nodes already exist in respective
  1838. //region lists
  1839. oldRAFreeList = freeRAList;
  1840. //update region adjacency free list
  1841. freeRAList = freeRAList->next->next;
  1842. //populate RAList nodes
  1843. raNode1->label = curLabel;
  1844. raNode2->label = bottomLabel;
  1845. //insert nodes into the RAM
  1846. exists = 0;
  1847. raList[curLabel ].Insert ( raNode2 );
  1848. exists = raList[bottomLabel].Insert ( raNode1 );
  1849. //if the node already exists then place
  1850. //nodes back onto the region adjacency
  1851. //free list
  1852. if ( exists )
  1853. freeRAList = oldRAFreeList;
  1854. }
  1855. }
  1856. //check only to the bottom neighbors of the right boundary
  1857. //pixels...
  1858. //calculate pixel locations (j = width-1)
  1859. curLabel = labels[i*width+j ]; //current pixel
  1860. bottomLabel = labels[ ( i+1 ) *width+j]; //bottom pixel
  1861. //check below, if the label of
  1862. //the bottom pixel is not the same as that
  1863. //of the current one then region[j] and region[j+width]
  1864. //are adjacent to one another - update the RAM
  1865. if ( curLabel != bottomLabel )
  1866. {
  1867. //obtain RAList object from region adjacency free
  1868. //list
  1869. raNode1 = freeRAList;
  1870. raNode2 = freeRAList->next;
  1871. //keep a pointer to the old region adj. free
  1872. //list just in case nodes already exist in respective
  1873. //region lists
  1874. oldRAFreeList = freeRAList;
  1875. //update region adjacency free list
  1876. freeRAList = freeRAList->next->next;
  1877. //populate RAList nodes
  1878. raNode1->label = curLabel;
  1879. raNode2->label = bottomLabel;
  1880. //insert nodes into the RAM
  1881. exists = 0;
  1882. raList[curLabel ].Insert ( raNode2 );
  1883. exists = raList[bottomLabel].Insert ( raNode1 );
  1884. //if the node already exists then place
  1885. //nodes back onto the region adjacency
  1886. //free list
  1887. if ( exists )
  1888. freeRAList = oldRAFreeList;
  1889. }
  1890. }
  1891. //check only to the right neighbors of the bottom boundary
  1892. //pixels...
  1893. //check the right for pixel locations whose x < width - 1
  1894. for ( j = 0; j < width - 1; j++ )
  1895. {
  1896. //calculate pixel labels (i = height-1)
  1897. curLabel = labels[i*width+j ]; //current pixel
  1898. rightLabel = labels[i*width+j+1 ]; //right pixel
  1899. //check to the right, if the label of
  1900. //the right pixel is not the same as that
  1901. //of the current one then region[j] and region[j+1]
  1902. //are adjacent to one another - update the RAM
  1903. if ( curLabel != rightLabel )
  1904. {
  1905. //obtain RAList object from region adjacency free
  1906. //list
  1907. raNode1 = freeRAList;
  1908. raNode2 = freeRAList->next;
  1909. //keep a pointer to the old region adj. free
  1910. //list just in case nodes already exist in respective
  1911. //region lists
  1912. oldRAFreeList = freeRAList;
  1913. //update region adjacency free list
  1914. freeRAList = freeRAList->next->next;
  1915. //populate RAList nodes
  1916. raNode1->label = curLabel;
  1917. raNode2->label = rightLabel;
  1918. //insert nodes into the RAM
  1919. exists = 0;
  1920. raList[curLabel ].Insert ( raNode2 );
  1921. exists = raList[rightLabel].Insert ( raNode1 );
  1922. //if the node already exists then place
  1923. //nodes back onto the region adjacency
  1924. //free list
  1925. if ( exists )
  1926. freeRAList = oldRAFreeList;
  1927. }
  1928. }
  1929. //done.
  1930. return;
  1931. }
  1932. /*******************************************************/
  1933. /*Destroy Region Adjacency Matrix */
  1934. /*******************************************************/
  1935. /*Destroy a region adjacency matrix. */
  1936. /*******************************************************/
  1937. /*Post: */
  1938. /* - the region adjacency matrix has been destr- */
  1939. /* oyed: (1) its memory has been de-allocated, */
  1940. /* (2) the RAM structure has been initialize */
  1941. /* for re-use. */
  1942. /*******************************************************/
  1943. void msImageProcessor::DestroyRAM ( void )
  1944. {
  1945. //de-allocate memory for region adjaceny list
  1946. if ( raList ) delete [] raList;
  1947. if ( raPool ) delete [] raPool;
  1948. //initialize region adjacency matrix
  1949. raList = NULL;
  1950. freeRAList = NULL;
  1951. raPool = NULL;
  1952. //done.
  1953. return;
  1954. }
  1955. /*******************************************************/
  1956. /*Transitive Closure */
  1957. /*******************************************************/
  1958. /*Applies transitive closure to the RAM updating */
  1959. /*labels, modes and modePointCounts to reflect the new */
  1960. /*set of merged regions resulting from transitive clo- */
  1961. /*sure. */
  1962. /*******************************************************/
  1963. /*Post: */
  1964. /* - transitive closure has been applied to the */
  1965. /* regions classified by the RAM and labels, */
  1966. /* modes and modePointCounts have been updated */
  1967. /* to reflect the new set of mergd regions res- */
  1968. /* ulting from transitive closure. */
  1969. /*******************************************************/
  1970. void msImageProcessor::TransitiveClosure ( void )
  1971. {
  1972. //Step (1):
  1973. // Build RAM using classifiction structure originally
  1974. // generated by the method GridTable::Connect()
  1975. BuildRAM();
  1976. //Step (1a):
  1977. //Compute weights of weight graph using confidence map
  1978. //(if defined)
  1979. if ( weightMapDefined ) ComputeEdgeStrengths();
  1980. //Step (2):
  1981. //Treat each region Ri as a disjoint set:
  1982. // - attempt to join Ri and Rj for all i != j that are neighbors and
  1983. // whose associated modes are a normalized distance of < 0.5 from one
  1984. // another
  1985. // - the label of each region in the raList is treated as a pointer to the
  1986. // canonical element of that region (e.g. raList[i], initially has raList[i].label = i,
  1987. // namely each region is initialized to have itself as its canonical element).
  1988. //Traverse RAM attempting to join raList[i] with its neighbors...
  1989. int i, iCanEl, neighCanEl;
  1990. float threshold;
  1991. RAList *neighbor;
  1992. for ( i = 0; i < regionCount; i++ )
  1993. {
  1994. //aquire first neighbor in region adjacency list pointed to
  1995. //by raList[i]
  1996. neighbor = raList[i].next;
  1997. //compute edge strenght threshold using global and local
  1998. //epsilon
  1999. if ( epsilon > raList[i].edgeStrength )
  2000. threshold = epsilon;
  2001. else
  2002. threshold = raList[i].edgeStrength;
  2003. //traverse region adjacency list of region i, attempting to join
  2004. //it with regions whose mode is a normalized distance < 0.5 from
  2005. //that of region i...
  2006. while ( neighbor )
  2007. {
  2008. //attempt to join region and neighbor...
  2009. if ( ( InWindow ( i, neighbor->label ) ) && ( neighbor->edgeStrength < epsilon ) )
  2010. {
  2011. //region i and neighbor belong together so join them
  2012. //by:
  2013. // (1) find the canonical element of region i
  2014. iCanEl = i;
  2015. while ( raList[iCanEl].label != iCanEl )
  2016. iCanEl = raList[iCanEl].label;
  2017. // (2) find the canonical element of neighboring region
  2018. neighCanEl = neighbor->label;
  2019. while ( raList[neighCanEl].label != neighCanEl )
  2020. neighCanEl = raList[neighCanEl].label;
  2021. // if the canonical elements of are not the same then assign
  2022. // the canonical element having the smaller label to be the parent
  2023. // of the other region...
  2024. if ( iCanEl < neighCanEl )
  2025. raList[neighCanEl].label = iCanEl;
  2026. else
  2027. {
  2028. //must replace the canonical element of previous
  2029. //parent as well
  2030. raList[raList[iCanEl].label].label = neighCanEl;
  2031. //re-assign canonical element
  2032. raList[iCanEl].label = neighCanEl;
  2033. }
  2034. }
  2035. //check the next neighbor...
  2036. neighbor = neighbor->next;
  2037. }
  2038. }
  2039. // Step (3):
  2040. // Level binary trees formed by canonical elements
  2041. for ( i = 0; i < regionCount; i++ )
  2042. {
  2043. iCanEl = i;
  2044. while ( raList[iCanEl].label != iCanEl )
  2045. iCanEl = raList[iCanEl].label;
  2046. raList[i].label = iCanEl;
  2047. }
  2048. // Step (4):
  2049. //Traverse joint sets, relabeling image.
  2050. // (a)
  2051. // Accumulate modes and re-compute point counts using canonical
  2052. // elements generated by step 2.
  2053. //allocate memory for mode and point count temporary buffers...
  2054. float *modes_buffer = new float [N*regionCount];
  2055. int *MPC_buffer = new int [regionCount];
  2056. //initialize buffers to zero
  2057. for ( i = 0; i < regionCount; i++ )
  2058. MPC_buffer[i] = 0;
  2059. for ( i = 0; i < N*regionCount; i++ )
  2060. modes_buffer[i] = 0;
  2061. //traverse raList accumulating modes and point counts
  2062. //using canoncial element information...
  2063. int k, iMPC;
  2064. for ( i = 0; i < regionCount; i++ )
  2065. {
  2066. //obtain canonical element of region i
  2067. iCanEl = raList[i].label;
  2068. //obtain mode point count of region i
  2069. iMPC = modePointCounts[i];
  2070. //accumulate modes_buffer[iCanEl]
  2071. for ( k = 0; k < N; k++ )
  2072. modes_buffer[ ( N*iCanEl ) +k] += iMPC * modes[ ( N*i ) +k];
  2073. //accumulate MPC_buffer[iCanEl]
  2074. MPC_buffer[iCanEl] += iMPC;
  2075. }
  2076. // (b)
  2077. // Re-label new regions of the image using the canonical
  2078. // element information generated by step (2)
  2079. // Also use this information to compute the modes of the newly
  2080. // defined regions, and to assign new region point counts in
  2081. // a consecute manner to the modePointCounts array
  2082. //allocate memory for label buffer
  2083. int *label_buffer = new int [regionCount];
  2084. //initialize label buffer to -1
  2085. for ( i = 0; i < regionCount; i++ )
  2086. label_buffer[i] = -1;
  2087. //traverse raList re-labeling the regions
  2088. int label = -1;
  2089. for ( i = 0; i < regionCount; i++ )
  2090. {
  2091. //obtain canonical element of region i
  2092. iCanEl = raList[i].label;
  2093. if ( label_buffer[iCanEl] < 0 )
  2094. {
  2095. //assign a label to the new region indicated by canonical
  2096. //element of i
  2097. label_buffer[iCanEl] = ++label;
  2098. //recompute mode storing the result in modes[label]...
  2099. iMPC = MPC_buffer[iCanEl];
  2100. for ( k = 0; k < N; k++ )
  2101. modes[ ( N*label ) +k] = ( modes_buffer[ ( N*iCanEl ) +k] ) / ( iMPC );
  2102. //assign a corresponding mode point count for this region into
  2103. //the mode point counts array using the MPC buffer...
  2104. modePointCounts[label] = MPC_buffer[iCanEl];
  2105. }
  2106. }
  2107. //re-assign region count using label counter
  2108. //int oldRegionCount = regionCount;
  2109. regionCount = label + 1;
  2110. // (c)
  2111. // Use the label buffer to reconstruct the label map, which specified
  2112. // the new image given its new regions calculated above
  2113. for ( i = 0; i < height*width; i++ )
  2114. labels[i] = label_buffer[raList[labels[i]].label];
  2115. //de-allocate memory
  2116. delete [] modes_buffer;
  2117. delete [] MPC_buffer;
  2118. delete [] label_buffer;
  2119. //done.
  2120. return;
  2121. }
  2122. /*******************************************************/
  2123. /*Compute Edge Strengths */
  2124. /*******************************************************/
  2125. /*Computes the a weight for each link in the region */
  2126. /*graph maintined by the RAM, resulting in a weighted */
  2127. /*graph in which the weights consist of a confidence */
  2128. /*between zero and one indicating if the regions are */
  2129. /*separated by a strong or weak edge. */
  2130. /*******************************************************/
  2131. /*Post: */
  2132. /* - an edge strength has been computed between */
  2133. /* each region of the image and placed as a */
  2134. /* weight in the RAM to be used during transi- */
  2135. /* tive closure. */
  2136. /*******************************************************/
  2137. void msImageProcessor::ComputeEdgeStrengths ( void )
  2138. {
  2139. //initialize visit table - used to keep track
  2140. //of which pixels have already been visited such
  2141. //as not to contribute their strength value to
  2142. //a boundary sum multiple times...
  2143. memset ( visitTable, 0, L*sizeof ( unsigned char ) );
  2144. //traverse labeled image computing edge strengths
  2145. //(excluding image boundary)...
  2146. int x, y, dp, curLabel, rightLabel, bottomLabel;
  2147. RAList *curRegion;
  2148. for ( y = 1; y < height - 1; y++ )
  2149. {
  2150. for ( x = 1; x < width - 1; x++ )
  2151. {
  2152. //compute data point location using x and y
  2153. dp = y * width + x;
  2154. //obtain labels at different pixel locations
  2155. curLabel = labels[dp ]; //current pixel
  2156. rightLabel = labels[dp+1 ]; //right pixel
  2157. bottomLabel = labels[dp+width]; //bottom pixel
  2158. //check right and bottom neighbor to see if there is a
  2159. //change in label then we are at an edge therefore record
  2160. //the edge strength at this edge accumulating its value
  2161. //in the RAM...
  2162. if ( curLabel != rightLabel )
  2163. {
  2164. //traverse into RAM...
  2165. curRegion = &raList[curLabel];
  2166. while ( ( curRegion ) && ( curRegion->label != rightLabel ) )
  2167. curRegion = curRegion->next;
  2168. //this should not occur...
  2169. assert ( curRegion );
  2170. //accumulate edge strength
  2171. curRegion->edgeStrength += weightMap[dp] + weightMap[dp+1];
  2172. curRegion->edgePixelCount += 2;
  2173. }
  2174. if ( curLabel != bottomLabel )
  2175. {
  2176. //traverse into RAM...
  2177. curRegion = &raList[curLabel];
  2178. while ( ( curRegion ) && ( curRegion->label != bottomLabel ) )
  2179. curRegion = curRegion->next;
  2180. //this should not occur...
  2181. assert ( curRegion );
  2182. //accumulate edge strength
  2183. if ( curLabel == rightLabel )
  2184. {
  2185. curRegion->edgeStrength += weightMap[dp] + weightMap[dp+width];
  2186. curRegion->edgePixelCount += 2;
  2187. }
  2188. else
  2189. {
  2190. curRegion->edgeStrength += weightMap[dp+width];
  2191. curRegion->edgePixelCount += 1;
  2192. }
  2193. }
  2194. }
  2195. }
  2196. //compute strengths using accumulated strengths obtained above...
  2197. RAList *neighborRegion;
  2198. float edgeStrength;
  2199. int edgePixelCount;
  2200. for ( x = 0; x < regionCount; x++ )
  2201. {
  2202. //traverse the region list of the current region
  2203. curRegion = &raList[x];
  2204. curRegion = curRegion->next;
  2205. while ( curRegion )
  2206. {
  2207. //with the assumption that regions having a smaller
  2208. //label in the current region list have already
  2209. //had their edge strengths computed, only compute
  2210. //edge strengths for the regions whose label is greater
  2211. //than x, the current region (region list) under
  2212. //consideration...
  2213. curLabel = curRegion->label;
  2214. if ( curLabel > x )
  2215. {
  2216. //obtain pointer to the element identifying the
  2217. //current region in the neighbors region list...
  2218. neighborRegion = &raList[curLabel];
  2219. while ( ( neighborRegion ) && ( neighborRegion->label != x ) )
  2220. neighborRegion = neighborRegion->next;
  2221. //this should not occur...
  2222. assert ( neighborRegion );
  2223. //compute edge strengths using accumulated confidence
  2224. //value and pixel count
  2225. if ( ( edgePixelCount = curRegion->edgePixelCount + neighborRegion->edgePixelCount ) != 0 )
  2226. {
  2227. //compute edge strength
  2228. edgeStrength = curRegion->edgeStrength + neighborRegion->edgeStrength;
  2229. edgeStrength /= edgePixelCount;
  2230. //store edge strength and pixel count for corresponding regions
  2231. curRegion->edgeStrength = neighborRegion->edgeStrength = edgeStrength;
  2232. curRegion->edgePixelCount = neighborRegion->edgePixelCount = edgePixelCount;
  2233. }
  2234. }
  2235. //traverse to the next region in the region adjacency list
  2236. //of the current region x
  2237. curRegion = curRegion->next;
  2238. }
  2239. }
  2240. //compute average edge strength amongst the edges connecting
  2241. //it to each of its neighbors
  2242. int numNeighbors;
  2243. for ( x = 0; x < regionCount; x++ )
  2244. {
  2245. //traverse the region list of the current region
  2246. //accumulating weights
  2247. curRegion = &raList[x];
  2248. curRegion = curRegion->next;
  2249. edgeStrength = 0;
  2250. numNeighbors = 0;
  2251. while ( curRegion )
  2252. {
  2253. numNeighbors++;
  2254. edgeStrength += curRegion->edgeStrength;
  2255. curRegion = curRegion->next;
  2256. }
  2257. //divide by the number of regions connected
  2258. //to the current region
  2259. if ( numNeighbors ) edgeStrength /= numNeighbors;
  2260. //store the result in the raList for region
  2261. //x
  2262. raList[x].edgeStrength = edgeStrength;
  2263. }
  2264. //traverse raList and output the resulting list
  2265. //to a file
  2266. //done.
  2267. return;
  2268. }
  2269. /*******************************************************/
  2270. /*Prune */
  2271. /*******************************************************/
  2272. /*Prunes regions from the image whose pixel density */
  2273. /*is less than a specified threshold. */
  2274. /*******************************************************/
  2275. /*Pre: */
  2276. /* - minRegion is the minimum allowable pixel de- */
  2277. /* nsity a region may have without being pruned */
  2278. /* from the image */
  2279. /*Post: */
  2280. /* - regions whose pixel density is less than */
  2281. /* or equal to minRegion have been pruned from */
  2282. /* the image. */
  2283. /*******************************************************/
  2284. void msImageProcessor::Prune ( int minRegion )
  2285. {
  2286. //Allocate Memory for temporary buffers...
  2287. //allocate memory for mode and point count temporary buffers...
  2288. float *modes_buffer = new float [N*regionCount];
  2289. int *MPC_buffer = new int [regionCount];
  2290. //allocate memory for label buffer
  2291. int *label_buffer = new int [regionCount];
  2292. //Declare variables
  2293. int i, k, candidate, iCanEl, neighCanEl, iMPC, label, oldRegionCount, minRegionCount;
  2294. double minSqDistance, neighborDistance;
  2295. RAList *neighbor;
  2296. //Apply pruning algorithm to classification structure, removing all regions whose area
  2297. //is under the threshold area minRegion (pixels)
  2298. do
  2299. {
  2300. //Assume that no region has area under threshold area of
  2301. minRegionCount = 0;
  2302. //Step (1):
  2303. // Build RAM using classifiction structure originally
  2304. // generated by the method GridTable::Connect()
  2305. BuildRAM();
  2306. // Step (2):
  2307. // Traverse the RAM joining regions whose area is less than minRegion (pixels)
  2308. // with its respective candidate region.
  2309. // A candidate region is a region that displays the following properties:
  2310. // - it is adjacent to the region being pruned
  2311. // - the distance of its mode is a minimum to that of the region being pruned
  2312. // such that or it is the only adjacent region having an area greater than
  2313. // minRegion
  2314. for ( i = 0; i < regionCount; i++ )
  2315. {
  2316. //if the area of the ith region is less than minRegion
  2317. //join it with its candidate region...
  2318. //*******************************************************************************
  2319. //Note: Adjust this if statement if a more sophisticated pruning criterion
  2320. // is desired. Basically in this step a region whose area is less than
  2321. // minRegion is pruned by joining it with its "closest" neighbor (in color).
  2322. // Therefore, by placing a different criterion for fusing a region the
  2323. // pruning method may be altered to implement a more sophisticated algorithm.
  2324. //*******************************************************************************
  2325. if ( modePointCounts[i] < minRegion )
  2326. {
  2327. //update minRegionCount to indicate that a region
  2328. //having area less than minRegion was found
  2329. minRegionCount++;
  2330. //obtain a pointer to the first region in the
  2331. //region adjacency list of the ith region...
  2332. neighbor = raList[i].next;
  2333. //calculate the distance between the mode of the ith
  2334. //region and that of the neighboring region...
  2335. candidate = neighbor->label;
  2336. minSqDistance = SqDistance ( i, candidate );
  2337. //traverse region adjacency list of region i and select
  2338. //a candidate region
  2339. neighbor = neighbor->next;
  2340. while ( neighbor )
  2341. {
  2342. //calculate the square distance between region i
  2343. //and current neighbor...
  2344. neighborDistance = SqDistance ( i, neighbor->label );
  2345. //if this neighbors square distance to region i is less
  2346. //than minSqDistance, then select this neighbor as the
  2347. //candidate region for region i
  2348. if ( neighborDistance < minSqDistance )
  2349. {
  2350. minSqDistance = neighborDistance;
  2351. candidate = neighbor->label;
  2352. }
  2353. //traverse region list of region i
  2354. neighbor = neighbor->next;
  2355. }
  2356. //join region i with its candidate region:
  2357. // (1) find the canonical element of region i
  2358. iCanEl = i;
  2359. while ( raList[iCanEl].label != iCanEl )
  2360. iCanEl = raList[iCanEl].label;
  2361. // (2) find the canonical element of neighboring region
  2362. neighCanEl = candidate;
  2363. while ( raList[neighCanEl].label != neighCanEl )
  2364. neighCanEl = raList[neighCanEl].label;
  2365. // if the canonical elements of are not the same then assign
  2366. // the canonical element having the smaller label to be the parent
  2367. // of the other region...
  2368. if ( iCanEl < neighCanEl )
  2369. raList[neighCanEl].label = iCanEl;
  2370. else
  2371. {
  2372. //must replace the canonical element of previous
  2373. //parent as well
  2374. raList[raList[iCanEl].label].label = neighCanEl;
  2375. //re-assign canonical element
  2376. raList[iCanEl].label = neighCanEl;
  2377. }
  2378. }
  2379. }
  2380. // Step (3):
  2381. // Level binary trees formed by canonical elements
  2382. for ( i = 0; i < regionCount; i++ )
  2383. {
  2384. iCanEl = i;
  2385. while ( raList[iCanEl].label != iCanEl )
  2386. iCanEl = raList[iCanEl].label;
  2387. raList[i].label = iCanEl;
  2388. }
  2389. // Step (4):
  2390. //Traverse joint sets, relabeling image.
  2391. // Accumulate modes and re-compute point counts using canonical
  2392. // elements generated by step 2.
  2393. //initialize buffers to zero
  2394. for ( i = 0; i < regionCount; i++ )
  2395. MPC_buffer[i] = 0;
  2396. for ( i = 0; i < N*regionCount; i++ )
  2397. modes_buffer[i] = 0;
  2398. //traverse raList accumulating modes and point counts
  2399. //using canoncial element information...
  2400. for ( i = 0; i < regionCount; i++ )
  2401. {
  2402. //obtain canonical element of region i
  2403. iCanEl = raList[i].label;
  2404. //obtain mode point count of region i
  2405. iMPC = modePointCounts[i];
  2406. //accumulate modes_buffer[iCanEl]
  2407. for ( k = 0; k < N; k++ )
  2408. modes_buffer[ ( N*iCanEl ) +k] += iMPC * modes[ ( N*i ) +k];
  2409. //accumulate MPC_buffer[iCanEl]
  2410. MPC_buffer[iCanEl] += iMPC;
  2411. }
  2412. // (b)
  2413. // Re-label new regions of the image using the canonical
  2414. // element information generated by step (2)
  2415. // Also use this information to compute the modes of the newly
  2416. // defined regions, and to assign new region point counts in
  2417. // a consecute manner to the modePointCounts array
  2418. //initialize label buffer to -1
  2419. for ( i = 0; i < regionCount; i++ )
  2420. label_buffer[i] = -1;
  2421. //traverse raList re-labeling the regions
  2422. label = -1;
  2423. for ( i = 0; i < regionCount; i++ )
  2424. {
  2425. //obtain canonical element of region i
  2426. iCanEl = raList[i].label;
  2427. if ( label_buffer[iCanEl] < 0 )
  2428. {
  2429. //assign a label to the new region indicated by canonical
  2430. //element of i
  2431. label_buffer[iCanEl] = ++label;
  2432. //recompute mode storing the result in modes[label]...
  2433. iMPC = MPC_buffer[iCanEl];
  2434. for ( k = 0; k < N; k++ )
  2435. modes[ ( N*label ) +k] = ( modes_buffer[ ( N*iCanEl ) +k] ) / ( iMPC );
  2436. //assign a corresponding mode point count for this region into
  2437. //the mode point counts array using the MPC buffer...
  2438. modePointCounts[label] = MPC_buffer[iCanEl];
  2439. }
  2440. }
  2441. //re-assign region count using label counter
  2442. oldRegionCount = regionCount;
  2443. regionCount = label + 1;
  2444. // (c)
  2445. // Use the label buffer to reconstruct the label map, which specified
  2446. // the new image given its new regions calculated above
  2447. for ( i = 0; i < height*width; i++ )
  2448. labels[i] = label_buffer[raList[labels[i]].label];
  2449. } while ( minRegionCount > 0 );
  2450. //de-allocate memory
  2451. delete [] modes_buffer;
  2452. delete [] MPC_buffer;
  2453. delete [] label_buffer;
  2454. //done.
  2455. return;
  2456. }
  2457. /*******************************************************/
  2458. /*Define Boundaries */
  2459. /*******************************************************/
  2460. /*Defines the boundaries for each region of the segm- */
  2461. /*ented image storing the result into a region list */
  2462. /*object. */
  2463. /*******************************************************/
  2464. /*Pre: */
  2465. /* - the image has been segmented and a classifi- */
  2466. /* cation structure has been created for this */
  2467. /* image */
  2468. /*Post: */
  2469. /* - the boundaries of the segmented image have */
  2470. /* been defined and the boundaries of each reg- */
  2471. /* ion has been stored into a region list obj- */
  2472. /* ect. */
  2473. /*******************************************************/
  2474. void msImageProcessor::DefineBoundaries ( void )
  2475. {
  2476. //declare and allocate memory for boundary map and count
  2477. int *boundaryMap, *boundaryCount;
  2478. if ( ( ! ( boundaryMap = new int [L] ) ) || ( ! ( boundaryCount = new int [regionCount] ) ) )
  2479. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "DefineBoundaries", ( char* ) "Not enough memory." );
  2480. //initialize boundary map and count
  2481. int i;
  2482. for ( i = 0; i < L; i++ )
  2483. boundaryMap[i] = -1;
  2484. for ( i = 0; i < regionCount; i++ )
  2485. boundaryCount[i] = 0;
  2486. //initialize and declare total boundary count -
  2487. //the total number of boundary pixels present in
  2488. //the segmented image
  2489. int totalBoundaryCount = 0;
  2490. //traverse the image checking the right and bottom
  2491. //four connected neighbors of each pixel marking
  2492. //boundary map with the boundaries of each region and
  2493. //incrementing boundaryCount using the label information
  2494. //***********************************************************************
  2495. //***********************************************************************
  2496. int j, label, dataPoint;
  2497. //first row (every pixel is a boundary pixel)
  2498. for ( i = 0; i < width; i++ )
  2499. {
  2500. boundaryMap[i] = label = labels[i];
  2501. boundaryCount[label]++;
  2502. totalBoundaryCount++;
  2503. }
  2504. //define boundaries for all rows except for the first
  2505. //and last one...
  2506. for ( i = 1; i < height - 1; i++ )
  2507. {
  2508. //mark the first pixel in an image row as an image boundary...
  2509. dataPoint = i * width;
  2510. boundaryMap[dataPoint] = label = labels[dataPoint];
  2511. boundaryCount[label]++;
  2512. totalBoundaryCount++;
  2513. for ( j = 1; j < width - 1; j++ )
  2514. {
  2515. //define datapoint and its right and bottom
  2516. //four connected neighbors
  2517. dataPoint = i * width + j;
  2518. //check four connected neighbors if they are
  2519. //different this pixel is a boundary pixel
  2520. label = labels[dataPoint];
  2521. if ( ( label != labels[dataPoint-1] ) || ( label != labels[dataPoint+1] ) ||
  2522. ( label != labels[dataPoint-width] ) || ( label != labels[dataPoint+width] ) )
  2523. {
  2524. boundaryMap[dataPoint] = label = labels[dataPoint];
  2525. boundaryCount[label]++;
  2526. totalBoundaryCount++;
  2527. }
  2528. }
  2529. //mark the last pixel in an image row as an image boundary...
  2530. dataPoint = ( i + 1 ) * width - 1;
  2531. boundaryMap[dataPoint] = label = labels[dataPoint];
  2532. boundaryCount[label]++;
  2533. totalBoundaryCount++;
  2534. }
  2535. //last row (every pixel is a boundary pixel) (i = height-1)
  2536. register int start = ( height - 1 ) * width, stop = height * width;
  2537. for ( i = start; i < stop; i++ )
  2538. {
  2539. boundaryMap[i] = label = labels[i];
  2540. boundaryCount[label]++;
  2541. totalBoundaryCount++;
  2542. }
  2543. //***********************************************************************
  2544. //***********************************************************************
  2545. //store boundary locations into a boundary buffer using
  2546. //boundary map and count
  2547. //***********************************************************************
  2548. //***********************************************************************
  2549. int *boundaryBuffer = new int [totalBoundaryCount], *boundaryIndex = new int [regionCount];
  2550. //use boundary count to initialize boundary index...
  2551. int counter = 0;
  2552. for ( i = 0; i < regionCount; i++ )
  2553. {
  2554. boundaryIndex[i] = counter;
  2555. counter += boundaryCount[i];
  2556. }
  2557. //traverse boundary map placing the boundary pixel
  2558. //locations into the boundaryBuffer
  2559. for ( i = 0; i < L; i++ )
  2560. {
  2561. //if its a boundary pixel store it into
  2562. //the boundary buffer
  2563. if ( ( label = boundaryMap[i] ) >= 0 )
  2564. {
  2565. boundaryBuffer[boundaryIndex[label]] = i;
  2566. boundaryIndex[label]++;
  2567. }
  2568. }
  2569. //***********************************************************************
  2570. //***********************************************************************
  2571. //store the boundary locations stored by boundaryBuffer into
  2572. //the region list for each region
  2573. //***********************************************************************
  2574. //***********************************************************************
  2575. //destroy the old region list
  2576. if ( regionList ) delete regionList;
  2577. //create a new region list
  2578. if ( ! ( regionList = new RegionList ( regionCount, totalBoundaryCount, N ) ) )
  2579. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "DefineBoundaries", ( char* ) "Not enough memory." );
  2580. //add boundary locations for each region using the boundary
  2581. //buffer and boundary counts
  2582. counter = 0;
  2583. for ( i = 0; i < regionCount; i++ )
  2584. {
  2585. regionList->AddRegion ( i, boundaryCount[i], &boundaryBuffer[counter] );
  2586. counter += boundaryCount[i];
  2587. }
  2588. //***********************************************************************
  2589. //***********************************************************************
  2590. // dealocate local used memory
  2591. delete [] boundaryMap;
  2592. delete [] boundaryCount;
  2593. delete [] boundaryBuffer;
  2594. delete [] boundaryIndex;
  2595. //done.
  2596. return;
  2597. }
  2598. /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
  2599. /* Image Data Searching/Distance Calculation */
  2600. /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/
  2601. /*******************************************************/
  2602. /*In Window */
  2603. /*******************************************************/
  2604. /*Returns true if the two specified data points are */
  2605. /*within rR of each other. */
  2606. /*******************************************************/
  2607. /*Pre: */
  2608. /* - mode1 and mode2 are indeces into msRawData */
  2609. /* specifying the modes of the pixels having */
  2610. /* these indeces. */
  2611. /*Post: */
  2612. /* - true is returned if mode1 and mode2 are wi- */
  2613. /* thin rR of one another, false is returned */
  2614. /* otherwise. */
  2615. /*******************************************************/
  2616. bool msImageProcessor::InWindow ( int mode1, int mode2 )
  2617. {
  2618. int k = 1, s = 0, p;
  2619. double diff = 0, el;
  2620. while ( ( diff < 0.25 ) && ( k != kp ) ) // Partial Distortion Search
  2621. {
  2622. //Calculate distance squared of sub-space s
  2623. diff = 0;
  2624. for ( p = 0; p < P[k]; p++ )
  2625. {
  2626. el = ( modes[mode1*N+p+s] - modes[mode2*N+p+s] ) / ( h[k] * offset[k] );
  2627. if ( ( !p ) && ( k == 1 ) && ( modes[mode1*N] > 80 ) )
  2628. diff += 4 * el * el;
  2629. else
  2630. diff += el * el;
  2631. }
  2632. //next subspace
  2633. s += P[k];
  2634. k++;
  2635. }
  2636. return ( bool ) ( diff < 0.25 );
  2637. }
  2638. /*******************************************************/
  2639. /*Square Distance */
  2640. /*******************************************************/
  2641. /*Computs the normalized square distance between two */
  2642. /*modes. */
  2643. /*******************************************************/
  2644. /*Pre: */
  2645. /* - mode1 and mode2 are indeces into the modes */
  2646. /* array specifying two modes of the image */
  2647. /*Post: */
  2648. /* - the normalized square distance between modes */
  2649. /* indexed by mode1 and mode2 has been calc- */
  2650. /* ulated and the result has been returned. */
  2651. /*******************************************************/
  2652. float msImageProcessor::SqDistance ( int mode1, int mode2 )
  2653. {
  2654. int k = 1, s = 0, p;
  2655. float dist = 0, el;
  2656. for ( k = 1; k < kp; k++ )
  2657. {
  2658. //Calculate distance squared of sub-space s
  2659. for ( p = 0; p < P[k]; p++ )
  2660. {
  2661. el = ( modes[mode1*N+p+s] - modes[mode2*N+p+s] ) / ( h[k] * offset[k] );
  2662. dist += el * el;
  2663. }
  2664. //next subspace
  2665. s += P[k];
  2666. k++;
  2667. }
  2668. //return normalized square distance between modes
  2669. //1 and 2
  2670. return dist;
  2671. }
  2672. /*/\/\/\/\/\/\/\/\/\/\*/
  2673. /* Memory Management */
  2674. /*\/\/\/\/\/\/\/\/\/\/*/
  2675. /*******************************************************/
  2676. /*Initialize Output */
  2677. /*******************************************************/
  2678. /*Allocates memory needed by the mean shift image pro- */
  2679. /*cessor class output storage data structure. */
  2680. /*******************************************************/
  2681. /*Post: */
  2682. /* - the memory needed by the output storage */
  2683. /* structure of this class has been (re-)allo- */
  2684. /* cated. */
  2685. /*******************************************************/
  2686. void msImageProcessor::InitializeOutput ( void )
  2687. {
  2688. //De-allocate memory if output was defined for previous image
  2689. DestroyOutput();
  2690. //Allocate memory for msRawData (filtered image output)
  2691. if ( ! ( msRawData = new float [L*N] ) )
  2692. {
  2693. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Allocate", ( char* ) "Not enough memory." );
  2694. return;
  2695. }
  2696. //Allocate memory used to store image modes and their corresponding regions...
  2697. if ( ( ! ( modes = new float [L* ( N+2 ) ] ) ) || ( ! ( labels = new int [L] ) ) || ( ! ( modePointCounts = new int [L] ) ) || ( ! ( indexTable = new int [L] ) ) )
  2698. {
  2699. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Allocate", ( char* ) "Not enough memory" );
  2700. return;
  2701. }
  2702. //Allocate memory for integer modes used to perform connected components
  2703. //(image labeling)...
  2704. // if(!(LUV_data = new int [N*L]))
  2705. if ( ! ( LUV_data = new float[N*L] ) )
  2706. {
  2707. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Allocate", ( char* ) "Not enough memory" );
  2708. return;
  2709. }
  2710. //indicate that the class output storage structure has been defined
  2711. class_state.OUTPUT_DEFINED = true;
  2712. }
  2713. /*******************************************************/
  2714. /*Destroy Output */
  2715. /*******************************************************/
  2716. /*De-allocates memory needed by the mean shift image */
  2717. /*processor class output storage data structure. */
  2718. /*******************************************************/
  2719. /*Post: */
  2720. /* - the memory needed by the output storage */
  2721. /* structure of this class has been de-alloc- */
  2722. /* ated. */
  2723. /* - the output storage structure has been init- */
  2724. /* ialized for re-use. */
  2725. /*******************************************************/
  2726. void msImageProcessor::DestroyOutput ( void )
  2727. {
  2728. //de-allocate memory for msRawData (filtered image output)
  2729. if ( msRawData ) delete [] msRawData;
  2730. //de-allocate memory used by output storage and image
  2731. //classification structure
  2732. if ( modes ) delete [] modes;
  2733. if ( labels ) delete [] labels;
  2734. if ( modePointCounts ) delete [] modePointCounts;
  2735. if ( indexTable ) delete [] indexTable;
  2736. //de-allocate memory for LUV_data
  2737. if ( LUV_data ) delete [] LUV_data;
  2738. //initialize data members for re-use...
  2739. //initialize output structures...
  2740. msRawData = NULL;
  2741. //re-initialize classification structure
  2742. modes = NULL;
  2743. labels = NULL;
  2744. modePointCounts = NULL;
  2745. regionCount = 0;
  2746. //indicate that the output has been destroyed
  2747. class_state.OUTPUT_DEFINED = false;
  2748. //done.
  2749. return;
  2750. }
  2751. // NEW
  2752. void msImageProcessor::NewOptimizedFilter1 ( float sigmaS, float sigmaR )
  2753. {
  2754. // Declare Variables
  2755. int iterationCount, i, j, k, modeCandidateX, modeCandidateY, modeCandidate_i;
  2756. double mvAbs, diff, el;
  2757. //make sure that a lattice height and width have
  2758. //been defined...
  2759. if ( !height )
  2760. {
  2761. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "LFilter", ( char* ) "Lattice height and width are undefined." );
  2762. return;
  2763. }
  2764. //re-assign bandwidths to sigmaS and sigmaR
  2765. if ( ( ( h[0] = sigmaS ) <= 0 ) || ( ( h[1] = sigmaR ) <= 0 ) )
  2766. {
  2767. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Segment", ( char* ) "sigmaS and/or sigmaR is zero or negative." );
  2768. return;
  2769. }
  2770. //define input data dimension with lattice
  2771. int lN = N + 2;
  2772. // Traverse each data point applying mean shift
  2773. // to each data point
  2774. // Allcocate memory for yk
  2775. double *yk = new double [lN];
  2776. // Allocate memory for Mh
  2777. double *Mh = new double [lN];
  2778. // let's use some temporary data
  2779. float* sdata;
  2780. sdata = new float[lN*L];
  2781. // copy the scaled data
  2782. int idxs, idxd;
  2783. idxs = idxd = 0;
  2784. if ( N == 3 )
  2785. {
  2786. for ( i = 0; i < L; i++ )
  2787. {
  2788. sdata[idxs++] = ( i % width ) / sigmaS;
  2789. sdata[idxs++] = ( i / width ) / sigmaS;
  2790. sdata[idxs++] = data[idxd++] / sigmaR;
  2791. sdata[idxs++] = data[idxd++] / sigmaR;
  2792. sdata[idxs++] = data[idxd++] / sigmaR;
  2793. }
  2794. } else if ( N == 1 )
  2795. {
  2796. for ( i = 0; i < L; i++ )
  2797. {
  2798. sdata[idxs++] = ( i % width ) / sigmaS;
  2799. sdata[idxs++] = ( i / width ) / sigmaS;
  2800. sdata[idxs++] = data[idxd++] / sigmaR;
  2801. }
  2802. } else
  2803. {
  2804. for ( i = 0; i < L; i++ )
  2805. {
  2806. sdata[idxs++] = ( i % width ) / sigmaS;
  2807. sdata[idxs++] = ( i / width ) / sigmaS;
  2808. for ( j = 0; j < N; j++ )
  2809. sdata[idxs++] = data[idxd++] / sigmaR;
  2810. }
  2811. }
  2812. // index the data in the 3d buckets (x, y, L)
  2813. int* buckets;
  2814. int* slist;
  2815. slist = new int[L];
  2816. int bucNeigh[27];
  2817. float sMins; // just for L
  2818. float sMaxs[3]; // for all
  2819. sMaxs[0] = width / sigmaS;
  2820. sMaxs[1] = height / sigmaS;
  2821. sMins = sMaxs[2] = sdata[2];
  2822. idxs = 2;
  2823. float cval;
  2824. for ( i = 0; i < L; i++ )
  2825. {
  2826. cval = sdata[idxs];
  2827. if ( cval < sMins )
  2828. sMins = cval;
  2829. else if ( cval > sMaxs[2] )
  2830. sMaxs[2] = cval;
  2831. idxs += lN;
  2832. }
  2833. int nBuck1, nBuck2, nBuck3;
  2834. int cBuck1, cBuck2, cBuck3, cBuck;
  2835. nBuck1 = ( int ) ( sMaxs[0] + 3 );
  2836. nBuck2 = ( int ) ( sMaxs[1] + 3 );
  2837. nBuck3 = ( int ) ( sMaxs[2] - sMins + 3 );
  2838. buckets = new int[nBuck1*nBuck2*nBuck3];
  2839. for ( i = 0; i < ( nBuck1*nBuck2*nBuck3 ); i++ )
  2840. buckets[i] = -1;
  2841. idxs = 0;
  2842. for ( i = 0; i < L; i++ )
  2843. {
  2844. // find bucket for current data and add it to the list
  2845. cBuck1 = ( int ) sdata[idxs] + 1;
  2846. cBuck2 = ( int ) sdata[idxs+1] + 1;
  2847. cBuck3 = ( int ) ( sdata[idxs+2] - sMins ) + 1;
  2848. idxs += lN;
  2849. cBuck = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  2850. slist[i] = buckets[cBuck];
  2851. buckets[cBuck] = i;
  2852. }
  2853. // init bucNeigh
  2854. idxd = 0;
  2855. for ( cBuck1 = -1; cBuck1 <= 1; cBuck1++ )
  2856. {
  2857. for ( cBuck2 = -1; cBuck2 <= 1; cBuck2++ )
  2858. {
  2859. for ( cBuck3 = -1; cBuck3 <= 1; cBuck3++ )
  2860. {
  2861. bucNeigh[idxd++] = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  2862. }
  2863. }
  2864. }
  2865. double wsuml, weight;
  2866. double hiLTr = 80.0 / sigmaR;
  2867. // done indexing/hashing
  2868. // Initialize mode table used for basin of attraction
  2869. memset ( modeTable, 0, width*height );
  2870. // proceed ...
  2871. #ifdef PROMPT
  2872. printf ( ( char* ) "done.\nApplying mean shift (Using Lattice) ... " );
  2873. #ifdef SHOW_PROGRESS
  2874. printf ( ( char* ) "\n 0%%" );
  2875. #endif
  2876. #endif
  2877. for ( i = 0; i < L; i++ )
  2878. {
  2879. // if a mode was already assigned to this data point
  2880. // then skip this point, otherwise proceed to
  2881. // find its mode by applying mean shift...
  2882. if ( modeTable[i] == 1 )
  2883. continue;
  2884. // initialize point list...
  2885. pointCount = 0;
  2886. // Assign window center (window centers are
  2887. // initialized by createLattice to be the point
  2888. // data[i])
  2889. idxs = i * lN;
  2890. for ( j = 0; j < lN; j++ )
  2891. yk[j] = sdata[idxs+j];
  2892. // Calculate the mean shift vector using the lattice
  2893. // LatticeMSVector(Mh, yk); // modify to new
  2894. /*****************************************************/
  2895. // Initialize mean shift vector
  2896. for ( j = 0; j < lN; j++ )
  2897. Mh[j] = 0;
  2898. wsuml = 0;
  2899. // uniformLSearch(Mh, yk_ptr); // modify to new
  2900. // find bucket of yk
  2901. cBuck1 = ( int ) yk[0] + 1;
  2902. cBuck2 = ( int ) yk[1] + 1;
  2903. cBuck3 = ( int ) ( yk[2] - sMins ) + 1;
  2904. cBuck = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  2905. for ( j = 0; j < 27; j++ )
  2906. {
  2907. idxd = buckets[cBuck+bucNeigh[j]];
  2908. // list parse, crt point is cHeadList
  2909. while ( idxd >= 0 )
  2910. {
  2911. idxs = lN * idxd;
  2912. // determine if inside search window
  2913. el = sdata[idxs+0] - yk[0];
  2914. diff = el * el;
  2915. el = sdata[idxs+1] - yk[1];
  2916. diff += el * el;
  2917. if ( diff < 1.0 )
  2918. {
  2919. el = sdata[idxs+2] - yk[2];
  2920. if ( yk[2] > hiLTr )
  2921. diff = 4 * el * el;
  2922. else
  2923. diff = el * el;
  2924. if ( N > 1 )
  2925. {
  2926. el = sdata[idxs+3] - yk[3];
  2927. diff += el * el;
  2928. el = sdata[idxs+4] - yk[4];
  2929. diff += el * el;
  2930. }
  2931. if ( diff < 1.0 )
  2932. {
  2933. weight = 1 - weightMap[idxd];
  2934. for ( k = 0; k < lN; k++ )
  2935. Mh[k] += weight * sdata[idxs+k];
  2936. wsuml += weight;
  2937. }
  2938. }
  2939. idxd = slist[idxd];
  2940. }
  2941. }
  2942. if ( wsuml > 0 )
  2943. {
  2944. for ( j = 0; j < lN; j++ )
  2945. Mh[j] = Mh[j] / wsuml - yk[j];
  2946. }
  2947. else
  2948. {
  2949. for ( j = 0; j < lN; j++ )
  2950. Mh[j] = 0;
  2951. }
  2952. /*****************************************************/
  2953. // Calculate its magnitude squared
  2954. //mvAbs = 0;
  2955. //for(j = 0; j < lN; j++)
  2956. // mvAbs += Mh[j]*Mh[j];
  2957. mvAbs = ( Mh[0] * Mh[0] + Mh[1] * Mh[1] ) * sigmaS * sigmaS;
  2958. if ( N == 3 )
  2959. mvAbs += ( Mh[2] * Mh[2] + Mh[3] * Mh[3] + Mh[4] * Mh[4] ) * sigmaR * sigmaR;
  2960. else
  2961. mvAbs += Mh[2] * Mh[2] * sigmaR * sigmaR;
  2962. // Keep shifting window center until the magnitude squared of the
  2963. // mean shift vector calculated at the window center location is
  2964. // under a specified threshold (Epsilon)
  2965. // NOTE: iteration count is for speed up purposes only - it
  2966. // does not have any theoretical importance
  2967. iterationCount = 1;
  2968. while ( ( mvAbs >= EPSILON2 ) && ( iterationCount < LIMIT ) )
  2969. {
  2970. // Shift window location
  2971. for ( j = 0; j < lN; j++ )
  2972. yk[j] += Mh[j];
  2973. // check to see if the current mode location is in the
  2974. // basin of attraction...
  2975. // calculate the location of yk on the lattice
  2976. modeCandidateX = ( int ) ( sigmaS * yk[0] + 0.5 );
  2977. modeCandidateY = ( int ) ( sigmaS * yk[1] + 0.5 );
  2978. modeCandidate_i = modeCandidateY * width + modeCandidateX;
  2979. // if mvAbs != 0 (yk did indeed move) then check
  2980. // location basin_i in the mode table to see if
  2981. // this data point either:
  2982. // (1) has not been associated with a mode yet
  2983. // (modeTable[basin_i] = 0), so associate
  2984. // it with this one
  2985. //
  2986. // (2) it has been associated with a mode other
  2987. // than the one that this data point is converging
  2988. // to (modeTable[basin_i] = 1), so assign to
  2989. // this data point the same mode as that of basin_i
  2990. if ( ( modeTable[modeCandidate_i] != 2 ) && ( modeCandidate_i != i ) )
  2991. {
  2992. // obtain the data point at basin_i to
  2993. // see if it is within h*TC_DIST_FACTOR of
  2994. // of yk
  2995. diff = 0;
  2996. idxs = lN * modeCandidate_i;
  2997. for ( k = 2; k < lN; k++ )
  2998. {
  2999. el = sdata[idxs+k] - yk[k];
  3000. diff += el * el;
  3001. }
  3002. // if the data point at basin_i is within
  3003. // a distance of h*TC_DIST_FACTOR of yk
  3004. // then depending on modeTable[basin_i] perform
  3005. // either (1) or (2)
  3006. if ( diff < TC_DIST_FACTOR )
  3007. {
  3008. // if the data point at basin_i has not
  3009. // been associated to a mode then associate
  3010. // it with the mode that this one will converge
  3011. // to
  3012. if ( modeTable[modeCandidate_i] == 0 )
  3013. {
  3014. // no mode associated yet so associate
  3015. // it with this one...
  3016. pointList[pointCount++] = modeCandidate_i;
  3017. modeTable[modeCandidate_i] = 2;
  3018. } else
  3019. {
  3020. // the mode has already been associated with
  3021. // another mode, thererfore associate this one
  3022. // mode and the modes in the point list with
  3023. // the mode associated with data[basin_i]...
  3024. // store the mode info into yk using msRawData...
  3025. for ( j = 0; j < N; j++ )
  3026. yk[j+2] = msRawData[modeCandidate_i*N+j] / sigmaR;
  3027. // update mode table for this data point
  3028. // indicating that a mode has been associated
  3029. // with it
  3030. modeTable[i] = 1;
  3031. // indicate that a mode has been associated
  3032. // to this data point (data[i])
  3033. mvAbs = -1;
  3034. // stop mean shift calculation...
  3035. break;
  3036. }
  3037. }
  3038. }
  3039. // Calculate the mean shift vector at the new
  3040. // window location using lattice
  3041. // Calculate the mean shift vector using the lattice
  3042. // LatticeMSVector(Mh, yk); // modify to new
  3043. /*****************************************************/
  3044. // Initialize mean shift vector
  3045. for ( j = 0; j < lN; j++ )
  3046. Mh[j] = 0;
  3047. wsuml = 0;
  3048. // uniformLSearch(Mh, yk_ptr); // modify to new
  3049. // find bucket of yk
  3050. cBuck1 = ( int ) yk[0] + 1;
  3051. cBuck2 = ( int ) yk[1] + 1;
  3052. cBuck3 = ( int ) ( yk[2] - sMins ) + 1;
  3053. cBuck = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  3054. for ( j = 0; j < 27; j++ )
  3055. {
  3056. idxd = buckets[cBuck+bucNeigh[j]];
  3057. // list parse, crt point is cHeadList
  3058. while ( idxd >= 0 )
  3059. {
  3060. idxs = lN * idxd;
  3061. // determine if inside search window
  3062. el = sdata[idxs+0] - yk[0];
  3063. diff = el * el;
  3064. el = sdata[idxs+1] - yk[1];
  3065. diff += el * el;
  3066. if ( diff < 1.0 )
  3067. {
  3068. el = sdata[idxs+2] - yk[2];
  3069. if ( yk[2] > hiLTr )
  3070. diff = 4 * el * el;
  3071. else
  3072. diff = el * el;
  3073. if ( N > 1 )
  3074. {
  3075. el = sdata[idxs+3] - yk[3];
  3076. diff += el * el;
  3077. el = sdata[idxs+4] - yk[4];
  3078. diff += el * el;
  3079. }
  3080. if ( diff < 1.0 )
  3081. {
  3082. weight = 1 - weightMap[idxd];
  3083. for ( k = 0; k < lN; k++ )
  3084. Mh[k] += weight * sdata[idxs+k];
  3085. wsuml += weight;
  3086. }
  3087. }
  3088. idxd = slist[idxd];
  3089. }
  3090. }
  3091. if ( wsuml > 0 )
  3092. {
  3093. for ( j = 0; j < lN; j++ )
  3094. Mh[j] = Mh[j] / wsuml - yk[j];
  3095. }
  3096. else
  3097. {
  3098. for ( j = 0; j < lN; j++ )
  3099. Mh[j] = 0;
  3100. }
  3101. /*****************************************************/
  3102. // Calculate its magnitude squared
  3103. //mvAbs = 0;
  3104. //for(j = 0; j < lN; j++)
  3105. // mvAbs += Mh[j]*Mh[j];
  3106. mvAbs = ( Mh[0] * Mh[0] + Mh[1] * Mh[1] ) * sigmaS * sigmaS;
  3107. if ( N == 3 )
  3108. mvAbs += ( Mh[2] * Mh[2] + Mh[3] * Mh[3] + Mh[4] * Mh[4] ) * sigmaR * sigmaR;
  3109. else
  3110. mvAbs += Mh[2] * Mh[2] * sigmaR * sigmaR;
  3111. // Increment iteration count
  3112. iterationCount++;
  3113. }
  3114. // if a mode was not associated with this data point
  3115. // yet associate it with yk...
  3116. if ( mvAbs >= 0 )
  3117. {
  3118. // Shift window location
  3119. for ( j = 0; j < lN; j++ )
  3120. yk[j] += Mh[j];
  3121. // update mode table for this data point
  3122. // indicating that a mode has been associated
  3123. // with it
  3124. modeTable[i] = 1;
  3125. }
  3126. for ( k = 0; k < N; k++ )
  3127. yk[k+2] *= sigmaR;
  3128. // associate the data point indexed by
  3129. // the point list with the mode stored
  3130. // by yk
  3131. for ( j = 0; j < pointCount; j++ )
  3132. {
  3133. // obtain the point location from the
  3134. // point list
  3135. modeCandidate_i = pointList[j];
  3136. // update the mode table for this point
  3137. modeTable[modeCandidate_i] = 1;
  3138. //store result into msRawData...
  3139. for ( k = 0; k < N; k++ )
  3140. msRawData[N*modeCandidate_i+k] = ( float ) ( yk[k+2] );
  3141. }
  3142. //store result into msRawData...
  3143. for ( j = 0; j < N; j++ )
  3144. msRawData[N*i+j] = ( float ) ( yk[j+2] );
  3145. // Prompt user on progress
  3146. #ifdef SHOW_PROGRESS
  3147. percent_complete = ( float ) ( i / ( float ) ( L ) ) * 100;
  3148. printf ( ( char* ) "\r%2d%%", ( int ) ( percent_complete + 0.5 ) );
  3149. #endif
  3150. // Check to see if the algorithm has been halted
  3151. if ( ( i % PROGRESS_RATE == 0 ) && ( ( ErrorStatus = msSys.Progress ( ( float ) ( i / ( float ) ( L ) ) * ( float ) ( 0.8 ) ) ) ) == EL_HALT )
  3152. break;
  3153. }
  3154. // Prompt user that filtering is completed
  3155. #ifdef PROMPT
  3156. #ifdef SHOW_PROGRESS
  3157. printf ( ( char* ) "\r" );
  3158. #endif
  3159. printf ( ( char* ) "done." );
  3160. #endif
  3161. // de-allocate memory
  3162. delete [] buckets;
  3163. delete [] slist;
  3164. delete [] sdata;
  3165. delete [] yk;
  3166. delete [] Mh;
  3167. // done.
  3168. return;
  3169. }
  3170. // NEW
  3171. void msImageProcessor::NewOptimizedFilter2 ( float sigmaS, float sigmaR )
  3172. {
  3173. // Declare Variables
  3174. int iterationCount, i, j, k, modeCandidateX, modeCandidateY, modeCandidate_i;
  3175. double mvAbs, diff, el;
  3176. //make sure that a lattice height and width have
  3177. //been defined...
  3178. if ( !height )
  3179. {
  3180. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "LFilter", ( char* ) "Lattice height and width are undefined." );
  3181. return;
  3182. }
  3183. //re-assign bandwidths to sigmaS and sigmaR
  3184. if ( ( ( h[0] = sigmaS ) <= 0 ) || ( ( h[1] = sigmaR ) <= 0 ) )
  3185. {
  3186. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Segment", ( char* ) "sigmaS and/or sigmaR is zero or negative." );
  3187. return;
  3188. }
  3189. //define input data dimension with lattice
  3190. int lN = N + 2;
  3191. // Traverse each data point applying mean shift
  3192. // to each data point
  3193. // Allcocate memory for yk
  3194. double *yk = new double [lN];
  3195. // Allocate memory for Mh
  3196. double *Mh = new double [lN];
  3197. // let's use some temporary data
  3198. float* sdata;
  3199. sdata = new float[lN*L];
  3200. // copy the scaled data
  3201. int idxs, idxd;
  3202. idxs = idxd = 0;
  3203. if ( N == 3 )
  3204. {
  3205. for ( i = 0; i < L; i++ )
  3206. {
  3207. sdata[idxs++] = ( i % width ) / sigmaS;
  3208. sdata[idxs++] = ( i / width ) / sigmaS;
  3209. sdata[idxs++] = data[idxd++] / sigmaR;
  3210. sdata[idxs++] = data[idxd++] / sigmaR;
  3211. sdata[idxs++] = data[idxd++] / sigmaR;
  3212. }
  3213. } else if ( N == 1 )
  3214. {
  3215. for ( i = 0; i < L; i++ )
  3216. {
  3217. sdata[idxs++] = ( i % width ) / sigmaS;
  3218. sdata[idxs++] = ( i / width ) / sigmaS;
  3219. sdata[idxs++] = data[idxd++] / sigmaR;
  3220. }
  3221. } else
  3222. {
  3223. for ( i = 0; i < L; i++ )
  3224. {
  3225. sdata[idxs++] = ( i % width ) / sigmaS;
  3226. sdata[idxs++] = ( i / width ) / sigmaS;
  3227. for ( j = 0; j < N; j++ )
  3228. sdata[idxs++] = data[idxd++] / sigmaR;
  3229. }
  3230. }
  3231. // index the data in the 3d buckets (x, y, L)
  3232. int* buckets;
  3233. int* slist;
  3234. slist = new int[L];
  3235. int bucNeigh[27];
  3236. float sMins; // just for L
  3237. float sMaxs[3]; // for all
  3238. sMaxs[0] = width / sigmaS;
  3239. sMaxs[1] = height / sigmaS;
  3240. sMins = sMaxs[2] = sdata[2];
  3241. idxs = 2;
  3242. float cval;
  3243. for ( i = 0; i < L; i++ )
  3244. {
  3245. cval = sdata[idxs];
  3246. if ( cval < sMins )
  3247. sMins = cval;
  3248. else if ( cval > sMaxs[2] )
  3249. sMaxs[2] = cval;
  3250. idxs += lN;
  3251. }
  3252. int nBuck1, nBuck2, nBuck3;
  3253. int cBuck1, cBuck2, cBuck3, cBuck;
  3254. nBuck1 = ( int ) ( sMaxs[0] + 3 );
  3255. nBuck2 = ( int ) ( sMaxs[1] + 3 );
  3256. nBuck3 = ( int ) ( sMaxs[2] - sMins + 3 );
  3257. buckets = new int[nBuck1*nBuck2*nBuck3];
  3258. for ( i = 0; i < ( nBuck1*nBuck2*nBuck3 ); i++ )
  3259. buckets[i] = -1;
  3260. idxs = 0;
  3261. for ( i = 0; i < L; i++ )
  3262. {
  3263. // find bucket for current data and add it to the list
  3264. cBuck1 = ( int ) sdata[idxs] + 1;
  3265. cBuck2 = ( int ) sdata[idxs+1] + 1;
  3266. cBuck3 = ( int ) ( sdata[idxs+2] - sMins ) + 1;
  3267. cBuck = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  3268. slist[i] = buckets[cBuck];
  3269. buckets[cBuck] = i;
  3270. idxs += lN;
  3271. }
  3272. // init bucNeigh
  3273. idxd = 0;
  3274. for ( cBuck1 = -1; cBuck1 <= 1; cBuck1++ )
  3275. {
  3276. for ( cBuck2 = -1; cBuck2 <= 1; cBuck2++ )
  3277. {
  3278. for ( cBuck3 = -1; cBuck3 <= 1; cBuck3++ )
  3279. {
  3280. bucNeigh[idxd++] = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  3281. }
  3282. }
  3283. }
  3284. double wsuml, weight;
  3285. double hiLTr = 80.0 / sigmaR;
  3286. // done indexing/hashing
  3287. // Initialize mode table used for basin of attraction
  3288. memset ( modeTable, 0, width*height );
  3289. // proceed ...
  3290. #ifdef PROMPT
  3291. printf ( ( char* ) "done.\nApplying mean shift (Using Lattice) ... " );
  3292. #ifdef SHOW_PROGRESS
  3293. printf ( ( char* ) "\n 0%%" );
  3294. #endif
  3295. #endif
  3296. for ( i = 0; i < L; i++ )
  3297. {
  3298. // if a mode was already assigned to this data point
  3299. // then skip this point, otherwise proceed to
  3300. // find its mode by applying mean shift...
  3301. if ( modeTable[i] == 1 )
  3302. continue;
  3303. // initialize point list...
  3304. pointCount = 0;
  3305. // Assign window center (window centers are
  3306. // initialized by createLattice to be the point
  3307. // data[i])
  3308. idxs = i * lN;
  3309. for ( j = 0; j < lN; j++ )
  3310. yk[j] = sdata[idxs+j];
  3311. // Calculate the mean shift vector using the lattice
  3312. // LatticeMSVector(Mh, yk); // modify to new
  3313. /*****************************************************/
  3314. // Initialize mean shift vector
  3315. for ( j = 0; j < lN; j++ )
  3316. Mh[j] = 0;
  3317. wsuml = 0;
  3318. // uniformLSearch(Mh, yk_ptr); // modify to new
  3319. // find bucket of yk
  3320. cBuck1 = ( int ) yk[0] + 1;
  3321. cBuck2 = ( int ) yk[1] + 1;
  3322. cBuck3 = ( int ) ( yk[2] - sMins ) + 1;
  3323. cBuck = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  3324. for ( j = 0; j < 27; j++ )
  3325. {
  3326. idxd = buckets[cBuck+bucNeigh[j]];
  3327. // list parse, crt point is cHeadList
  3328. while ( idxd >= 0 )
  3329. {
  3330. idxs = lN * idxd;
  3331. // determine if inside search window
  3332. el = sdata[idxs+0] - yk[0];
  3333. diff = el * el;
  3334. el = sdata[idxs+1] - yk[1];
  3335. diff += el * el;
  3336. if ( diff < 1.0 )
  3337. {
  3338. el = sdata[idxs+2] - yk[2];
  3339. if ( yk[2] > hiLTr )
  3340. diff = 4 * el * el;
  3341. else
  3342. diff = el * el;
  3343. if ( N > 1 )
  3344. {
  3345. el = sdata[idxs+3] - yk[3];
  3346. diff += el * el;
  3347. el = sdata[idxs+4] - yk[4];
  3348. diff += el * el;
  3349. }
  3350. if ( diff < 1.0 )
  3351. {
  3352. weight = 1 - weightMap[idxd];
  3353. for ( k = 0; k < lN; k++ )
  3354. Mh[k] += weight * sdata[idxs+k];
  3355. wsuml += weight;
  3356. //set basin of attraction mode table
  3357. if ( diff < speedThreshold )
  3358. {
  3359. if ( modeTable[idxd] == 0 )
  3360. {
  3361. pointList[pointCount++] = idxd;
  3362. modeTable[idxd] = 2;
  3363. }
  3364. }
  3365. }
  3366. }
  3367. idxd = slist[idxd];
  3368. }
  3369. }
  3370. if ( wsuml > 0 )
  3371. {
  3372. for ( j = 0; j < lN; j++ )
  3373. Mh[j] = Mh[j] / wsuml - yk[j];
  3374. }
  3375. else
  3376. {
  3377. for ( j = 0; j < lN; j++ )
  3378. Mh[j] = 0;
  3379. }
  3380. /*****************************************************/
  3381. // Calculate its magnitude squared
  3382. //mvAbs = 0;
  3383. //for(j = 0; j < lN; j++)
  3384. // mvAbs += Mh[j]*Mh[j];
  3385. mvAbs = ( Mh[0] * Mh[0] + Mh[1] * Mh[1] ) * sigmaS * sigmaS;
  3386. if ( N == 3 )
  3387. mvAbs += ( Mh[2] * Mh[2] + Mh[3] * Mh[3] + Mh[4] * Mh[4] ) * sigmaR * sigmaR;
  3388. else
  3389. mvAbs += Mh[2] * Mh[2] * sigmaR * sigmaR;
  3390. // Keep shifting window center until the magnitude squared of the
  3391. // mean shift vector calculated at the window center location is
  3392. // under a specified threshold (Epsilon)
  3393. // NOTE: iteration count is for speed up purposes only - it
  3394. // does not have any theoretical importance
  3395. iterationCount = 1;
  3396. while ( ( mvAbs >= EPSILON2 ) && ( iterationCount < LIMIT ) )
  3397. {
  3398. // Shift window location
  3399. for ( j = 0; j < lN; j++ )
  3400. yk[j] += Mh[j];
  3401. // check to see if the current mode location is in the
  3402. // basin of attraction...
  3403. // calculate the location of yk on the lattice
  3404. modeCandidateX = ( int ) ( sigmaS * yk[0] + 0.5 );
  3405. modeCandidateY = ( int ) ( sigmaS * yk[1] + 0.5 );
  3406. modeCandidate_i = modeCandidateY * width + modeCandidateX;
  3407. // if mvAbs != 0 (yk did indeed move) then check
  3408. // location basin_i in the mode table to see if
  3409. // this data point either:
  3410. // (1) has not been associated with a mode yet
  3411. // (modeTable[basin_i] = 0), so associate
  3412. // it with this one
  3413. //
  3414. // (2) it has been associated with a mode other
  3415. // than the one that this data point is converging
  3416. // to (modeTable[basin_i] = 1), so assign to
  3417. // this data point the same mode as that of basin_i
  3418. if ( ( modeTable[modeCandidate_i] != 2 ) && ( modeCandidate_i != i ) )
  3419. {
  3420. // obtain the data point at basin_i to
  3421. // see if it is within h*TC_DIST_FACTOR of
  3422. // of yk
  3423. diff = 0;
  3424. idxs = lN * modeCandidate_i;
  3425. for ( k = 2; k < lN; k++ )
  3426. {
  3427. el = sdata[idxs+k] - yk[k];
  3428. diff += el * el;
  3429. }
  3430. // if the data point at basin_i is within
  3431. // a distance of h*TC_DIST_FACTOR of yk
  3432. // then depending on modeTable[basin_i] perform
  3433. // either (1) or (2)
  3434. if ( diff < speedThreshold )
  3435. {
  3436. // if the data point at basin_i has not
  3437. // been associated to a mode then associate
  3438. // it with the mode that this one will converge
  3439. // to
  3440. if ( modeTable[modeCandidate_i] == 0 )
  3441. {
  3442. // no mode associated yet so associate
  3443. // it with this one...
  3444. pointList[pointCount++] = modeCandidate_i;
  3445. modeTable[modeCandidate_i] = 2;
  3446. } else
  3447. {
  3448. // the mode has already been associated with
  3449. // another mode, thererfore associate this one
  3450. // mode and the modes in the point list with
  3451. // the mode associated with data[basin_i]...
  3452. // store the mode info into yk using msRawData...
  3453. for ( j = 0; j < N; j++ )
  3454. yk[j+2] = msRawData[modeCandidate_i*N+j] / sigmaR;
  3455. // update mode table for this data point
  3456. // indicating that a mode has been associated
  3457. // with it
  3458. modeTable[i] = 1;
  3459. // indicate that a mode has been associated
  3460. // to this data point (data[i])
  3461. mvAbs = -1;
  3462. // stop mean shift calculation...
  3463. break;
  3464. }
  3465. }
  3466. }
  3467. // Calculate the mean shift vector at the new
  3468. // window location using lattice
  3469. // Calculate the mean shift vector using the lattice
  3470. // LatticeMSVector(Mh, yk); // modify to new
  3471. /*****************************************************/
  3472. // Initialize mean shift vector
  3473. for ( j = 0; j < lN; j++ )
  3474. Mh[j] = 0;
  3475. wsuml = 0;
  3476. // uniformLSearch(Mh, yk_ptr); // modify to new
  3477. // find bucket of yk
  3478. cBuck1 = ( int ) yk[0] + 1;
  3479. cBuck2 = ( int ) yk[1] + 1;
  3480. cBuck3 = ( int ) ( yk[2] - sMins ) + 1;
  3481. cBuck = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  3482. for ( j = 0; j < 27; j++ )
  3483. {
  3484. idxd = buckets[cBuck+bucNeigh[j]];
  3485. // list parse, crt point is cHeadList
  3486. while ( idxd >= 0 )
  3487. {
  3488. idxs = lN * idxd;
  3489. // determine if inside search window
  3490. el = sdata[idxs+0] - yk[0];
  3491. diff = el * el;
  3492. el = sdata[idxs+1] - yk[1];
  3493. diff += el * el;
  3494. if ( diff < 1.0 )
  3495. {
  3496. el = sdata[idxs+2] - yk[2];
  3497. if ( yk[2] > hiLTr )
  3498. diff = 4 * el * el;
  3499. else
  3500. diff = el * el;
  3501. if ( N > 1 )
  3502. {
  3503. el = sdata[idxs+3] - yk[3];
  3504. diff += el * el;
  3505. el = sdata[idxs+4] - yk[4];
  3506. diff += el * el;
  3507. }
  3508. if ( diff < 1.0 )
  3509. {
  3510. weight = 1 - weightMap[idxd];
  3511. for ( k = 0; k < lN; k++ )
  3512. Mh[k] += weight * sdata[idxs+k];
  3513. wsuml += weight;
  3514. //set basin of attraction mode table
  3515. if ( diff < speedThreshold )
  3516. {
  3517. if ( modeTable[idxd] == 0 )
  3518. {
  3519. pointList[pointCount++] = idxd;
  3520. modeTable[idxd] = 2;
  3521. }
  3522. }
  3523. }
  3524. }
  3525. idxd = slist[idxd];
  3526. }
  3527. }
  3528. if ( wsuml > 0 )
  3529. {
  3530. for ( j = 0; j < lN; j++ )
  3531. Mh[j] = Mh[j] / wsuml - yk[j];
  3532. }
  3533. else
  3534. {
  3535. for ( j = 0; j < lN; j++ )
  3536. Mh[j] = 0;
  3537. }
  3538. /*****************************************************/
  3539. // Calculate its magnitude squared
  3540. //mvAbs = 0;
  3541. //for(j = 0; j < lN; j++)
  3542. // mvAbs += Mh[j]*Mh[j];
  3543. mvAbs = ( Mh[0] * Mh[0] + Mh[1] * Mh[1] ) * sigmaS * sigmaS;
  3544. if ( N == 3 )
  3545. mvAbs += ( Mh[2] * Mh[2] + Mh[3] * Mh[3] + Mh[4] * Mh[4] ) * sigmaR * sigmaR;
  3546. else
  3547. mvAbs += Mh[2] * Mh[2] * sigmaR * sigmaR;
  3548. // Increment iteration count
  3549. iterationCount++;
  3550. }
  3551. // if a mode was not associated with this data point
  3552. // yet associate it with yk...
  3553. if ( mvAbs >= 0 )
  3554. {
  3555. // Shift window location
  3556. for ( j = 0; j < lN; j++ )
  3557. yk[j] += Mh[j];
  3558. // update mode table for this data point
  3559. // indicating that a mode has been associated
  3560. // with it
  3561. modeTable[i] = 1;
  3562. }
  3563. for ( k = 0; k < N; k++ )
  3564. yk[k+2] *= sigmaR;
  3565. // associate the data point indexed by
  3566. // the point list with the mode stored
  3567. // by yk
  3568. for ( j = 0; j < pointCount; j++ )
  3569. {
  3570. // obtain the point location from the
  3571. // point list
  3572. modeCandidate_i = pointList[j];
  3573. // update the mode table for this point
  3574. modeTable[modeCandidate_i] = 1;
  3575. //store result into msRawData...
  3576. for ( k = 0; k < N; k++ )
  3577. msRawData[N*modeCandidate_i+k] = ( float ) ( yk[k+2] );
  3578. }
  3579. //store result into msRawData...
  3580. for ( j = 0; j < N; j++ )
  3581. msRawData[N*i+j] = ( float ) ( yk[j+2] );
  3582. // Prompt user on progress
  3583. #ifdef SHOW_PROGRESS
  3584. percent_complete = ( float ) ( i / ( float ) ( L ) ) * 100;
  3585. printf ( ( char* ) "\r%2d%%", ( int ) ( percent_complete + 0.5 ) );
  3586. #endif
  3587. // Check to see if the algorithm has been halted
  3588. if ( ( i % PROGRESS_RATE == 0 ) && ( ( ErrorStatus = msSys.Progress ( ( float ) ( i / ( float ) ( L ) ) * ( float ) ( 0.8 ) ) ) ) == EL_HALT )
  3589. break;
  3590. }
  3591. // Prompt user that filtering is completed
  3592. #ifdef PROMPT
  3593. #ifdef SHOW_PROGRESS
  3594. printf ( ( char* ) "\r" );
  3595. #endif
  3596. printf ( ( char* ) "done." );
  3597. #endif
  3598. // de-allocate memory
  3599. delete [] buckets;
  3600. delete [] slist;
  3601. delete [] sdata;
  3602. delete [] yk;
  3603. delete [] Mh;
  3604. // done.
  3605. return;
  3606. }
  3607. void msImageProcessor::NewNonOptimizedFilter ( float sigmaS, float sigmaR )
  3608. {
  3609. // Declare Variables
  3610. int iterationCount, i, j, k;
  3611. double mvAbs, diff, el;
  3612. //make sure that a lattice height and width have
  3613. //been defined...
  3614. if ( !height )
  3615. {
  3616. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "LFilter", ( char* ) "Lattice height and width are undefined." );
  3617. return;
  3618. }
  3619. //re-assign bandwidths to sigmaS and sigmaR
  3620. if ( ( ( h[0] = sigmaS ) <= 0 ) || ( ( h[1] = sigmaR ) <= 0 ) )
  3621. {
  3622. ErrorHandler ( ( char* ) "msImageProcessor", ( char* ) "Segment", ( char* ) "sigmaS and/or sigmaR is zero or negative." );
  3623. return;
  3624. }
  3625. //define input data dimension with lattice
  3626. int lN = N + 2;
  3627. // Traverse each data point applying mean shift
  3628. // to each data point
  3629. // Allcocate memory for yk
  3630. double *yk = new double [lN];
  3631. // Allocate memory for Mh
  3632. double *Mh = new double [lN];
  3633. // let's use some temporary data
  3634. double* sdata;
  3635. sdata = new double[lN*L];
  3636. // copy the scaled data
  3637. int idxs, idxd;
  3638. idxs = idxd = 0;
  3639. if ( N == 3 )
  3640. {
  3641. for ( i = 0; i < L; i++ )
  3642. {
  3643. sdata[idxs++] = ( i % width ) / sigmaS;
  3644. sdata[idxs++] = ( i / width ) / sigmaS;
  3645. sdata[idxs++] = data[idxd++] / sigmaR;
  3646. sdata[idxs++] = data[idxd++] / sigmaR;
  3647. sdata[idxs++] = data[idxd++] / sigmaR;
  3648. }
  3649. } else if ( N == 1 )
  3650. {
  3651. for ( i = 0; i < L; i++ )
  3652. {
  3653. sdata[idxs++] = ( i % width ) / sigmaS;
  3654. sdata[idxs++] = ( i / width ) / sigmaS;
  3655. sdata[idxs++] = data[idxd++] / sigmaR;
  3656. }
  3657. } else
  3658. {
  3659. for ( i = 0; i < L; i++ )
  3660. {
  3661. sdata[idxs++] = ( i % width ) / sigmaS;
  3662. sdata[idxs++] = ( i % width ) / sigmaS;
  3663. for ( j = 0; j < N; j++ )
  3664. sdata[idxs++] = data[idxd++] / sigmaR;
  3665. }
  3666. }
  3667. // index the data in the 3d buckets (x, y, L)
  3668. int* buckets;
  3669. int* slist;
  3670. slist = new int[L];
  3671. int bucNeigh[27];
  3672. double sMins; // just for L
  3673. double sMaxs[3]; // for all
  3674. sMaxs[0] = width / sigmaS;
  3675. sMaxs[1] = height / sigmaS;
  3676. sMins = sMaxs[2] = sdata[2];
  3677. idxs = 2;
  3678. double cval;
  3679. for ( i = 0; i < L; i++ )
  3680. {
  3681. cval = sdata[idxs];
  3682. if ( cval < sMins )
  3683. sMins = cval;
  3684. else if ( cval > sMaxs[2] )
  3685. sMaxs[2] = cval;
  3686. idxs += lN;
  3687. }
  3688. int nBuck1, nBuck2, nBuck3;
  3689. int cBuck1, cBuck2, cBuck3, cBuck;
  3690. nBuck1 = ( int ) ( sMaxs[0] + 3 );
  3691. nBuck2 = ( int ) ( sMaxs[1] + 3 );
  3692. nBuck3 = ( int ) ( sMaxs[2] - sMins + 3 );
  3693. buckets = new int[nBuck1*nBuck2*nBuck3];
  3694. for ( i = 0; i < ( nBuck1*nBuck2*nBuck3 ); i++ )
  3695. buckets[i] = -1;
  3696. idxs = 0;
  3697. for ( i = 0; i < L; i++ )
  3698. {
  3699. // find bucket for current data and add it to the list
  3700. cBuck1 = ( int ) sdata[idxs] + 1;
  3701. cBuck2 = ( int ) sdata[idxs+1] + 1;
  3702. cBuck3 = ( int ) ( sdata[idxs+2] - sMins ) + 1;
  3703. cBuck = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  3704. slist[i] = buckets[cBuck];
  3705. buckets[cBuck] = i;
  3706. idxs += lN;
  3707. }
  3708. // init bucNeigh
  3709. idxd = 0;
  3710. for ( cBuck1 = -1; cBuck1 <= 1; cBuck1++ )
  3711. {
  3712. for ( cBuck2 = -1; cBuck2 <= 1; cBuck2++ )
  3713. {
  3714. for ( cBuck3 = -1; cBuck3 <= 1; cBuck3++ )
  3715. {
  3716. bucNeigh[idxd++] = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  3717. }
  3718. }
  3719. }
  3720. double wsuml, weight;
  3721. double hiLTr = 80.0 / sigmaR;
  3722. // done indexing/hashing
  3723. // proceed ...
  3724. #ifdef PROMPT
  3725. printf ( ( char* ) "done.\nApplying mean shift (Using Lattice)... " );
  3726. #ifdef SHOW_PROGRESS
  3727. printf ( ( char* ) "\n 0%%" );
  3728. #endif
  3729. #endif
  3730. for ( i = 0; i < L; i++ )
  3731. {
  3732. // Assign window center (window centers are
  3733. // initialized by createLattice to be the point
  3734. // data[i])
  3735. idxs = i * lN;
  3736. for ( j = 0; j < lN; j++ )
  3737. yk[j] = sdata[idxs+j];
  3738. // Calculate the mean shift vector using the lattice
  3739. // LatticeMSVector(Mh, yk);
  3740. /*****************************************************/
  3741. // Initialize mean shift vector
  3742. for ( j = 0; j < lN; j++ )
  3743. Mh[j] = 0;
  3744. wsuml = 0;
  3745. // uniformLSearch(Mh, yk_ptr); // modify to new
  3746. // find bucket of yk
  3747. cBuck1 = ( int ) yk[0] + 1;
  3748. cBuck2 = ( int ) yk[1] + 1;
  3749. cBuck3 = ( int ) ( yk[2] - sMins ) + 1;
  3750. cBuck = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  3751. for ( j = 0; j < 27; j++ )
  3752. {
  3753. idxd = buckets[cBuck+bucNeigh[j]];
  3754. // list parse, crt point is cHeadList
  3755. while ( idxd >= 0 )
  3756. {
  3757. idxs = lN * idxd;
  3758. // determine if inside search window
  3759. el = sdata[idxs+0] - yk[0];
  3760. diff = el * el;
  3761. el = sdata[idxs+1] - yk[1];
  3762. diff += el * el;
  3763. if ( diff < 1.0 )
  3764. {
  3765. el = sdata[idxs+2] - yk[2];
  3766. if ( yk[2] > hiLTr )
  3767. diff = 4 * el * el;
  3768. else
  3769. diff = el * el;
  3770. if ( N > 1 )
  3771. {
  3772. el = sdata[idxs+3] - yk[3];
  3773. diff += el * el;
  3774. el = sdata[idxs+4] - yk[4];
  3775. diff += el * el;
  3776. }
  3777. if ( diff < 1.0 )
  3778. {
  3779. weight = 1 - weightMap[idxd];
  3780. for ( k = 0; k < lN; k++ )
  3781. Mh[k] += weight * sdata[idxs+k];
  3782. wsuml += weight;
  3783. }
  3784. }
  3785. idxd = slist[idxd];
  3786. }
  3787. }
  3788. if ( wsuml > 0 )
  3789. {
  3790. for ( j = 0; j < lN; j++ )
  3791. Mh[j] = Mh[j] / wsuml - yk[j];
  3792. }
  3793. else
  3794. {
  3795. for ( j = 0; j < lN; j++ )
  3796. Mh[j] = 0;
  3797. }
  3798. /*****************************************************/
  3799. // Calculate its magnitude squared
  3800. mvAbs = 0;
  3801. for ( j = 0; j < lN; j++ )
  3802. mvAbs += Mh[j] * Mh[j];
  3803. // Keep shifting window center until the magnitude squared of the
  3804. // mean shift vector calculated at the window center location is
  3805. // under a specified threshold (Epsilon)
  3806. // NOTE: iteration count is for speed up purposes only - it
  3807. // does not have any theoretical importance
  3808. iterationCount = 1;
  3809. while ( ( mvAbs >= EPSILON2 ) && ( iterationCount < LIMIT ) )
  3810. {
  3811. // Shift window location
  3812. for ( j = 0; j < lN; j++ )
  3813. yk[j] += Mh[j];
  3814. // Calculate the mean shift vector at the new
  3815. // window location using lattice
  3816. // LatticeMSVector(Mh, yk);
  3817. /*****************************************************/
  3818. // Initialize mean shift vector
  3819. for ( j = 0; j < lN; j++ )
  3820. Mh[j] = 0;
  3821. wsuml = 0;
  3822. // uniformLSearch(Mh, yk_ptr); // modify to new
  3823. // find bucket of yk
  3824. cBuck1 = ( int ) yk[0] + 1;
  3825. cBuck2 = ( int ) yk[1] + 1;
  3826. cBuck3 = ( int ) ( yk[2] - sMins ) + 1;
  3827. cBuck = cBuck1 + nBuck1 * ( cBuck2 + nBuck2 * cBuck3 );
  3828. for ( j = 0; j < 27; j++ )
  3829. {
  3830. idxd = buckets[cBuck+bucNeigh[j]];
  3831. // list parse, crt point is cHeadList
  3832. while ( idxd >= 0 )
  3833. {
  3834. idxs = lN * idxd;
  3835. // determine if inside search window
  3836. el = sdata[idxs+0] - yk[0];
  3837. diff = el * el;
  3838. el = sdata[idxs+1] - yk[1];
  3839. diff += el * el;
  3840. if ( diff < 1.0 )
  3841. {
  3842. el = sdata[idxs+2] - yk[2];
  3843. if ( yk[2] > hiLTr )
  3844. diff = 4 * el * el;
  3845. else
  3846. diff = el * el;
  3847. if ( N > 1 )
  3848. {
  3849. el = sdata[idxs+3] - yk[3];
  3850. diff += el * el;
  3851. el = sdata[idxs+4] - yk[4];
  3852. diff += el * el;
  3853. }
  3854. if ( diff < 1.0 )
  3855. {
  3856. weight = 1 - weightMap[idxd];
  3857. for ( k = 0; k < lN; k++ )
  3858. Mh[k] += weight * sdata[idxs+k];
  3859. wsuml += weight;
  3860. }
  3861. }
  3862. idxd = slist[idxd];
  3863. }
  3864. }
  3865. if ( wsuml > 0 )
  3866. {
  3867. for ( j = 0; j < lN; j++ )
  3868. Mh[j] = Mh[j] / wsuml - yk[j];
  3869. }
  3870. else
  3871. {
  3872. for ( j = 0; j < lN; j++ )
  3873. Mh[j] = 0;
  3874. }
  3875. /*****************************************************/
  3876. // Calculate its magnitude squared
  3877. //mvAbs = 0;
  3878. //for(j = 0; j < lN; j++)
  3879. // mvAbs += Mh[j]*Mh[j];
  3880. mvAbs = ( Mh[0] * Mh[0] + Mh[1] * Mh[1] ) * sigmaS * sigmaS;
  3881. if ( N == 3 )
  3882. mvAbs += ( Mh[2] * Mh[2] + Mh[3] * Mh[3] + Mh[4] * Mh[4] ) * sigmaR * sigmaR;
  3883. else
  3884. mvAbs += Mh[2] * Mh[2] * sigmaR * sigmaR;
  3885. // Increment interation count
  3886. iterationCount++;
  3887. }
  3888. // Shift window location
  3889. for ( j = 0; j < lN; j++ )
  3890. yk[j] += Mh[j];
  3891. //store result into msRawData...
  3892. for ( j = 0; j < N; j++ )
  3893. msRawData[N*i+j] = ( float ) ( yk[j+2] * sigmaR );
  3894. // Prompt user on progress
  3895. #ifdef SHOW_PROGRESS
  3896. percent_complete = ( float ) ( i / ( float ) ( L ) ) * 100;
  3897. printf ( ( char* ) "\r%2d%%", ( int ) ( percent_complete + 0.5 ) );
  3898. #endif
  3899. // Check to see if the algorithm has been halted
  3900. if ( ( i % PROGRESS_RATE == 0 ) && ( ( ErrorStatus = msSys.Progress ( ( float ) ( i / ( float ) ( L ) ) * ( float ) ( 0.8 ) ) ) ) == EL_HALT )
  3901. break;
  3902. }
  3903. // Prompt user that filtering is completed
  3904. #ifdef PROMPT
  3905. #ifdef SHOW_PROGRESS
  3906. printf ( ( char* ) "\r" );
  3907. #endif
  3908. printf ( ( char* ) "done." );
  3909. #endif
  3910. // de-allocate memory
  3911. delete [] buckets;
  3912. delete [] slist;
  3913. delete [] sdata;
  3914. delete [] yk;
  3915. delete [] Mh;
  3916. // done.
  3917. return;
  3918. }
  3919. void msImageProcessor::SetSpeedThreshold ( float speedUpThreshold )
  3920. {
  3921. speedThreshold = speedUpThreshold;
  3922. }
  3923. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  3924. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  3925. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  3926. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  3927. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/