From 3a438326c6901fafd9be8b5446a828aa5f63a1cc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leonardo=20Fl=C3=B3rez-Valencia?= Date: Sun, 18 Jun 2017 23:05:45 -0500 Subject: [PATCH] ... --- CMakeLists.txt | 85 +++++ cmake/fpaBaseConfig.cmake | 65 ++++ cmake/fpaConfig.cmake.in | 16 + data/binary_test_2D_00.png | Bin 0 -> 5192 bytes data/input_mori_binary.png | Bin 0 -> 2563 bytes lib/CMakeLists.txt | 8 + lib/fpa/Base/Algorithm.h | 127 +++++++ lib/fpa/Base/Algorithm.hxx | 212 +++++++++++ lib/fpa/Base/Dijkstra.h | 69 ++++ lib/fpa/Base/Dijkstra.hxx | 74 ++++ lib/fpa/Base/DijkstraBase.h | 91 +++++ lib/fpa/Base/DijkstraBase.hxx | 114 ++++++ lib/fpa/Base/Functors/Dijkstra/Function.h | 64 ++++ .../Functors/RegionGrow/BinaryThreshold.h | 86 +++++ lib/fpa/Base/Functors/RegionGrow/Tautology.h | 69 ++++ lib/fpa/Base/Graph.h | 170 +++++++++ lib/fpa/Base/Graph.hxx | 272 +++++++++++++ lib/fpa/Base/MarksInterface.h | 50 +++ lib/fpa/Base/MarksInterface.hxx | 43 +++ lib/fpa/Base/MarksInterfaceWithCollisions.h | 62 +++ lib/fpa/Base/MarksInterfaceWithCollisions.hxx | 133 +++++++ lib/fpa/Base/MinimumSpanningTree.h | 77 ++++ lib/fpa/Base/MinimumSpanningTree.hxx | 237 ++++++++++++ lib/fpa/Base/RegionGrow.h | 96 +++++ lib/fpa/Base/RegionGrow.hxx | 155 ++++++++ lib/fpa/Base/SeedsInterface.h | 86 +++++ lib/fpa/Base/SeedsInterface.hxx | 117 ++++++ lib/fpa/CMakeLists.txt | 69 ++++ lib/fpa/Config.h.in | 18 + lib/fpa/Image/Algorithm.h | 88 +++++ lib/fpa/Image/Algorithm.hxx | 176 +++++++++ lib/fpa/Image/Dijkstra.h | 103 +++++ lib/fpa/Image/Functors/Dijkstra/Function.h | 69 ++++ lib/fpa/Image/Functors/Dijkstra/Gaussian.h | 104 +++++ lib/fpa/Image/Functors/Dijkstra/Identity.h | 73 ++++ lib/fpa/Image/Functors/Dijkstra/Invert.h | 94 +++++ lib/fpa/Image/LabelledSeedsInterface.h | 62 +++ lib/fpa/Image/LabelledSeedsInterface.hxx | 64 ++++ lib/fpa/Image/MinimumSpanningTree.h | 71 ++++ lib/fpa/Image/PathsToImageFilter.h | 84 ++++ lib/fpa/Image/PathsToImageFilter.hxx | 79 ++++ lib/fpa/Image/PolyLineParametricPath.h | 97 +++++ lib/fpa/Image/PolyLineParametricPath.hxx | 194 ++++++++++ lib/fpa/Image/RandomWalker.h | 78 ++++ lib/fpa/Image/RandomWalker.hxx | 124 ++++++ lib/fpa/Image/RegionGrow.h | 68 ++++ lib/fpa/Image/Skeleton.h | 67 ++++ lib/fpa/Image/Skeleton.hxx | 99 +++++ lib/fpa/Image/SkeletonFilter.h | 160 ++++++++ lib/fpa/Image/SkeletonFilter.hxx | 359 ++++++++++++++++++ lib/fpa/Image/VisualDebugger.h | 98 +++++ lib/fpa/Image/VisualDebugger.hxx | 134 +++++++ lib/fpa/Image/VisualDebugger2D.h | 76 ++++ lib/fpa/Image/VisualDebugger2D.hxx | 74 ++++ lib/fpa/Version.cxx.in | 7 + tests/CMakeLists.txt | 10 + tests/image/BaseFunctions.h | 315 +++++++++++++++ tests/image/CMakeLists.txt | 19 + tests/image/Dijkstra_Gaussian.cxx | 99 +++++ tests/image/Dijkstra_Identity.cxx | 87 +++++ tests/image/RandomWalker.cxx | 113 ++++++ tests/image/RegionGrow_Tautology.cxx | 87 +++++ tests/image/SkeletonFilter.cxx | 74 ++++ 63 files changed, 6171 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 cmake/fpaBaseConfig.cmake create mode 100644 cmake/fpaConfig.cmake.in create mode 100644 data/binary_test_2D_00.png create mode 100644 data/input_mori_binary.png create mode 100644 lib/CMakeLists.txt create mode 100644 lib/fpa/Base/Algorithm.h create mode 100644 lib/fpa/Base/Algorithm.hxx create mode 100644 lib/fpa/Base/Dijkstra.h create mode 100644 lib/fpa/Base/Dijkstra.hxx create mode 100644 lib/fpa/Base/DijkstraBase.h create mode 100644 lib/fpa/Base/DijkstraBase.hxx create mode 100644 lib/fpa/Base/Functors/Dijkstra/Function.h create mode 100644 lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h create mode 100644 lib/fpa/Base/Functors/RegionGrow/Tautology.h create mode 100644 lib/fpa/Base/Graph.h create mode 100644 lib/fpa/Base/Graph.hxx create mode 100644 lib/fpa/Base/MarksInterface.h create mode 100644 lib/fpa/Base/MarksInterface.hxx create mode 100644 lib/fpa/Base/MarksInterfaceWithCollisions.h create mode 100644 lib/fpa/Base/MarksInterfaceWithCollisions.hxx create mode 100644 lib/fpa/Base/MinimumSpanningTree.h create mode 100644 lib/fpa/Base/MinimumSpanningTree.hxx create mode 100644 lib/fpa/Base/RegionGrow.h create mode 100644 lib/fpa/Base/RegionGrow.hxx create mode 100644 lib/fpa/Base/SeedsInterface.h create mode 100644 lib/fpa/Base/SeedsInterface.hxx create mode 100644 lib/fpa/CMakeLists.txt create mode 100644 lib/fpa/Config.h.in create mode 100644 lib/fpa/Image/Algorithm.h create mode 100644 lib/fpa/Image/Algorithm.hxx create mode 100644 lib/fpa/Image/Dijkstra.h create mode 100644 lib/fpa/Image/Functors/Dijkstra/Function.h create mode 100644 lib/fpa/Image/Functors/Dijkstra/Gaussian.h create mode 100644 lib/fpa/Image/Functors/Dijkstra/Identity.h create mode 100644 lib/fpa/Image/Functors/Dijkstra/Invert.h create mode 100644 lib/fpa/Image/LabelledSeedsInterface.h create mode 100644 lib/fpa/Image/LabelledSeedsInterface.hxx create mode 100644 lib/fpa/Image/MinimumSpanningTree.h create mode 100644 lib/fpa/Image/PathsToImageFilter.h create mode 100644 lib/fpa/Image/PathsToImageFilter.hxx create mode 100644 lib/fpa/Image/PolyLineParametricPath.h create mode 100644 lib/fpa/Image/PolyLineParametricPath.hxx create mode 100644 lib/fpa/Image/RandomWalker.h create mode 100644 lib/fpa/Image/RandomWalker.hxx create mode 100644 lib/fpa/Image/RegionGrow.h create mode 100644 lib/fpa/Image/Skeleton.h create mode 100644 lib/fpa/Image/Skeleton.hxx create mode 100644 lib/fpa/Image/SkeletonFilter.h create mode 100644 lib/fpa/Image/SkeletonFilter.hxx create mode 100644 lib/fpa/Image/VisualDebugger.h create mode 100644 lib/fpa/Image/VisualDebugger.hxx create mode 100644 lib/fpa/Image/VisualDebugger2D.h create mode 100644 lib/fpa/Image/VisualDebugger2D.hxx create mode 100644 lib/fpa/Version.cxx.in create mode 100644 tests/CMakeLists.txt create mode 100644 tests/image/BaseFunctions.h create mode 100644 tests/image/CMakeLists.txt create mode 100644 tests/image/Dijkstra_Gaussian.cxx create mode 100644 tests/image/Dijkstra_Identity.cxx create mode 100644 tests/image/RandomWalker.cxx create mode 100644 tests/image/RegionGrow_Tautology.cxx create mode 100644 tests/image/SkeletonFilter.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..095eff9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.0) + +## ======================== +## == Project definition == +## ======================== + +set(prj_MAJ_VERSION 0) +set(prj_MIN_VERSION 1) +set(prj_REL_VERSION 0) +set(prj_VERSION "${prj_MAJ_VERSION}.${prj_MIN_VERSION}.${prj_REL_VERSION}") +set(prj_SHORT_VERSION "${prj_MAJ_VERSION}") +project(fpa VERSION ${prj_VERSION}) + +## ========================== +## == Some useful policies == +## ========================== + +set(_policies CMP0015 CMP0020 CMP0042 CMP0053) +foreach(_p ${_policies}) + if(POLICY ${_p}) + cmake_policy(SET ${_p} NEW) + endif(POLICY ${_p}) +endforeach(_p) + +## =============================== +## == Some basic configurations == +## =============================== + +include(cmake/fpaBaseConfig.cmake) + +## ========================== +## == Find needed packages == +## ========================== + +find_package(ivq CONFIG QUIET) +if(NOT ivq_FOUND) + find_package(ITK CONFIG REQUIRED) + include(${ITK_USE_FILE}) +endif(NOT ivq_FOUND) + +## ========================= +## == Installation values == +## ========================= + +set(config_install_dir "lib/cmake/${PROJECT_NAME}") +set(include_install_dir "include") +set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") +set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake") +set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake") +set(targets_export_name "${PROJECT_NAME}Targets") +set(namespace "${PROJECT_NAME}::") + +## =========================== +## == Build different parts == +## =========================== + +subdirs(lib tests) + +## =============================== +## == Global installation rules == +## =============================== + +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${version_config}" COMPATIBILITY SameMajorVersion + ) +configure_package_config_file( + "cmake/${PROJECT_NAME}Config.cmake.in" + "${project_config}" + INSTALL_DESTINATION "${config_install_dir}" + ) +install( + FILES + "${project_config}" + "${version_config}" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${PROJECT_NAME}BaseConfig.cmake" + DESTINATION "${config_install_dir}" + ) +install( + EXPORT "${targets_export_name}" + NAMESPACE "${namespace}" + DESTINATION "${config_install_dir}" + ) + +## eof - $RCSfile$ diff --git a/cmake/fpaBaseConfig.cmake b/cmake/fpaBaseConfig.cmake new file mode 100644 index 0000000..4e9cb25 --- /dev/null +++ b/cmake/fpaBaseConfig.cmake @@ -0,0 +1,65 @@ +## ========================================================= +## == If working on a MacOSX, activate the use of RPATH's == +## ========================================================= + +set(EXECUTABLE_TYPE "" CACHE STRING "Executable linking." FORCE) +if(APPLE) + set(EXECUTABLE_TYPE "MACOSX_BUNDLE" CACHE STRING "Executable linking." FORCE) + set(CMAKE_MACOSX_RPATH true CACHE BOOL "Use RPATH's on MacOSX systems." FORCE) + mark_as_advanced(CMAKE_MACOSX_RPATH) +elseif(WIN32) + set(EXECUTABLE_TYPE "WIN32" CACHE STRING "Executable linking." FORCE) +endif(APPLE) +mark_as_advanced(EXECUTABLE_TYPE) + +## ======================================================================= +## == Force c++11 language version == +## == NOTE: It seems that by default on Visual Studio Compiler supports == +## == c++11, so it only need to be tested on other OS. == +## ======================================================================= + +if(NOT MSVC) + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("-std=c++11" COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + else(COMPILER_SUPPORTS_CXX11) + check_cxx_compiler_flag("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + if(COMPILER_SUPPORTS_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + else(COMPILER_SUPPORTS_CXX0X) + message( + FATAL_ERROR + "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support." + ) + endif(COMPILER_SUPPORTS_CXX0X) + endif(COMPILER_SUPPORTS_CXX11) +endif(NOT MSVC) + +## =================================================== +## == Prepare header generator to build shared libs == +## =================================================== + +include(GenerateExportHeader) + +## ================================================== +## == Do not allow to build inside the source tree == +## ================================================== + +if(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR}) + message(FATAL_ERROR "Building in the source tree is not allowed.") +endif(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR}) + +## ================================================= +## == Where to put targets (executables and libs) == +## ================================================= + +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) +mark_as_advanced( + CMAKE_BACKWARDS_COMPATIBILITY + EXECUTABLE_OUTPUT_PATH + LIBRARY_OUTPUT_PATH + ) + +## eof - $RCSfile$ diff --git a/cmake/fpaConfig.cmake.in b/cmake/fpaConfig.cmake.in new file mode 100644 index 0000000..26692f3 --- /dev/null +++ b/cmake/fpaConfig.cmake.in @@ -0,0 +1,16 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/fpaBaseConfig.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake") +check_required_components("@PROJECT_NAME@") + +## ============== +## == Find ITK == +## ============== + +set(ITK_DIR @ITK_DIR@) + +find_package(ITK CONFIG REQUIRED) +include(${ITK_USE_FILE}) + +## eof - $RCSfile$ diff --git a/data/binary_test_2D_00.png b/data/binary_test_2D_00.png new file mode 100644 index 0000000000000000000000000000000000000000..fbe9d39bd59189ecf7f8ef87e48abde2f3d01953 GIT binary patch literal 5192 zcma)9c{o)6_aD=ZI}EO|PKi5=td%v|KIR(BAZe2=Yhx|DN_LmVP#8-{ib^R-krY`A z@reqNiYy^ZWhrGDe6K#w@BiO@p1Yj$exLI?=XK6=-_J=nc)&!Ee-l3rhZ8hq7#_yq zHo)sQh$(QZn{CUn7r~!l8-&9Nh_2r}xSU)mOvx8)YGK6pnO|H;NsAJfXoRV@cpbF~ zru+H$xcLTSA`V9nbaM%IW5Q>>f<0jqQ;UPl?QVQHoM^47A#yb2`nC({b$L%f zAN+ba&2J>U#}W!JiLbGyhW19FGcQ&}0n5ef8#3Z$LummE*9jo%!F{{Y?1ivTz9#oA zAJ8Bg=?R=3ia&5rBGU7GSY-yz{}c%I=To_Fh51pwmA4}9kaW2vnja-FMQ9p~zkN_3 za-9FxV0`UCuv*_>is&{N-?N}t-F5-5X$EP3vu(f53v|e+)C&u`^2V6P!Om>J=>9Q> zet8n0xh^fdD_k-}X>2|6!AB;sFwACAK&1R)H_5QeMpZw!Jv~HRpvLXAM84}0UoU9_ zo-z#gen_45)Z#>zHu~B_pt2C^JJRHBx0UE>r-x8gGOoEGicVJbK`=pHy?g-8X4 zdR5-9wspO|9AQBY40fx$S8MyDXX!#bgC%WmQ&Qx2ENL{v{ffjUk^*w^mmEkJvO*~qK*vD;16xxl$&Ey=i`C^Hj<_BqHk;-bt13Yk zx^^TWmTC&I_SPoG8gb-x1&04H88-u#t(UFTSnA9)xPe2F2kD_yMiW2Z&`xrom7fgx zIR_y;hgfYN>!#u<&MjeDAbre&aYe8)Qfh7n|7fjKa&zEHusT4zEY|v>Zcx=Je4+U8 zol`Y2c~Kpcc^<{j>{G?e3oScql{sr`bx{Kcgje$4F8B47B_1!+j9QMWm5H$Rh^lfd zEjxU9cVtZOd#CbE3id@66#I={o{Y#9+H|$#RPyGmJl5dnYpuIcDKk4Fe^)c7dMM#@ znC|rZyrH%&4mP`V;v+<6{U*b7iu~T2_vF8F(Jp$i?gMIBfkOL1Deo29SrMiQYs zcHMK5(E0nNh5N5tCVe{o!iP?87}zuDyL_Yjo>h!dOLF$dT$pwXw^*njMuSAkbPbk# z2IjlkI2KtKbFF)+E!n&L0<422XPbA}>BQD6+{=YO$;DB8D#fH8_&Spe89SsLDx?Fl z@L&1`_oJW}ivewPZ$UTw@U|KJDV}^taEh&}!WJ$%tM7Rta+I47J=okik$n2J+CvQo zmYPUo!RML`*_C@(mDHq=ozA>5pz=00$b(498H5_Q%)fxNs{Xx9rY6R-L<(r^#vlR2RCs)+Xj9uq5g=V|xDWI$)ta_3e3 z{Pq$whojqnOsQU>0S$jbnNdvy{Lhzs)?sKqOV&t79!%8!EkZ|O|GG5zqi=nzj7=~E z7-qs!LocWFEeL4ttFeuILECL~k-u2vG!g88q}i*Xu583-z^wXr|Qd)5wOhdrmYgqK09!vGCx_@481& zDI{?zRY8UWCr>I%hywfWC&{m=AaA$oFByZ#%(p`_0b>I-%I`o_w>hOk#DHTLJboC6q?an1%Mc)Jo`~dnk)hhItr)3HbLnVk`$n!zwpnUfp0|9cIg>FxWyv`giiTGS`r15iCd$dr?4P}H0mc_h zYUCzeTlwHo4VUfgkh+nmy_H$#Nu{lD{9HlB1}ZW35Cy{0s#6D40i_-4=e zlaBv(RLiCn5i}KO<%8DCq%Hi)$iqoy0xzm2%sFSFcNRZ!2`;T9Y>_zW z&N0oyciaYeWOggmE+29c5^sD777nZ$w}vMu&4EBzKWVq%*pc6n?0rTh9KG!fEfG6ObrYsRh7e^Ys$mt^S(+7FLyk0 z9DR}>BO8fis%CPf^871L51j^P&sRhp5qRH{R@kc(?65~@=Dx$S>*JEiZG+CIU+lhn zku8{Is5^tHG?jag?~QwsNsKb_ega3N@V&A#gHHA`%!0SzpqD;+m>+6Kv_03 z6Q(&J)p1sfkzGD#=W0AI!M;1;mUpRE)xsi;5^M-{KIC{cJX+F(^Do-Sx^^F;cwJEd zCHNQ-$eD1Pc3lafwmk%Nw$OUN7`3822~>7aCzQ<%Kb-khq{i_5fEO`?%^^8^teB%-w(WZewqj*uAWX;LxX< zN>WI<*xDyT+DA#C!wF{Nt}oQqsK-Wg?*jyfUt> z9M7+6zVErZyPB~T8DtqjL& zxvpx!o3Vyqil615zH;5B-s&!ekD7`Ulce&^AF34mY1aHK>I%T~2^>y) z>@K3KKehpV>Oy`eIH7lf;m_@VS$%sukyLRTjs%BsQb)(k*KDrK)hV%YUM`H}U&}G^ z)!M?hwd+M4My!f271D~PDM(q^R7-0~%4(au8Pw)E9WPcpRy8gCIrv3rQ8}rgdnc>2 z`gr!qhg?md8<;%;v2yS14;C?e)pp#sIAX6B+x?_dwxVk2grw@RH_y?yEk;A$j-gFO z_F1DtcAr(*lBMpONMW+y4=)-E2wR(N20$vZZKDVuVkg`e|2O9bkF2N8yX$JA&Q4oRv*K`;U6q=bs z9?GB`P3%uOd|)>Ndg}7sP8aEWn2`kw9fkm`MR}0usHmM(q(U$iZ}>MFy!=viw`jo( zi2hXA%9a-cVm6@g(gq+#9))=sJaYd9eOrhEbZmwhb?XeQvtkUP^`HT?o(~>syqK(L zvJWFeJO>LqnhL^5+xQ(33ZQW_c3tu5%Ti7mB+oWuU`$}L#M!fGJ!Ak`@SxvX!m+@> zw}Z9k+HLvORgj9~?MX1e!}?sh4s$_{O3(}iW?kbk;&Y{dyAm)5re)D54j{*`ZDa!- zd(-{;{F?%KqhY8B`|%0;qGF$v%)$oLzf@G)~)9ugocQ(DTsOu&+ml_@J-xoj!m z3M%*el&)S@0O?f=0V9_Q&pA6Ib3@!w^@0>xzH5u24guN|6*Fz5ILi0rs;s=llD!e9P8zm>g4%b%D`7{5n~`8`wr;k zhyJRD|8X_qU|Ea^t+RQjVS^u~onN?Pu4H7Tn)El3Xn4A>z@w&qV$=?^h`}|8q9Kn- zK)@vCfei(U7@o|q1?lV7a&hnzAPaxpn}7IQqYRQ+lYB{GO{J~M)k_dEjMh^G z=e~HHhuM32wBBqpI0lkV+R^EvfZtNXQ*ks7a|N)?HzS51i0+QB2|}@)a8fmalQ7@{`WtYZ+5C{9a4eiNJ!(=gz>B#0 zMtM4;(Xtm3hLglTt;{@2r!wAa*+oJlT#amQJr^K{92$%#H%c9@7pAkx0Nhgi?4p1K z(kB)zWLRH z+ zrL!So8DGw(T#7iG1e+6E)6ZZ1-ChUW4K+`6J;VK-AZ5VG+Vr^hy>H`}lzNU4n!8YQ z-u8OYN}Ui2YYDc>8HrQ6E63DE|FmaXarGi@=eO_5*s*=9z@>Kz7vOH9vbgNx3kc27 zEa;t2qyWlpjLO+q3UK!XL!x*q9X#B~QL}C1x`2p^RGQJrRtP<+PQ7jsC$0{MytwzhR%xE5SrbX_&b%sc3QKH}YoJKA);Y_j&TNSiM&a5gm6dXBE zIr+QFKhAJSL5rCLTL~(!&UX=QI*2Psp7vf^Zg`Uls zQzwZ}9^3s;iNgr6rH`$hkz}1xwJ%Yjlj7i)MBCZca8~g>yAl;V9Sk&1)yXSjw$y#~ z{&7}qZUbp#CFpdwVsq}sJ?5GAnSPjuD_0-Q)T|Oe=){IUo-SoxJveLmy65V2S3&Q` z(9z`c*c9^S&+9Q=NSzt|Xecd?0eJ?UH%cXT;7NdgI2+mrV`n1`J2t*gy8|&G27^cIw_JebuptMN3_%2E zBDAS5^H&TIFdPFrgZ}~jUtE7rkrV%&_v>bZqDcNI0k7xjpZjhj3Bbl1Jp=8S^(pV4 zL}*{W9)=4vD6+*qXUK|2F~dJ0LZbRVE_OC literal 0 HcmV?d00001 diff --git a/data/input_mori_binary.png b/data/input_mori_binary.png new file mode 100644 index 0000000000000000000000000000000000000000..d6052476e0b2a2675e6f9b21be2f497f09e7e6d3 GIT binary patch literal 2563 zcmd5;dsq|K65kLs_#iNMtL5Gysm*RW5N$A6?1oei*ZhFBDkBE7yiUr^_5!wvZVD;T#BN z_z*N8j&K9?z6s|HyNq~`@DZ;O{vQGX=soZE1O2a`mE~IpKtx>Wb7Ik&@ZuMPZTnbl zHk}F16l&%&yXUtxMB()A^uglxNEk`Bw)iSvl&IF+hgX_huf1S_%xa9aS=f7M6;Wti zlF@c1VjYYm6j**%DT-BVn&5TvmRB9$4|{p_y5$YK%@IyNf0m@$JU$9(dUayo^9>o& zgdG8|Yj(uBBaR0g>fW3?E28*0Vf$tYnIh^pb%u#UoIpcxrb<-DUCiO?8O3RtuAjS- zBF|?00ayG9DVi5@c{f-5DJimPZnWi!SCJx%kS5)j0wo$@ROy;z)NN1Y?8{<%q}?({ z8ZQ&shgIyoSakIEJt5keYRy>}-v@T$BCsRnOyh}&w`;p2J42D)$ z`>m^_$_9hMCi;(JzswRY1&OFgb@JFQ-^>^rgK{a^l1s^2i)KBU#|#@4)3+jAxaZjn z%E=E~ba05(o4UVm`q1Z^K*B~BI@q5FBa~pVk<$#4`Q})EYx%8Tr@^gEqa#<3G<X}~*{;E^etEnrEe?(`mo7s;HGY2ZPiG za4B9SIY$CrykL^Swm~n?0WzN2wbW|ac%VrdJ2~<#8N-RAOHZU5qD9H}68}voSQK03yr!WK20vRWP*(#p>v3xZqxzs?wQ)(yBj(k!=j4{dH(B z&n&r3tv5tFQLmWB)5LHq!qsh7V0MrZ>pU7UimUTbU>QKEKqJO+btVd|6Uubg>Gon4 zw8n)uZXWNAsXb&PJA>76LZngxS2!wJ2RrCbj5(lE*%f05j$nnh#bBA-quWl0UkDsUI4G5EXj@ z@@||QQRQW6zmxMIk|{%97utI`>jgUKCwa=!dLQGG0K>S^&y*TjIrHM}32(=ceu@;n zc$sD9v3O*~TkiXE@gk4Fzk!h96I_aDyjKU61iuTapJgMBfNMNNYDySfX-;k zJYQMmj{8nj1(OR%&Z}USck|eAULpj@hd7w{t?kZhg4-K;^)X{FAp;lOrnM#kPrbLEdKwW|vg{$K z1zM%Rwty2j@U+lgo~&Mhl^V^O09S`;y=G8)b%Bv}2+X*Fz}4O|^SJ=Br4Ee-Nqg}T zT5PjOqQ&n>;^+^|Rn~aR3fl5Gd z^D)cj+D)mC*ABgU9$~e#vx}K#b7F4l>VBtb{dCD_xRnzS)^;g*tUe{!C}k-tV?co= zx`g`>7gMfws5LjEin!EvToruB(rq%*9=%6~Zu$E6fghArXoRhVjtfdcnoAbOfKn-Q zuZu2`qSGN`%#cpk>Aos3`?r6Sy<9n$6g4#)`B5+M!h*_2N84#rXHy*o z;_K^3p@10U*hzV8u3#8Nw}jl3+vm1ohZ0A=3J5CL6+;*)UJO68v0Rn literal 0 HcmV?d00001 diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..f4c0955 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,8 @@ + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ) +subdirs(fpa) + +## eof - $RCSfile$ diff --git a/lib/fpa/Base/Algorithm.h b/lib/fpa/Base/Algorithm.h new file mode 100644 index 0000000..e5b6f2b --- /dev/null +++ b/lib/fpa/Base/Algorithm.h @@ -0,0 +1,127 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__Algorithm__h__ +#define __fpa__Base__Algorithm__h__ + +#include + +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > + class Algorithm + : public _TFilter, + public _TMarksInterface, + public _TSeedsInterface + { + public: + typedef Algorithm Self; + typedef _TFilter Superclass; + typedef _TMarksInterface TMarksInterface; + typedef _TSeedsInterface TSeedsInterface; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename _TSeedsInterface::TInputValue TInputValue; + typedef typename _TSeedsInterface::TOutputValue TOutputValue; + typedef typename _TSeedsInterface::TNode TNode; + typedef typename _TSeedsInterface::TSeeds TSeeds; + typedef typename _TSeedsInterface::TVertex TVertex; + + typedef std::vector< TVertex > TNeighborhood; + + /** + */ + class TEvent + : public itk::EventObject + { + public: + typedef TEvent Self; + typedef itk::EventObject Superclass; + + public: + TEvent( ); + TEvent( const TVertex& v, unsigned long fid, bool intoq ); + virtual ~TEvent( ); + virtual const char* GetEventName( ) const override; + virtual bool CheckEvent( const itk::EventObject* e ) const override; + virtual itk::EventObject* MakeObject( ) const override; + + private: + // Purposely not implemented. + Self& operator=( const Self& other ); + + public: + TVertex Vertex; + unsigned long FrontId; + bool IntoQueue; + }; + + public: + itkTypeMacro( fpa::Base::Algorithm, _TFilter ); + + itkBooleanMacro( VisualDebug ); + + itkGetConstMacro( InitValue, TOutputValue ); + itkGetConstMacro( VisualDebug, bool ); + + itkSetMacro( InitValue, TOutputValue ); + itkSetMacro( VisualDebug, bool ); + + public: + virtual void InvokeEvent( const itk::EventObject& e ); + virtual void InvokeEvent( const itk::EventObject& e ) const; + + protected: + Algorithm( ); + virtual ~Algorithm( ); + + virtual void GenerateData( ) override; + virtual void _BeforeGenerateData( ); + virtual void _AfterGenerateData( ); + + virtual void _QueueInit( ); + + virtual void _ConfigureOutput( const TOutputValue& v ) = 0; + virtual TNeighborhood _GetNeighbors( const TVertex& v ) const = 0; + virtual TInputValue _GetInputValue( const TVertex& v ) const = 0; + virtual TOutputValue _GetOutputValue( const TVertex& v ) const = 0; + + virtual TOutputValue _ComputeOutputValue( const TNode& n ) = 0; + virtual void _UpdateOutputValue( const TNode& n ) = 0; + virtual void _QueueClear( ) = 0; + virtual void _QueuePush( const TNode& node ) = 0; + virtual unsigned long _QueueSize( ) const = 0; + virtual TNode _QueuePop( ) = 0; + + private: + // Purposely not implemented + Algorithm( const Self& other ); + Self& operator=( const Self& other ); + + protected: + bool m_VisualDebug; + TOutputValue m_InitValue; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__Algorithm__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Algorithm.hxx b/lib/fpa/Base/Algorithm.hxx new file mode 100644 index 0000000..383db74 --- /dev/null +++ b/lib/fpa/Base/Algorithm.hxx @@ -0,0 +1,212 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__Algorithm__hxx__ +#define __fpa__Base__Algorithm__hxx__ + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent:: +TEvent( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent:: +TEvent( const TVertex& v, unsigned long fid, bool intoq ) + : Superclass( ), + Vertex( v ), + FrontId( fid ), + IntoQueue( intoq ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent:: +~TEvent( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +const char* +fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent:: +GetEventName( ) const +{ + return( "fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent" ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +bool +fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent:: +CheckEvent( const itk::EventObject* e ) const +{ + return( dynamic_cast< const Self* >( e ) != NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +itk::EventObject* +fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >::TEvent:: +MakeObject( ) const +{ + return( new Self ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: +InvokeEvent( const itk::EventObject& e ) +{ + TEvent a; + if( a.CheckEvent( &e ) ) + { + if( this->m_VisualDebug ) + this->Superclass::InvokeEvent( e ); + } + else + this->Superclass::InvokeEvent( e ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: +InvokeEvent( const itk::EventObject& e ) const +{ + TEvent a; + if( a.CheckEvent( &e ) ) + { + if( this->m_VisualDebug ) + this->Superclass::InvokeEvent( e ); + } + else + this->Superclass::InvokeEvent( e ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: +Algorithm( ) + : Superclass( ), + _TMarksInterface( this ), + _TSeedsInterface( this ), + m_VisualDebug( false ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: +~Algorithm( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: +GenerateData( ) +{ + this->InvokeEvent( itk::StartEvent( ) ); + + // Init objects + this->_BeforeGenerateData( ); + this->_ConfigureOutput( this->m_InitValue ); + this->_InitMarks( this->GetNumberOfSeeds( ) ); + + // Init queue + this->_QueueInit( ); + typename TSeeds::const_iterator sIt = this->BeginSeeds( ); + for( ; sIt != this->EndSeeds( ); ++sIt ) + { + this->_QueuePush( *sIt ); + this->InvokeEvent( TEvent( sIt->Vertex, sIt->FrontId, true ) ); + + } // rof + + // Main loop + while( this->_QueueSize( ) > 0 ) + { + // Get next candidate + TNode node = this->_QueuePop( ); + this->InvokeEvent( TEvent( node.Vertex, node.FrontId, false ) ); + if( !( this->_IsMarked( node.Vertex ) ) ) + { + // Mark it + if( this->_Mark( node.Vertex, node.FrontId ) ) + { + // Update output value + this->_UpdateOutputValue( node ); + + // Add neighborhood + TNeighborhood neighbors = this->_GetNeighbors( node.Vertex ); + typename TNeighborhood::const_iterator nIt = neighbors.begin( ); + bool coll = false; + while( nIt != neighbors.end( ) && !coll ) + { + if( this->_IsMarked( *nIt ) ) + { + // Invoke stop at collisions + if( this->_Collisions( node.Vertex, *nIt ) ) + { + this->_QueueClear( ); + coll = true; + + } // fi + } + else + { + TNode nnode; + nnode.Vertex = *nIt; + nnode.Parent = node.Vertex; + nnode.FrontId = node.FrontId; + nnode.Value = this->_ComputeOutputValue( nnode ); + this->_QueuePush( nnode ); + this->InvokeEvent( TEvent( nnode.Vertex, nnode.FrontId, true ) ); + + } // fi + ++nIt; + + } // elihw + + } // fi + + } // fi + + } // elihw + + // Finish + this->_AfterGenerateData( ); + this->InvokeEvent( itk::EndEvent( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: +_BeforeGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: +_AfterGenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TFilter, class _TMarksInterface, class _TSeedsInterface > +void fpa::Base::Algorithm< _TFilter, _TMarksInterface, _TSeedsInterface >:: +_QueueInit( ) +{ + this->_QueueClear( ); +} + +#endif // __fpa__Base__Algorithm__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Dijkstra.h b/lib/fpa/Base/Dijkstra.h new file mode 100644 index 0000000..10489db --- /dev/null +++ b/lib/fpa/Base/Dijkstra.h @@ -0,0 +1,69 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__Dijkstra__h__ +#define __fpa__Base__Dijkstra__h__ + +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TAlgorithm, class _TMST > + class Dijkstra + : public fpa::Base::DijkstraBase< _TAlgorithm > + { + public: + typedef Dijkstra Self; + typedef fpa::Base::DijkstraBase< _TAlgorithm > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TMST TMST; + + typedef typename Superclass::TNode TNode; + typedef typename Superclass::TInputValue TInputValue; + typedef typename Superclass::TOutputValue TOutputValue; + typedef typename Superclass::TFrontId TFrontId; + typedef typename Superclass::TVertex TVertex; + + typedef typename Superclass::TQueue TQueue; + typedef typename Superclass::TQueueOrder TQueueOrder; + typedef typename Superclass::TWeightFunction TWeightFunction; + + public: + TMST* GetMinimumSpanningTree( ); + const TMST* GetMinimumSpanningTree( ) const; + + protected: + Dijkstra( ); + virtual ~Dijkstra( ); + + virtual void _AfterGenerateData( ) override; + virtual void _UpdateOutputValue( const TNode& n ) override; + + private: + // Purposely not implemented. + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned int m_MSTIdx; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__Dijkstra__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Dijkstra.hxx b/lib/fpa/Base/Dijkstra.hxx new file mode 100644 index 0000000..93a102d --- /dev/null +++ b/lib/fpa/Base/Dijkstra.hxx @@ -0,0 +1,74 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__Dijkstra__hxx__ +#define __fpa__Base__Dijkstra__hxx__ + +// ------------------------------------------------------------------------- +template< class _TAlgorithm, class _TMST > +typename fpa::Base::Dijkstra< _TAlgorithm, _TMST >:: +TMST* fpa::Base::Dijkstra< _TAlgorithm, _TMST >:: +GetMinimumSpanningTree( ) +{ + dynamic_cast< TMST* >( + this->itk::ProcessObject::GetOutput( this->m_MSTIdx ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm, class _TMST > +const typename fpa::Base::Dijkstra< _TAlgorithm, _TMST >:: +TMST* fpa::Base::Dijkstra< _TAlgorithm, _TMST >:: +GetMinimumSpanningTree( ) const +{ + dynamic_cast< const TMST* >( + this->itk::ProcessObject::GetOutput( this->m_MSTIdx ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm, class _TMST > +fpa::Base::Dijkstra< _TAlgorithm, _TMST >:: +Dijkstra( ) + : Superclass( ) +{ + this->m_MSTIdx = this->GetNumberOfRequiredOutputs( ); + this->itk::ProcessObject::SetNumberOfRequiredOutputs( this->m_MSTIdx + 1 ); + this->SetNthOutput( this->m_MSTIdx, TMST::New( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm, class _TMST > +fpa::Base::Dijkstra< _TAlgorithm, _TMST >:: +~Dijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm, class _TMST > +void fpa::Base::Dijkstra< _TAlgorithm, _TMST >:: +_AfterGenerateData( ) +{ + typedef typename Superclass::TSeedsInterface::TSeeds::iterator _TIt; + + TMST* mst = this->GetMinimumSpanningTree( ); + mst->ClearSeeds( ); + mst->SetCollisions( this->m_Collisions ); + for( _TIt sIt = this->BeginSeeds( ); sIt != this->EndSeeds( ); ++sIt ) + mst->AddSeed( sIt->Vertex ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm, class _TMST > +void fpa::Base::Dijkstra< _TAlgorithm, _TMST >:: +_UpdateOutputValue( const TNode& n ) +{ + this->Superclass::_UpdateOutputValue( n ); + this->GetMinimumSpanningTree( )->SetParent( n.Vertex, n.Parent ); +} + +#endif // __fpa__Base__Dijkstra__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/DijkstraBase.h b/lib/fpa/Base/DijkstraBase.h new file mode 100644 index 0000000..fd36890 --- /dev/null +++ b/lib/fpa/Base/DijkstraBase.h @@ -0,0 +1,91 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__DijkstraBase__h__ +#define __fpa__Base__DijkstraBase__h__ + +#include + +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TAlgorithm > + class DijkstraBase + : public _TAlgorithm + { + public: + typedef DijkstraBase Self; + typedef _TAlgorithm Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename _TAlgorithm::TNode TNode; + typedef typename _TAlgorithm::TInputValue TInputValue; + typedef typename _TAlgorithm::TOutputValue TOutputValue; + typedef typename _TAlgorithm::TVertex TVertex; + + typedef std::vector< TNode > TQueue; + struct TQueueOrder + { + bool operator()( const TNode& a, const TNode& b ) const + { + return( b.Value < a.Value ); + } + }; + typedef fpa::Base::Functors::Dijkstra::Function< TVertex, TOutputValue > TWeightFunction; + + public: + itkConceptMacro( + Check_TOutputValue, + ( itk::Concept::IsFloatingPoint< TOutputValue > ) + ); + + public: + itkGetObjectMacro( WeightFunction, TWeightFunction ); + itkSetObjectMacro( WeightFunction, TWeightFunction ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const override; + + protected: + DijkstraBase( ); + virtual ~DijkstraBase( ); + + virtual TOutputValue _ComputeOutputValue( const TNode& n ) override; + virtual void _QueueInit( ) override; + virtual void _QueueClear( ) override; + virtual TNode _QueuePop( ) override; + virtual void _QueuePush( const TNode& node ) override; + virtual unsigned long _QueueSize( ) const override; + + private: + // Purposely not implemented. + DijkstraBase( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TWeightFunction::Pointer m_WeightFunction; + + TQueue m_Queue; + TQueueOrder m_QueueOrder; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__DijkstraBase__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/DijkstraBase.hxx b/lib/fpa/Base/DijkstraBase.hxx new file mode 100644 index 0000000..a78554b --- /dev/null +++ b/lib/fpa/Base/DijkstraBase.hxx @@ -0,0 +1,114 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__DijkstraBase__hxx__ +#define __fpa__Base__DijkstraBase__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +itk::ModifiedTimeType fpa::Base::DijkstraBase< _TAlgorithm >:: +GetMTime( ) const +{ + itk::ModifiedTimeType t = this->Superclass::GetMTime( ); + if( this->m_WeightFunction.IsNotNull( ) ) + { + itk::ModifiedTimeType q = this->m_WeightFunction->GetMTime( ); + t = ( q < t )? q: t; + + } // fi + return( t ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +fpa::Base::DijkstraBase< _TAlgorithm >:: +DijkstraBase( ) + : Superclass( ) +{ + this->SetInitValue( std::numeric_limits< TOutputValue >::max( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +fpa::Base::DijkstraBase< _TAlgorithm >:: +~DijkstraBase( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +typename fpa::Base::DijkstraBase< _TAlgorithm >:: +TOutputValue fpa::Base::DijkstraBase< _TAlgorithm >:: +_ComputeOutputValue( const TNode& n ) +{ + TOutputValue c = this->m_WeightFunction->Evaluate( n.Vertex, n.Parent ); + return( c + this->_GetOutputValue( n.Parent ) ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +void fpa::Base::DijkstraBase< _TAlgorithm >:: +_QueueInit( ) +{ + typedef typename Superclass::TSeedsInterface::TSeeds::iterator _TIt; + + this->Superclass::_QueueInit( ); + for( _TIt sIt = this->BeginSeeds( ); sIt != this->EndSeeds( ); ++sIt ) + sIt->Value = TOutputValue( 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +void fpa::Base::DijkstraBase< _TAlgorithm >:: +_QueueClear( ) +{ + this->m_Queue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +typename fpa::Base::DijkstraBase< _TAlgorithm >:: +TNode fpa::Base::DijkstraBase< _TAlgorithm >:: +_QueuePop( ) +{ + std::pop_heap( + this->m_Queue.begin( ), this->m_Queue.end( ), this->m_QueueOrder + ); + TNode n = this->m_Queue.back( ); + this->m_Queue.pop_back( ); + return( n ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +void fpa::Base::DijkstraBase< _TAlgorithm >:: +_QueuePush( const TNode& node ) +{ + bool push_needed = ( node.Parent == node.Vertex ); + push_needed |= !( node.Value < this->_GetOutputValue( node.Parent ) ); + if( push_needed ) + { + this->m_Queue.push_back( node ); + std::push_heap( + this->m_Queue.begin( ), this->m_Queue.end( ), this->m_QueueOrder + ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +unsigned long fpa::Base::DijkstraBase< _TAlgorithm >:: +_QueueSize( ) const +{ + return( this->m_Queue.size( ) ); +} + +#endif // __fpa__Base__DijkstraBase__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/Dijkstra/Function.h b/lib/fpa/Base/Functors/Dijkstra/Function.h new file mode 100644 index 0000000..013cb99 --- /dev/null +++ b/lib/fpa/Base/Functors/Dijkstra/Function.h @@ -0,0 +1,64 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__Functors__Dijkstra__Function__h__ +#define __fpa__Base__Functors__Dijkstra__Function__h__ + +#include + +namespace fpa +{ + namespace Base + { + namespace Functors + { + namespace Dijkstra + { + /** + */ + template< class _TVertex, class _TOutputValue > + class Function + : public itk::Object + { + public: + typedef Function Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( fpa::Base::Functors::Dijkstra::Function, itk::Object ); + + public: + virtual _TOutputValue Evaluate( + const _TVertex& v, const _TVertex& p + ) const = 0; + + protected: + Function( ) + : Superclass( ) + { + } + virtual ~Function( ) + { + } + + private: + // Purposely not implemented + Function( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Base__Functors__Dijkstra__Function__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h b/lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h new file mode 100644 index 0000000..ce533f6 --- /dev/null +++ b/lib/fpa/Base/Functors/RegionGrow/BinaryThreshold.h @@ -0,0 +1,86 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__Functors__RegionGrow__BinaryThreshold__h__ +#define __fpa__Base__Functors__RegionGrow__BinaryThreshold__h__ + +#include +#include + +namespace fpa +{ + namespace Base + { + namespace Functors + { + namespace RegionGrow + { + /** + */ + template< class _TValue > + class BinaryThreshold + : public itk::FunctionBase< _TValue, bool > + { + public: + typedef BinaryThreshold Self; + typedef itk::FunctionBase< _TValue, bool > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Base::Functors::RegionGrow::BinaryThreshold, + itk::FunctionBase + ); + + itkGetConstMacro( Lower, _TValue ); + itkGetConstMacro( Upper, _TValue ); + + itkSetMacro( Lower, _TValue ); + itkSetMacro( Upper, _TValue ); + + public: + virtual bool Evaluate( const _TValue& input ) const override + { + return( this->m_Lower < input && input < this->m_Upper ); + } + + protected: + BinaryThreshold( ) + : Superclass( ) + { + this->m_Upper = std::numeric_limits< _TValue >::max( ); + if( std::numeric_limits< _TValue >::is_integer ) + this->m_Lower = std::numeric_limits< _TValue >::min( ); + else + this->m_Lower = -this->m_Upper; + } + + virtual ~BinaryThreshold( ) + { + } + + private: + // Purposely not implemented + BinaryThreshold( const Self& other ); + Self& operator=( const Self& other ); + + protected: + _TValue m_Lower; + _TValue m_Upper; + }; + + } // ecapseman + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Base__Functors__RegionGrow__BinaryThreshold__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Functors/RegionGrow/Tautology.h b/lib/fpa/Base/Functors/RegionGrow/Tautology.h new file mode 100644 index 0000000..a024b59 --- /dev/null +++ b/lib/fpa/Base/Functors/RegionGrow/Tautology.h @@ -0,0 +1,69 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__Functors__RegionGrow__Tautology__h__ +#define __fpa__Base__Functors__RegionGrow__Tautology__h__ + +#include + +namespace fpa +{ + namespace Base + { + namespace Functors + { + namespace RegionGrow + { + /** + */ + template< class _TValue > + class Tautology + : public itk::FunctionBase< _TValue, bool > + { + public: + typedef Tautology Self; + typedef itk::FunctionBase< _TValue, bool > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Base::Functors::RegionGrow::Tautology, + itk::FunctionBase + ); + + public: + virtual bool Evaluate( const _TValue& input ) const override + { + return( true ); + } + + protected: + Tautology( ) + : Superclass( ) + { + } + virtual ~Tautology( ) + { + } + + private: + // Purposely not implemented + Tautology( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Base__Functors__RegionGrow__Tautology__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Graph.h b/lib/fpa/Base/Graph.h new file mode 100644 index 0000000..41b2fb9 --- /dev/null +++ b/lib/fpa/Base/Graph.h @@ -0,0 +1,170 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__Graph__h__ +#define __fpa__Base__Graph__h__ + +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** \brief A generic graph with templated index types. + * + * @param _TVertex Vertex type. + * @param _TCost Cost type. + * @param _TIndex Index type (it should be a strict weak ordering type). + */ + template< class _TVertex, class _TCost, class _TIndex = unsigned long, class _TIndexCompare = std::less< _TIndex > > + class Graph + : public itk::DataObject + { + public: + typedef Graph Self; + typedef itk::DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TVertex TVertex; + typedef _TCost TCost; + typedef _TIndex TIndex; + typedef _TIndexCompare TIndexCompare; + + // Base types + typedef std::map< TIndex, TVertex, TIndexCompare > TVertices; + typedef std::vector< TCost > TEdges; + typedef std::map< TIndex, TEdges, TIndexCompare > TMatrixRow; + typedef std::map< TIndex, TMatrixRow, TIndexCompare > TMatrix; + + public: + itkNewMacro( Self ); + itkTypeMacro( Graph, itk::DataObject ); + + public: + /*! \brief Iterators over vertices. + * These allow you to iterate over all of graph's vertices. + * + * Typical iteration should be done as: + * + * TGraph g; + * ... + * TGraph::TVertices::[const_]iterator vIt = g.BeginVertices( ); + * for( ; vIt != g.EndVertices( ); ++vIt ) + * { + * vIt->first; --> this is the vertex's index <-- + * vIt->second; --> this is the vertex's value <-- + * } + */ + inline typename TVertices::iterator BeginVertices( ) + { return( this->m_Vertices.begin( ) ); } + inline typename TVertices::iterator EndVertices( ) + { return( this->m_Vertices.end( ) ); } + inline typename TVertices::const_iterator BeginVertices( ) const + { return( this->m_Vertices.begin( ) ); } + inline typename TVertices::const_iterator EndVertices( ) const + { return( this->m_Vertices.end( ) ); } + + /*! \brief Iterators over edges. + * These allow you to iterate over all of graph's edges. + * + * Typical iteration should be done as: + * + * TGraph g; + * ... + * TGraph::TMatrix::[const_]iterator mIt = g.BeginEdgesRows( ); + * for( ; mIt != g.EndEdgesRows( ); ++mIt ) + * { + * mIt->first; --> this is the row index. <-- + * TGraph::TMatrixRow::[const_]iterator rIt = mIt->second.begin( ); + * for( ; rIt != mIt->second.end( ); ++rIt ) + * { + * rIt->first; --> this is the column index. + * TGraph::TEdges::[const_]iterator eIt = rIt->second.begin( ); + * for( ; eIt != rIt->second.end( ); ++eIt ) + * *eIt; --> this is the cost between mIt->first and rIt->first + * } + * } + */ + inline typename TMatrix::iterator BeginEdgesRows( ) + { return( this->m_Matrix.begin( ) ); } + inline typename TMatrix::iterator EndEdgetsRows( ) + { return( this->m_Matrix.end( ) ); } + inline typename TMatrix::const_iterator BeginEdgesRows( ) const + { return( this->m_Matrix.begin( ) ); } + inline typename TMatrix::const_iterator EndEdgesRows( ) const + { return( this->m_Matrix.end( ) ); } + + /*! \brief Clear all vertices and edges. + */ + void Clear( ); + + /*! \brief Clear all edges. + */ + inline void ClearEdges( ) + { this->m_Matrix.clear( ); } + + /*! \brief Vertex manipulation methods. + * Names are self-explanatory. + */ + inline bool HasVertexIndex( const TIndex& i ) const + { return( this->m_Vertices.find( i ) != this->m_Vertices.end( ) ); } + inline void SetVertex( const TIndex& index, TVertex& vertex ) + { this->m_Vertices[ index ] = vertex; } + inline TVertex& GetVertex( const TIndex& index ) + { return( this->m_Vertices[ index ] ); } + inline const TVertex& GetVertex( const TIndex& index ) const + { return( this->m_Vertices[ index ] ); } + bool RenameVertex( const TIndex& old_index, const TIndex& new_index ); + void RemoveVertex( const TIndex& index ); + + /*! \brief Edge manipulation methods. + * Names are self-explanatory. + */ + inline void AddEdge( const TIndex& orig, const TIndex& dest, const TCost& cost ) + { this->m_Matrix[ orig ][ dest ].push_back( cost ); } + TEdges& GetEdges( const TIndex& orig, const TIndex& dest ); + const TEdges& GetEdges( const TIndex& orig, const TIndex& dest ) const; + bool HasEdge( const TIndex& orig, const TIndex& dest ) const; + void RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost ); + void RemoveEdges( const TIndex& orig, const TIndex& dest ); + + /*! \brief Returns graph's sinks. + * + * A sink is a special vertex which does not have any "exiting" edges. + * + * @return Sinks ordered by their index. + */ + std::set< TIndex, TIndexCompare > GetSinks( ) const; + + protected: + Graph( ); + virtual ~Graph( ); + + private: + // Purposely not implemented + Graph( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TVertices m_Vertices; + TMatrix m_Matrix; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__Graph__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/Graph.hxx b/lib/fpa/Base/Graph.hxx new file mode 100644 index 0000000..03f85a8 --- /dev/null +++ b/lib/fpa/Base/Graph.hxx @@ -0,0 +1,272 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__Graph__hxx__ +#define __fpa__Base__Graph__hxx__ + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +Clear( ) +{ + this->m_Vertices.clear( ); + this->m_Matrix.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +bool fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RenameVertex( const TIndex& old_index, const TIndex& new_index ) +{ + typename TVertices::iterator old_v = this->m_Vertices.find( old_index ); + typename TVertices::iterator new_v = this->m_Vertices.find( new_index ); + if( old_v != this->m_Vertices.end( ) && new_v == this->m_Vertices.end( ) ) + { + // Replace vertex + this->m_Vertices[ new_index ] = old_v->second; + this->m_Vertices.erase( old_index ); + + // Duplicate edges + typename TMatrix::iterator mIt = this->m_Matrix.begin( ); + typename TMatrix::iterator found_row = this->m_Matrix.end( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + { + if( mIt->first == old_index ) + found_row = mIt; + + typename TMatrixRow::iterator rIt = mIt->second.begin( ); + for( ; rIt != mIt->second.end( ); ++rIt ) + { + if( mIt->first == old_index ) + this->m_Matrix[ new_index ][ rIt->first ] = rIt->second; + else if( rIt->first == old_index ) + this->m_Matrix[ mIt->first ][ new_index ] = rIt->second; + + } // rof + + } // rof + + // Delete old edges + if( found_row != this->m_Matrix.end( ) ) + this->m_Matrix.erase( found_row ); + + mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + { + typename TMatrixRow::iterator rIt = mIt->second.begin( ); + while( rIt != mIt->second.end( ) ) + { + if( rIt->first == old_index ) + { + mIt->second.erase( rIt ); + rIt = mIt->second.begin( ); + } + else + ++rIt; + + } // elihw + + } // rof + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RemoveVertex( const TIndex& index ) +{ + typename TVertices::iterator i = this->m_Vertices.find( index ); + if( i != this->m_Vertices.end( ) ) + { + // Delete vertex + this->m_Vertices.erase( i ); + + // Delete edges starting from given vertex + typename TMatrix::iterator mIt = this->m_Matrix.find( index ); + if( mIt != this->m_Matrix.end( ) ) + this->m_Matrix.erase( mIt ); + + // Delete edges arriving to given vertex + mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + { + typename TMatrixRow::iterator rIt = mIt->second.begin( ); + while( rIt != mIt->second.end( ) ) + { + if( rIt->first == index ) + { + mIt->second.erase( rIt ); + rIt = mIt->second.begin( ); + } + else + ++rIt; + + } // elihw + + } // rof + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +typename +fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +TEdges& +fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +GetEdges( const TIndex& orig, const TIndex& dest ) +{ + static TEdges null_edges; + typename TMatrix::iterator o = this->m_Matrix.find( orig ); + if( o != this->m_Matrix.find( orig ) ) + { + typename TMatrixRow::iterator d = o->second.find( dest ); + if( d == o->second.end( ) ) + { + null_edges.clear( ); + return( null_edges ); + } + else + return( d->second ); + } + else + { + null_edges.clear( ); + return( null_edges ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +const typename +fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +TEdges& +fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +GetEdges( const TIndex& orig, const TIndex& dest ) const +{ + static const TEdges null_edges; + typename TMatrix::iterator o = this->m_Matrix.find( orig ); + if( o != this->m_Matrix.find( orig ) ) + { + typename TMatrixRow::iterator d = o->second.find( dest ); + if( d == o->second.end( ) ) + return( null_edges ); + else + return( d->second ); + } + else + return( null_edges ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +bool fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +HasEdge( const TIndex& orig, const TIndex& dest ) const +{ + typename TMatrix::const_iterator mIt = this->m_Matrix.find( orig ); + if( mIt != this->m_Matrix.end( ) ) + return( mIt->second.find( dest ) != mIt->second.end( ) ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost ) +{ + typename TMatrix::iterator m = this->m_Matrix.find( orig ); + if( m != this->m_Matrix.end( ) ) + { + typename TMatrixRow::iterator r = m->second.find( dest ); + if( r != m->second.end( ) ) + { + typename TEdges::iterator e = r->second.end( ); + for( + typename TEdges::iterator i = r->second.begin( ); + i != r->second.end( ) && e == r->second.end( ); + ++i + ) + if( *i == cost ) + e = i; + if( e != r->second.end( ) ) + { + r->second.erase( e ); + if( r->second.size( ) == 0 ) + { + m->second.erase( r ); + if( m->second.size( ) == 0 ) + this->m_Matrix.erase( m ); + + } // fi + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +void fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +RemoveEdges( const TIndex& orig, const TIndex& dest ) +{ + typename TMatrix::iterator m = this->m_Matrix.find( orig ); + if( m != this->m_Matrix.end( ) ) + { + typename TMatrixRow::iterator r = m->second.find( dest ); + if( r != m->second.end( ) ) + { + m->second.erase( r ); + if( m->second.size( ) == 0 ) + this->m_Matrix.erase( m ); + + } // fi + + } // fi + +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +std::set< _TIndex, _TIndexCompare > +fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +GetSinks( ) const +{ + std::set< _TIndex, _TIndexCompare > sinks; + + typename TVertices::iterator vIt = this->m_Vertices.begin( ); + for( ; vIt != this->m_Vertices.end( ); ++vIt ) + sinks.insert( vIt->first ); + typename TMatrix::iterator mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + sinks.erase( mIt->first ); + + return( sinks ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +Graph( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare > +fpa::Base::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >:: +~Graph( ) +{ +} + +#endif // __fpa__Base__Graph__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MarksInterface.h b/lib/fpa/Base/MarksInterface.h new file mode 100644 index 0000000..3b99765 --- /dev/null +++ b/lib/fpa/Base/MarksInterface.h @@ -0,0 +1,50 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__MarksInterface__h__ +#define __fpa__Base__MarksInterface__h__ + +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TVertex > + class MarksInterface + { + public: + typedef _TVertex TVertex; + typedef MarksInterface Self; + + protected: + MarksInterface( itk::ProcessObject* filter ); + virtual ~MarksInterface( ); + + virtual bool _IsMarked( const TVertex& v ) const = 0; + virtual unsigned long _GetMark( const TVertex& v ) const = 0; + virtual bool _Mark( const TVertex& v, unsigned long frontId ) = 0; + + virtual void _InitMarks( unsigned long nSeeds ); + virtual bool _Collisions( const TVertex& a, const TVertex& b ); + + protected: + unsigned int m_NumberOfSeeds; + itk::ProcessObject* m_Filter; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__MarksInterface__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MarksInterface.hxx b/lib/fpa/Base/MarksInterface.hxx new file mode 100644 index 0000000..cd37eb5 --- /dev/null +++ b/lib/fpa/Base/MarksInterface.hxx @@ -0,0 +1,43 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__MarksInterface__hxx__ +#define __fpa__Base__MarksInterface__hxx__ + +// ------------------------------------------------------------------------- +template< class _TVertex > +fpa::Base::MarksInterface< _TVertex >:: +MarksInterface( itk::ProcessObject* filter ) + : m_NumberOfSeeds( 0 ), + m_Filter( filter ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +fpa::Base::MarksInterface< _TVertex >:: +~MarksInterface( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +void fpa::Base::MarksInterface< _TVertex >:: +_InitMarks( unsigned long nSeeds ) +{ + this->m_NumberOfSeeds = nSeeds; +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +bool fpa::Base::MarksInterface< _TVertex >:: +_Collisions( const TVertex& a, const TVertex& b ) +{ + return( false ); +} + +#endif // __fpa__Base__MarksInterface__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MarksInterfaceWithCollisions.h b/lib/fpa/Base/MarksInterfaceWithCollisions.h new file mode 100644 index 0000000..3d6f10e --- /dev/null +++ b/lib/fpa/Base/MarksInterfaceWithCollisions.h @@ -0,0 +1,62 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__MarksInterfaceWithCollisions__h__ +#define __fpa__Base__MarksInterfaceWithCollisions__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TVertex > + class MarksInterfaceWithCollisions + : public fpa::Base::MarksInterface< _TVertex > + { + public: + typedef _TVertex TVertex; + typedef MarksInterfaceWithCollisions Self; + typedef fpa::Base::MarksInterface< TVertex > Superclass; + + // Minigraph to represent collisions + typedef std::pair< TVertex, bool > TCollision; + typedef std::vector< TCollision > TCollisionsRow; + typedef std::vector< TCollisionsRow > TCollisions; + + public: + bool StopAtOneFront( ) const; + void StopAtOneFrontOn( ); + void StopAtOneFrontOff( ); + void SetStopAtOneFront( bool v ); + + protected: + MarksInterfaceWithCollisions( itk::ProcessObject* filter ); + virtual ~MarksInterfaceWithCollisions( ); + + virtual void _InitMarks( unsigned long nSeeds ) override; + virtual bool _Collisions( const TVertex& a, const TVertex& b ) override; + + protected: + bool m_StopAtOneFront; + TCollisions m_Collisions; + unsigned int m_NumberOfFronts; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__MarksInterfaceWithCollisions__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MarksInterfaceWithCollisions.hxx b/lib/fpa/Base/MarksInterfaceWithCollisions.hxx new file mode 100644 index 0000000..1230931 --- /dev/null +++ b/lib/fpa/Base/MarksInterfaceWithCollisions.hxx @@ -0,0 +1,133 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__MarksInterfaceWithCollisions__hxx__ +#define __fpa__Base__MarksInterfaceWithCollisions__hxx__ + +#include + +// ------------------------------------------------------------------------- +template< class _TVertex > +bool fpa::Base::MarksInterfaceWithCollisions< _TVertex >:: +StopAtOneFront( ) const +{ + return( this->m_StopAtOneFront ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +void fpa::Base::MarksInterfaceWithCollisions< _TVertex >:: +StopAtOneFrontOn( ) +{ + this->SetStopAtOneFront( true ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +void fpa::Base::MarksInterfaceWithCollisions< _TVertex >:: +StopAtOneFrontOff( ) +{ + this->SetStopAtOneFront( false ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +void fpa::Base::MarksInterfaceWithCollisions< _TVertex >:: +SetStopAtOneFront( bool v ) +{ + if( this->m_StopAtOneFront != v ) + { + this->m_StopAtOneFront = v; + if( this->m_Filter != NULL ) + this->m_Filter->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +fpa::Base::MarksInterfaceWithCollisions< _TVertex >:: +MarksInterfaceWithCollisions( itk::ProcessObject* filter ) + : Superclass( filter ), + m_StopAtOneFront( false ), + m_NumberOfFronts( 0 ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +fpa::Base::MarksInterfaceWithCollisions< _TVertex >:: +~MarksInterfaceWithCollisions( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +void fpa::Base::MarksInterfaceWithCollisions< _TVertex >:: +_InitMarks( unsigned long nSeeds ) +{ + this->Superclass::_InitMarks( nSeeds ); + this->m_NumberOfFronts = nSeeds; + TCollision coll( TVertex( ), false ); + TCollisionsRow row( this->m_NumberOfFronts, coll ); + this->m_Collisions.clear( ); + this->m_Collisions.resize( this->m_NumberOfFronts, row ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex > +bool fpa::Base::MarksInterfaceWithCollisions< _TVertex >:: +_Collisions( const TVertex& a, const TVertex& b ) +{ + unsigned long ma = this->_GetMark( a ); + unsigned long mb = this->_GetMark( b ); + if( ma == mb || ma == 0 || mb == 0 ) + return( false ); + + // Mark collision, if it is new + ma--; mb--; + bool ret = false; + bool exists = this->m_Collisions[ ma ][ mb ].second; + exists &= this->m_Collisions[ mb ][ ma ].second; + if( !exists ) + { + this->m_Collisions[ ma ][ mb ].first = a; + this->m_Collisions[ ma ][ mb ].second = true; + this->m_Collisions[ mb ][ ma ].first = b; + this->m_Collisions[ mb ][ ma ].second = true; + + // Update number of fronts + unsigned long count = 0; + std::vector< bool > m( this->m_NumberOfSeeds, false ); + std::queue< unsigned long > q; + q.push( 0 ); + while( !q.empty( ) ) + { + unsigned long f = q.front( ); + q.pop( ); + + if( m[ f ] ) + continue; + m[ f ] = true; + count++; + + for( unsigned int n = 0; n < this->m_NumberOfSeeds; ++n ) + if( this->m_Collisions[ f ][ n ].second && !m[ n ] ) + q.push( n ); + + } // elihw + this->m_NumberOfFronts = this->m_NumberOfSeeds - count + 1; + + } // fi + return( + this->m_StopAtOneFront && + this->m_NumberOfSeeds > 1 && + this->m_NumberOfFronts == 1 + ); +} + +#endif // __fpa__Base__MarksInterfaceWithCollisions__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MinimumSpanningTree.h b/lib/fpa/Base/MinimumSpanningTree.h new file mode 100644 index 0000000..35cb6e4 --- /dev/null +++ b/lib/fpa/Base/MinimumSpanningTree.h @@ -0,0 +1,77 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__MinimumSpanningTree__h__ +#define __fpa__Base__MinimumSpanningTree__h__ + +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TVertex, class _Superclass > + class MinimumSpanningTree + : public _Superclass + { + public: + typedef MinimumSpanningTree Self; + typedef _Superclass Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TVertex TVertex; + typedef std::pair< TVertex, bool > TCollision; + typedef std::vector< TCollision > TCollisionsRow; + typedef std::vector< TCollisionsRow > TCollisions; + typedef std::vector< TVertex > TVertices; + + protected: + typedef std::vector< unsigned long > _TRow; + typedef std::vector< _TRow > _TMatrix; + + public: + itkTypeMacro( fpa::Base::MinimumSpanningTree, _Superclass ); + + public: + const TCollisions& GetCollisions( ) const; + void SetCollisions( const TCollisions& collisions ); + + void ClearSeeds( ); + void AddSeed( const TVertex& seed ); + + virtual TVertex GetParent( const TVertex& v ) const = 0; + virtual void SetParent( const TVertex& v, const TVertex& p ) = 0; + + virtual TVertices GetPath( const TVertex& a ) const; + virtual TVertices GetPath( const TVertex& a, const TVertex& b ) const; + + protected: + MinimumSpanningTree( ); + virtual ~MinimumSpanningTree( ); + + private: + MinimumSpanningTree( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TCollisions m_Collisions; + _TMatrix m_FrontPaths; + std::vector< TVertex > m_Seeds; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__MinimumSpanningTree__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/MinimumSpanningTree.hxx b/lib/fpa/Base/MinimumSpanningTree.hxx new file mode 100644 index 0000000..c5838f3 --- /dev/null +++ b/lib/fpa/Base/MinimumSpanningTree.hxx @@ -0,0 +1,237 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__MinimumSpanningTree__hxx__ +#define __fpa__Base__MinimumSpanningTree__hxx__ + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +const typename fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +TCollisions& fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +GetCollisions( ) const +{ + return( this->m_Collisions ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +void fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +SetCollisions( const TCollisions& collisions ) +{ + static const unsigned long _inf = + std::numeric_limits< unsigned long >::max( ); + if( this->m_Collisions == collisions ) + return; + + this->m_Collisions = collisions; + + // Prepare a front graph + unsigned long N = this->m_Collisions.size( ); + _TMatrix dist( N, _TRow( N, _inf ) ); + this->m_FrontPaths = dist; + for( unsigned long i = 0; i < N; ++i ) + { + for( unsigned long j = 0; j < N; ++j ) + { + if( this->m_Collisions[ i ][ j ].second ) + { + dist[ i ][ j ] = 1; + dist[ j ][ i ] = 1; + this->m_FrontPaths[ i ][ j ] = j; + this->m_FrontPaths[ j ][ i ] = i; + + } // fi + + } // rof + dist[ i ][ i ] = 0; + this->m_FrontPaths[ i ][ i ] = i; + + } // rof + + // Use Floyd-Warshall to compute all possible paths between fronts + for( unsigned long k = 0; k < N; ++k ) + { + for( unsigned long i = 0; i < N; ++i ) + { + for( unsigned long j = 0; j < N; ++j ) + { + // WARNING: you don't want a numeric overflow!!! + unsigned long dik = dist[ i ][ k ]; + unsigned long dkj = dist[ k ][ j ]; + unsigned long sum = _inf; + if( dik < _inf && dkj < _inf ) + sum = dik + dkj; + + // Ok, continue Floyd-Warshall + if( sum < dist[ i ][ j ] ) + { + dist[ i ][ j ] = sum; + this->m_FrontPaths[ i ][ j ] = this->m_FrontPaths[ i ][ k ]; + + } // fi + + } // rof + + } // rof + + } // rof + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +void fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +ClearSeeds( ) +{ + this->m_Seeds.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +void fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +AddSeed( const _TVertex& seed ) +{ + this->m_Seeds.push_back( seed ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +typename fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +TVertices fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +GetPath( const _TVertex& a ) const +{ + TVertices vertices; + _TVertex it = a; + _TVertex p = this->GetParent( it ); + while( it != p ) + { + vertices.push_back( it ); + it = p; + p = this->GetParent( it ); + + } // elihw + vertices.push_back( it ); + return( vertices ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +typename fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +TVertices fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +GetPath( const _TVertex& a, const _TVertex& b ) const +{ + static const unsigned long _inf = + std::numeric_limits< unsigned long >::max( ); + + TVertices vertices; + TVertices pa = this->GetPath( a ); + TVertices pb = this->GetPath( b ); + if( pa.size( ) > 0 && pb.size( ) > 0 ) + { + // Find front identifiers + unsigned long ia = _inf, ib = _inf; + unsigned long N = this->m_Seeds.size( ); + for( unsigned long i = 0; i < N; ++i ) + { + if( this->m_Seeds[ i ] == pa[ pa.size( ) - 1 ] ) + ia = i; + if( this->m_Seeds[ i ] == pb[ pb.size( ) - 1 ] ) + ib = i; + + } // rof + + // Check if there is a front-jump between given seeds + if( ia != ib ) + { + // Compute front path + std::vector< long > fpath; + fpath.push_back( ia ); + while( ia != ib ) + { + ia = this->m_FrontPaths[ ia ][ ib ]; + fpath.push_back( ia ); + + } // elihw + + // Continue only if both fronts are connected + unsigned int N = fpath.size( ); + if( N > 0 ) + { + // First path: from start vertex to first collision + vertices = this->GetPath( + a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first + ); + + // Intermediary paths + for( unsigned int i = 1; i < N - 1; ++i ) + { + TVertices ipath = + this->GetPath( + this->m_Collisions[ fpath[ i ] ][ fpath[ i - 1 ] ].first, + this->m_Collisions[ fpath[ i ] ][ fpath[ i + 1 ] ].first + ); + for( long id = 0; id < ipath.size( ); ++id ) + vertices.push_back( ipath[ id ] ); + + } // rof + + // Final path: from last collision to end point + TVertices lpath = + this->GetPath( + this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b + ); + for( long id = 0; id < lpath.size( ); ++id ) + vertices.push_back( lpath[ id ] ); + + } // fi + } + else + { + // Ignore common part: find common ancestor + long aIt = pa.size( ) - 1; + long bIt = pb.size( ) - 1; + bool cont = true; + while( aIt >= 0 && bIt >= 0 && cont ) + { + cont = ( pa[ aIt ] == pb[ bIt ] ); + aIt--; + bIt--; + + } // elihw + aIt++; + bIt++; + + // Glue both parts + for( long cIt = 0; cIt <= aIt; ++cIt ) + vertices.push_back( pa[ cIt ] ); + for( ; bIt >= 0; --bIt ) + vertices.push_back( pb[ bIt ] ); + + } // fi + + } // fi + return( vertices ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +MinimumSpanningTree( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _Superclass > +fpa::Base::MinimumSpanningTree< _TVertex, _Superclass >:: +~MinimumSpanningTree( ) +{ +} + +#endif // __fpa__Base__MinimumSpanningTree__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/RegionGrow.h b/lib/fpa/Base/RegionGrow.h new file mode 100644 index 0000000..796c90b --- /dev/null +++ b/lib/fpa/Base/RegionGrow.h @@ -0,0 +1,96 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__RegionGrow__h__ +#define __fpa__Base__RegionGrow__h__ + +#include + +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TAlgorithm > + class RegionGrow + : public _TAlgorithm + { + public: + typedef RegionGrow Self; + typedef _TAlgorithm Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename _TAlgorithm::TNode TNode; + typedef typename _TAlgorithm::TInputValue TInputValue; + typedef typename _TAlgorithm::TOutputValue TOutputValue; + typedef typename _TAlgorithm::TFrontId TFrontId; + typedef typename _TAlgorithm::TVertex TVertex; + + typedef std::deque< TNode > TQueue; + typedef itk::FunctionBase< TInputValue, bool > TValuePredicate; + typedef itk::FunctionBase< TVertex, bool > TVertexPredicate; + + public: + itkConceptMacro( + Check_TOutputValue, + ( itk::Concept::IsUnsignedInteger< TOutputValue > ) + ); + + public: + itkGetObjectMacro( ValuePredicate, TValuePredicate ); + itkGetObjectMacro( VertexPredicate, TVertexPredicate ); + itkGetConstMacro( InsideValue, TOutputValue ); + + itkSetMacro( InsideValue, TOutputValue ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const override; + virtual TOutputValue GetOutsideValue( ) const; + virtual void SetOutsideValue( const TOutputValue& v ); + + void SetPredicate( TValuePredicate* p ); + void SetPredicate( TVertexPredicate* p ); + + protected: + RegionGrow( ); + virtual ~RegionGrow( ); + + virtual TOutputValue _ComputeOutputValue( const TNode& n ) override; + virtual void _QueueInit( ) override; + virtual void _QueueClear( ) override; + virtual TNode _QueuePop( ) override; + virtual void _QueuePush( const TNode& node ) override; + virtual unsigned long _QueueSize( ) const override; + + private: + // Purposely not implemented. + RegionGrow( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TValuePredicate::Pointer m_ValuePredicate; + typename TVertexPredicate::Pointer m_VertexPredicate; + + TOutputValue m_InsideValue; + + TQueue m_Queue; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__RegionGrow__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/RegionGrow.hxx b/lib/fpa/Base/RegionGrow.hxx new file mode 100644 index 0000000..18bb132 --- /dev/null +++ b/lib/fpa/Base/RegionGrow.hxx @@ -0,0 +1,155 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__RegionGrow__hxx__ +#define __fpa__Base__RegionGrow__hxx__ + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +itk::ModifiedTimeType fpa::Base::RegionGrow< _TAlgorithm >:: +GetMTime( ) const +{ + itk::ModifiedTimeType t = this->Superclass::GetMTime( ); + if( this->m_ValuePredicate.IsNotNull( ) ) + { + itk::ModifiedTimeType q = this->m_ValuePredicate->GetMTime( ); + t = ( q < t )? q: t; + + } // fi + if( this->m_VertexPredicate.IsNotNull( ) ) + { + itk::ModifiedTimeType q = this->m_VertexPredicate->GetMTime( ); + t = ( q < t )? q: t; + + } // fi + + return( t ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +typename fpa::Base::RegionGrow< _TAlgorithm >:: +TOutputValue fpa::Base::RegionGrow< _TAlgorithm >:: +GetOutsideValue( ) const +{ + return( this->GetInitValue( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +void fpa::Base::RegionGrow< _TAlgorithm >:: +SetOutsideValue( const TOutputValue& v ) +{ + this->SetInitValue( v ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +void fpa::Base::RegionGrow< _TAlgorithm >:: +SetPredicate( TValuePredicate* p ) +{ + if( this->m_ValuePredicate.GetPointer( ) != p ) + { + this->m_ValuePredicate = p; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +void fpa::Base::RegionGrow< _TAlgorithm >:: +SetPredicate( TVertexPredicate* p ) +{ + if( this->m_VertexPredicate.GetPointer( ) != p ) + { + this->m_VertexPredicate = p; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +fpa::Base::RegionGrow< _TAlgorithm >:: +RegionGrow( ) + : Superclass( ), + m_InsideValue( TOutputValue( 1 ) ) +{ + this->SetInitValue( TOutputValue( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +fpa::Base::RegionGrow< _TAlgorithm >:: +~RegionGrow( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +typename fpa::Base::RegionGrow< _TAlgorithm >:: +TOutputValue fpa::Base::RegionGrow< _TAlgorithm >:: +_ComputeOutputValue( const TNode& n ) +{ + TInputValue value = this->_GetInputValue( n.Vertex ); + bool inside = false; + if( this->m_ValuePredicate.IsNotNull( ) ) + inside = this->m_ValuePredicate->Evaluate( value ); + if( this->m_VertexPredicate.IsNotNull( ) ) + inside &= this->m_VertexPredicate->Evaluate( n.Vertex ); + return( ( inside )? this->m_InsideValue: this->m_InitValue ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +void fpa::Base::RegionGrow< _TAlgorithm >:: +_QueueInit( ) +{ + typedef typename Superclass::TSeedsInterface::TSeeds::iterator _TIt; + + this->Superclass::_QueueInit( ); + for( _TIt sIt = this->BeginSeeds( ); sIt != this->EndSeeds( ); ++sIt ) + sIt->Value = this->m_InsideValue; +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +void fpa::Base::RegionGrow< _TAlgorithm >:: +_QueueClear( ) +{ + this->m_Queue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +typename fpa::Base::RegionGrow< _TAlgorithm >:: +TNode fpa::Base::RegionGrow< _TAlgorithm >:: +_QueuePop( ) +{ + TNode n = this->m_Queue.front( ); + this->m_Queue.pop_front( ); + return( n ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +void fpa::Base::RegionGrow< _TAlgorithm >:: +_QueuePush( const TNode& node ) +{ + this->m_Queue.push_back( node ); +} + +// ------------------------------------------------------------------------- +template< class _TAlgorithm > +unsigned long fpa::Base::RegionGrow< _TAlgorithm >:: +_QueueSize( ) const +{ + return( this->m_Queue.size( ) ); +} + +#endif // __fpa__Base__RegionGrow__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/SeedsInterface.h b/lib/fpa/Base/SeedsInterface.h new file mode 100644 index 0000000..e9c67c3 --- /dev/null +++ b/lib/fpa/Base/SeedsInterface.h @@ -0,0 +1,86 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__SeedsInterface__h__ +#define __fpa__Base__SeedsInterface__h__ + +#include +#include + +#include +#include + +namespace fpa +{ + namespace Base + { + /** + */ + template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare = std::greater< _TVertex > > + class SeedsInterface + { + public: + itkConceptMacro( + Check_TFrontId, + ( itk::Concept::IsUnsignedInteger< _TFrontId > ) + ); + + public: + typedef _TVertex TVertex; + typedef _TInputValue TInputValue; + typedef _TOutputValue TOutputValue; + typedef _TFrontId TFrontId; + typedef _TCompare TCompare; + typedef SeedsInterface Self; + + struct TNode + { + TVertex Vertex; + TVertex Parent; + TFrontId FrontId; + + // Hack to hide the fact that seed values need to be initialized + mutable TOutputValue Value; + }; + struct TNodeCompare + { + bool operator()( const TNode& a, const TNode& b ) const + { + TCompare cmp; + return( cmp( a.Vertex, b.Vertex ) ); + } + }; + typedef std::set< TNode, TNodeCompare > TSeeds; + + public: + unsigned int GetNumberOfSeeds( ) const; + const TSeeds& GetSeeds( ) const; + typename TSeeds::const_iterator BeginSeeds( ) const; + typename TSeeds::const_iterator EndSeeds( ) const; + + virtual void AddSeed( const TVertex& seed ); + virtual void RemoveSeed( const TVertex& seed ); + virtual void ClearSeeds( ); + + protected: + SeedsInterface( itk::ProcessObject* filter ); + virtual ~SeedsInterface( ); + + protected: + TSeeds m_Seeds; + itk::ProcessObject* m_Filter; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Base__SeedsInterface__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Base/SeedsInterface.hxx b/lib/fpa/Base/SeedsInterface.hxx new file mode 100644 index 0000000..5c27216 --- /dev/null +++ b/lib/fpa/Base/SeedsInterface.hxx @@ -0,0 +1,117 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Base__SeedsInterface__hxx__ +#define __fpa__Base__SeedsInterface__hxx__ + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +unsigned int +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +GetNumberOfSeeds( ) const +{ + return( this->m_Seeds.size( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +const typename +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +TSeeds& +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +GetSeeds( ) const +{ + return( this->m_Seeds ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +typename +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +TSeeds::const_iterator +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +BeginSeeds( ) const +{ + return( this->m_Seeds.begin( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +typename +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +TSeeds::const_iterator +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +EndSeeds( ) const +{ + return( this->m_Seeds.end( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +void +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +AddSeed( const TVertex& seed ) +{ + TNode node; + node.Vertex = seed; + node.Parent = seed; + node.FrontId = TFrontId( this->m_Seeds.size( ) + 1 ); + if( this->m_Seeds.insert( node ).second && this->m_Filter != NULL ) + this->m_Filter->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +void +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +RemoveSeed( const TVertex& seed ) +{ + TNode node; + node.Vertex = seed; + node.Parent = seed; + typename TSeeds::const_iterator i = this->m_Seeds.find( node ); + if( i != this->m_Seeds.end( ) ) + { + this->m_Seeds.erase( i ); + if( this->m_Filter != NULL ) + this->m_Filter->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +void +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +ClearSeeds( ) +{ + if( this->m_Seeds.size( ) > 0 ) + { + this->m_Seeds.clear( ); + if( this->m_Filter != NULL ) + this->m_Filter->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +SeedsInterface( itk::ProcessObject* filter ) + : m_Filter( filter ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +~SeedsInterface( ) +{ + this->m_Seeds.clear( ); +} + +#endif // __fpa__Base__SeedsInterface__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/CMakeLists.txt b/lib/fpa/CMakeLists.txt new file mode 100644 index 0000000..264f589 --- /dev/null +++ b/lib/fpa/CMakeLists.txt @@ -0,0 +1,69 @@ + +## ===================== +## == Get source code == +## ===================== + +configure_file(Version.cxx.in "${CMAKE_CURRENT_BINARY_DIR}/Version.cxx" @ONLY) +configure_file(Config.h.in "${CMAKE_CURRENT_BINARY_DIR}/Config.h" @ONLY) +file(GLOB_RECURSE _base_src "${CMAKE_CURRENT_SOURCE_DIR}/Base/*.cxx") +file(GLOB_RECURSE _base_hdr "${CMAKE_CURRENT_SOURCE_DIR}/Base/*.h") +file(GLOB_RECURSE _base_hrc "${CMAKE_CURRENT_SOURCE_DIR}/Base/*.hxx") +file(GLOB_RECURSE _image_src "${CMAKE_CURRENT_SOURCE_DIR}/Image/*.cxx") +file(GLOB_RECURSE _image_hdr "${CMAKE_CURRENT_SOURCE_DIR}/Image/*.h") +file(GLOB_RECURSE _image_hrc "${CMAKE_CURRENT_SOURCE_DIR}/Image/*.hxx") + +set(_src + ${_base_src} ${_image_src} + "${CMAKE_CURRENT_BINARY_DIR}/Version.cxx" + ) +set( + _hdr + ${_base_hdr} ${_image_hdr} + "${CMAKE_CURRENT_BINARY_DIR}/Config.h" + ) +set(_hrc ${_base_hrc} ${_image_hrc}) + +## ===================== +## == Compile library == +## ===================== + +add_library(fpa SHARED ${_src} ${_hdr} ${_hrc}) +generate_export_header(fpa) +set_property(TARGET fpa PROPERTY VERSION ${prj_VERSION}) +set_property(TARGET fpa PROPERTY SOVERSION ${prj_SHORT_VERSION}) +set_property( + TARGET fpa PROPERTY INTERFACE_fpa_MAJOR_VERSION ${prj_MAJ_VERSION} + ) +set_property( + TARGET fpa APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ${prj_MAJ_VERSION} + ) +target_link_libraries(fpa PUBLIC ${VTK_LIBRARIES} ${ITK_LIBRARIES}) + +## ======================== +## == Installation rules == +## ======================== + +install( + TARGETS fpa + EXPORT "${targets_export_name}" + LIBRARY DESTINATION "lib" + ARCHIVE DESTINATION "lib" + RUNTIME DESTINATION "bin" + INCLUDES DESTINATION "${include_install_dir}" + ) +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DESTINATION "${include_install_dir}" + FILES_MATCHING PATTERN "*.h" + ) +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DESTINATION "${include_install_dir}" + FILES_MATCHING PATTERN "*.hxx" + ) +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/fpa_export.h" + DESTINATION "${include_install_dir}/fpa" + ) + +## eof - $RCSfile$ diff --git a/lib/fpa/Config.h.in b/lib/fpa/Config.h.in new file mode 100644 index 0000000..18294bf --- /dev/null +++ b/lib/fpa/Config.h.in @@ -0,0 +1,18 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Config__h__ +#define __fpa__Config__h__ + +#define ivq_FOUND @ivq_FOUND@ +#if ivq_FOUND == 1 +# define USE_ivq +#else +# undef USE_ivq +#endif + +#endif // __fpa__Config__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Algorithm.h b/lib/fpa/Image/Algorithm.h new file mode 100644 index 0000000..5547ff0 --- /dev/null +++ b/lib/fpa/Image/Algorithm.h @@ -0,0 +1,88 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__Algorithm__h__ +#define __fpa__Image__Algorithm__h__ + +#include +#include + +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > + class Algorithm + : public fpa::Base::Algorithm< itk::ImageToImageFilter< _TInputImage, _TOutputImage >, _TMarksInterface, _TSeedsInterface > + { + public: + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + typedef _TMarksInterface TMarksInterface; + typedef _TSeedsInterface TSeedsInterface; + typedef itk::ImageToImageFilter< TInputImage, TOutputImage > TFilter; + + typedef Algorithm Self; + typedef fpa::Base::Algorithm< TFilter, TMarksInterface, TSeedsInterface > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename TInputImage::PixelType TInputValue; + typedef typename TOutputImage::PixelType TOutputValue; + typedef typename Superclass::TFrontId TFrontId; + typedef typename Superclass::TNeighborhood TNeighborhood; + typedef typename Superclass::TNode TNode; + typedef typename Superclass::TVertex TVertex; + + typedef itk::Image< TFrontId, TInputImage::ImageDimension > TMarks; + + public: + itkTypeMacro( fpa::Image::Algorithm, fpa::Base::Algorithm ); + + itkGetConstMacro( NeigborhoodOrder, unsigned int ); + itkSetMacro( NeigborhoodOrder, unsigned int ); + + public: + TMarks* GetMarks( ); + const TMarks* GetMarks( ) const; + + protected: + Algorithm( ); + virtual ~Algorithm( ); + + virtual void _ConfigureOutput( const TOutputValue& v ) override; + virtual TNeighborhood _GetNeighbors( const TVertex& v ) const override; + virtual TInputValue _GetInputValue( const TVertex& v ) const override; + virtual TOutputValue _GetOutputValue( const TVertex& v ) const override; + virtual void _UpdateOutputValue( const TNode& n ) override; + virtual bool _IsMarked( const TVertex& v ) const override; + virtual unsigned long _GetMark( const TVertex& v ) const override; + virtual bool _Mark( const TVertex& v, unsigned long frontId ) override; + + private: + // Purposely not implemented. + Algorithm( const Self& other ); + Self& operator=( const Self& other ); + + protected: + unsigned long m_MarksIdx; + unsigned int m_NeigborhoodOrder; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__Algorithm__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Algorithm.hxx b/lib/fpa/Image/Algorithm.hxx new file mode 100644 index 0000000..0ae9b90 --- /dev/null +++ b/lib/fpa/Image/Algorithm.hxx @@ -0,0 +1,176 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__Algorithm__hxx__ +#define __fpa__Image__Algorithm__hxx__ + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +typename +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +TMarks* +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +GetMarks( ) +{ + dynamic_cast< TMarks* >( + this->itk::ProcessObject::GetOutput( this->m_MarksIdx ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +const typename +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +TMarks* +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +GetMarks( ) const +{ + dynamic_cast< const TMarks* >( + this->itk::ProcessObject::GetOutput( this->m_MarksIdx ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +Algorithm( ) + : Superclass( ), + m_NeigborhoodOrder( 1 ) +{ + this->m_MarksIdx = this->GetNumberOfRequiredOutputs( ); + this->itk::ProcessObject::SetNumberOfRequiredOutputs( this->m_MarksIdx + 1 ); + this->SetNthOutput( this->m_MarksIdx, TMarks::New( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +~Algorithm( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +void +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +_ConfigureOutput( const TOutputValue& v ) +{ + const TInputImage* in = this->GetInput( ); + + TOutputImage* out = this->GetOutput( ); + out->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) ); + out->SetRequestedRegion( in->GetRequestedRegion( ) ); + out->SetBufferedRegion( in->GetBufferedRegion( ) ); + out->SetSpacing( in->GetSpacing( ) ); + out->SetOrigin( in->GetOrigin( ) ); + out->SetDirection( in->GetDirection( ) ); + out->Allocate( ); + out->FillBuffer( v ); + + TMarks* marks = this->GetMarks( ); + marks->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) ); + marks->SetRequestedRegion( in->GetRequestedRegion( ) ); + marks->SetBufferedRegion( in->GetBufferedRegion( ) ); + marks->SetSpacing( in->GetSpacing( ) ); + marks->SetOrigin( in->GetOrigin( ) ); + marks->SetDirection( in->GetDirection( ) ); + marks->Allocate( ); + marks->FillBuffer( TFrontId( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +typename +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +TNeighborhood fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +_GetNeighbors( const TVertex& v ) const +{ + typename TInputImage::RegionType region = + this->GetInput( )->GetRequestedRegion( ); + TNeighborhood neighborhood; + if( this->m_NeigborhoodOrder != 1 ) + { + // TODO + } + else + { + for( unsigned int d = 0; d < TInputImage::ImageDimension; ++d ) + { + for( int s = -1; s <= 1; s += 2 ) + { + TVertex n = v; + n[ d ] += s; + if( region.IsInside( n ) ) + neighborhood.push_back( n ); + + } // rof + + } // rof + + } // fi + return( neighborhood ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +typename +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +TInputValue +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +_GetInputValue( const TVertex& v ) const +{ + return( this->GetInput( )->GetPixel( v ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +typename +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +TOutputValue fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +_GetOutputValue( const TVertex& v ) const +{ + return( this->GetOutput( )->GetPixel( v ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +void +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +_UpdateOutputValue( const TNode& n ) +{ + this->GetOutput( )->SetPixel( n.Vertex, n.Value ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +bool +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +_IsMarked( const TVertex& v ) const +{ + return( this->GetMarks( )->GetPixel( v ) > 0 ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +unsigned long +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +_GetMark( const TVertex& v ) const +{ + return( ( unsigned long )( this->GetMarks( )->GetPixel( v ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage, class _TMarksInterface, class _TSeedsInterface > +bool +fpa::Image::Algorithm< _TInputImage, _TOutputImage, _TMarksInterface, _TSeedsInterface >:: +_Mark( const TVertex& v, unsigned long frontId ) +{ + this->GetMarks( )->SetPixel( v, TFrontId( frontId ) ); + return( true ); +} + +#endif // __fpa__Image__Algorithm__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Dijkstra.h b/lib/fpa/Image/Dijkstra.h new file mode 100644 index 0000000..d5a1bb9 --- /dev/null +++ b/lib/fpa/Image/Dijkstra.h @@ -0,0 +1,103 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__Dijkstra__h__ +#define __fpa__Image__Dijkstra__h__ + +#include +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage, class _TFrontId = unsigned char > + class Dijkstra + : public fpa::Base::Dijkstra< fpa::Image::Algorithm< _TInputImage, _TOutputImage, fpa::Base::MarksInterfaceWithCollisions< typename _TInputImage::IndexType >, fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::PixelType, typename _TOutputImage::PixelType, _TFrontId, typename _TInputImage::IndexType::LexicographicCompare > >, fpa::Image::MinimumSpanningTree< _TInputImage::ImageDimension > > + { + public: + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + typedef _TFrontId TFrontId; + + typedef typename TInputImage::IndexType TVertex; + typedef typename TVertex::LexicographicCompare TVertexCompare; + typedef typename TInputImage::PixelType TInputValue; + typedef typename TOutputImage::PixelType TOutputValue; + + typedef fpa::Base::MarksInterfaceWithCollisions< TVertex > TMarksInterface; + typedef fpa::Base::SeedsInterface< TVertex, TInputValue, TOutputValue, TFrontId, TVertexCompare > TSeedsInterface; + typedef fpa::Image::Algorithm< TInputImage, TOutputImage, TMarksInterface, TSeedsInterface > TAlgorithm; + typedef fpa::Image::MinimumSpanningTree< TInputImage::ImageDimension > TMST; + + typedef Dijkstra Self; + typedef fpa::Base::Dijkstra< TAlgorithm, TMST > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef fpa::Image::Functors::Dijkstra::Function< TInputImage, TOutputValue > TWeightFunction; + + public: + itkNewMacro( Self ); + itkTypeMacro( fpa::Image::Dijkstra, fpa::Base::Dijkstra ); + + protected: + Dijkstra( ) + : Superclass( ) + { + typedef fpa::Image::Functors::Dijkstra::Identity< TInputImage, TOutputValue > _TDefaultFunction; + this->SetWeightFunction( _TDefaultFunction::New( ) ); + } + virtual ~Dijkstra( ) + { + } + + virtual void _ConfigureOutput( const TOutputValue& v ) override + { + this->Superclass::_ConfigureOutput( v ); + const TInputImage* in = this->GetInput( ); + + TMST* mst = this->GetMinimumSpanningTree( ); + mst->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) ); + mst->SetRequestedRegion( in->GetRequestedRegion( ) ); + mst->SetBufferedRegion( in->GetBufferedRegion( ) ); + mst->SetSpacing( in->GetSpacing( ) ); + mst->SetOrigin( in->GetOrigin( ) ); + mst->SetDirection( in->GetDirection( ) ); + mst->Allocate( ); + + typename TMST::PixelType zero; + zero.Fill( 0 ); + mst->FillBuffer( zero ); + } + + virtual void _BeforeGenerateData( ) override + { + this->Superclass::_BeforeGenerateData( ); + TWeightFunction* wf = + dynamic_cast< TWeightFunction* >( this->GetWeightFunction( ) ); + if( wf != NULL ) + wf->SetImage( this->GetInput( ) ); + } + + private: + // Purposely not implemented. + Dijkstra( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Image__Dijkstra__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/Dijkstra/Function.h b/lib/fpa/Image/Functors/Dijkstra/Function.h new file mode 100644 index 0000000..e9fa0b2 --- /dev/null +++ b/lib/fpa/Image/Functors/Dijkstra/Function.h @@ -0,0 +1,69 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__Functors__Dijkstra__Function__h__ +#define __fpa__Image__Functors__Dijkstra__Function__h__ + +#include + +namespace fpa +{ + namespace Image + { + namespace Functors + { + namespace Dijkstra + { + /** + */ + template< class _TInputImage, class _TOutputValue > + class Function + : public fpa::Base::Functors::Dijkstra::Function< typename _TInputImage::IndexType, _TOutputValue > + { + public: + typedef typename _TInputImage::IndexType TVertex; + typedef Function Self; + typedef fpa::Base::Functors::Dijkstra::Function< TVertex, _TOutputValue > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( + fpa::Image::Functors::Dijkstra::Function, + fpa::Base::Functors::Dijkstra::Function + ); + + itkGetConstObjectMacro( Image, _TInputImage ); + itkSetConstObjectMacro( Image, _TInputImage ); + + protected: + Function( ) + : Superclass( ) + { + } + virtual ~Function( ) + { + } + + private: + // Purposely not implemented + Function( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename _TInputImage::ConstPointer m_Image; + }; + + } // ecapseman + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Image__Functors__Dijkstra__Function__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/Dijkstra/Gaussian.h b/lib/fpa/Image/Functors/Dijkstra/Gaussian.h new file mode 100644 index 0000000..5187312 --- /dev/null +++ b/lib/fpa/Image/Functors/Dijkstra/Gaussian.h @@ -0,0 +1,104 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__Functors__Dijkstra__Gaussian__h__ +#define __fpa__Image__Functors__Dijkstra__Gaussian__h__ + +#include +#include + +namespace fpa +{ + namespace Image + { + namespace Functors + { + namespace Dijkstra + { + /** + */ + template< class _TInputImage, class _TOutputValue > + class Gaussian + : public fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue > + { + public: + typedef Gaussian Self; + typedef fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TVertex TVertex; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Image::Functors::Dijkstra::Gaussian, + fpa::Image::Functors::Dijkstra::Function + ); + + public: + double GetAlpha( ) const + { + return( double( 1 ) - this->m_Alpha ); + } + double GetBeta( ) const + { + return( std::sqrt( this->m_Beta ) ); + } + void SetAlpha( const double& v ) + { + this->m_Alpha = double( 1 ) - v; + this->Modified( ); + } + void SetBeta( const double& v ) + { + this->m_Beta = v * v; + this->Modified( ); + } + + virtual _TOutputValue Evaluate( + const TVertex& v, const TVertex& p + ) const override + { + double d = double( this->m_Image->GetPixel( v ) ); + d -= double( this->m_Image->GetPixel( p ) ); + d = ( d * d ) / this->m_Beta; + return( + _TOutputValue( double( 1 ) - ( this->m_Alpha * std::exp( -d ) ) ) + ); + } + + protected: + Gaussian( ) + : Superclass( ), + m_Alpha( double( 1 ) ), + m_Beta( double( 1 ) ) + { + } + virtual ~Gaussian( ) + { + } + + private: + // Purposely not implemented + Gaussian( const Self& other ); + Self& operator=( const Self& other ); + + protected: + double m_Alpha; + double m_Beta; + }; + + } // ecapseman + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Image__Functors__Dijkstra__Gaussian__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/Dijkstra/Identity.h b/lib/fpa/Image/Functors/Dijkstra/Identity.h new file mode 100644 index 0000000..3a0b370 --- /dev/null +++ b/lib/fpa/Image/Functors/Dijkstra/Identity.h @@ -0,0 +1,73 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__Functors__Dijkstra__Identity__h__ +#define __fpa__Image__Functors__Dijkstra__Identity__h__ + +#include + +namespace fpa +{ + namespace Image + { + namespace Functors + { + namespace Dijkstra + { + /** + */ + template< class _TInputImage, class _TOutputValue > + class Identity + : public fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue > + { + public: + typedef Identity Self; + typedef fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TVertex TVertex; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Image::Functors::Dijkstra::Identity, + fpa::Image::Functors::Dijkstra::Function + ); + + public: + virtual _TOutputValue Evaluate( + const TVertex& v, const TVertex& p + ) const override + { + return( _TOutputValue( this->m_Image->GetPixel( v ) ) ); + } + + protected: + Identity( ) + : Superclass( ) + { + } + virtual ~Identity( ) + { + } + + private: + // Purposely not implemented + Identity( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Image__Functors__Dijkstra__Identity__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Functors/Dijkstra/Invert.h b/lib/fpa/Image/Functors/Dijkstra/Invert.h new file mode 100644 index 0000000..8341f2e --- /dev/null +++ b/lib/fpa/Image/Functors/Dijkstra/Invert.h @@ -0,0 +1,94 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__Functors__Dijkstra__Invert__h__ +#define __fpa__Image__Functors__Dijkstra__Invert__h__ + +#include +#include + +namespace fpa +{ + namespace Image + { + namespace Functors + { + namespace Dijkstra + { + /** + */ + template< class _TInputImage, class _TOutputValue > + class Invert + : public fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue > + { + public: + typedef Invert Self; + typedef fpa::Image::Functors::Dijkstra::Function< _TInputImage, _TOutputValue > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TVertex TVertex; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Image::Functors::Dijkstra::Invert, + fpa::Image::Functors::Dijkstra::Function + ); + + itkGetConstMacro( Alpha, double ); + itkGetConstMacro( Beta, double ); + + itkSetMacro( Alpha, double ); + itkSetMacro( Beta, double ); + + public: + virtual _TOutputValue Evaluate( + const TVertex& v, const TVertex& p + ) const override + { + double a = double( this->m_Image->GetPixel( v ) ); + double d = this->m_Alpha; + d += std::pow( double( a ), this->m_Beta ); + double x = -1; + if( std::fabs( d ) > double( 0 ) ) + x = + double( 1 ) / + ( this->m_Alpha + std::pow( double( a ), this->m_Beta ) ); + return( _TOutputValue( x ) ); + } + + protected: + Invert( ) + : Superclass( ), + m_Alpha( double( 1 ) ), + m_Beta( double( 1 ) ) + { + } + virtual ~Invert( ) + { + } + + private: + // Purposely not implemented + Invert( const Self& other ); + Self& operator=( const Self& other ); + + protected: + double m_Alpha; + double m_Beta; + }; + + } // ecapseman + + } // ecapseman + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Image__Functors__Dijkstra__Invert__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/LabelledSeedsInterface.h b/lib/fpa/Image/LabelledSeedsInterface.h new file mode 100644 index 0000000..2492b84 --- /dev/null +++ b/lib/fpa/Image/LabelledSeedsInterface.h @@ -0,0 +1,62 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__LabelledSeedsInterface__h__ +#define __fpa__Image__LabelledSeedsInterface__h__ + +#include + +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare = std::greater< _TVertex > > + class LabelledSeedsInterface + : public fpa::Base::SeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare > + { + public: + typedef _TVertex TVertex; + typedef _TInputValue TInputValue; + typedef _TOutputValue TOutputValue; + typedef _TFrontId TFrontId; + typedef _TCompare TCompare; + typedef LabelledSeedsInterface Self; + typedef fpa::Base::SeedsInterface< TVertex, TInputValue, TOutputValue, TFrontId, TCompare > Superclass; + + typedef typename Superclass::TNode TNode; + typedef typename Superclass::TNodeCompare TNodeCompare; + typedef typename Superclass::TSeeds TSeeds; + + typedef itk::Image< TFrontId, TVertex::Dimension > TLabelImage; + + public: + virtual void AddSeed( const TVertex& seed ) override; + + const TLabelImage* GetLabels( ) const; + void SetLabels( const TLabelImage* image ); + + protected: + LabelledSeedsInterface( itk::ProcessObject* filter ); + virtual ~LabelledSeedsInterface( ); + + protected: + typename TLabelImage::ConstPointer m_LabelImage; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__LabelledSeedsInterface__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/LabelledSeedsInterface.hxx b/lib/fpa/Image/LabelledSeedsInterface.hxx new file mode 100644 index 0000000..a9a73c9 --- /dev/null +++ b/lib/fpa/Image/LabelledSeedsInterface.hxx @@ -0,0 +1,64 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__LabelledSeedsInterface__hxx__ +#define __fpa__Image__LabelledSeedsInterface__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +void +fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +AddSeed( const TVertex& seed ) +{ + std::ostringstream msg; + msg << "itk::ERROR: fpa::Image::LabelledSeedsInterface (" << this + << "): \"AddSeed( const TVertex& seed )\" is not valid for this class. " + << "Use \"SetLabels( TLabelImage* labels )\" instead."; + ::itk::ExceptionObject e( + __FILE__, __LINE__, msg.str( ).c_str( ), ITK_LOCATION + ); + throw e; +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +const typename +fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +TLabelImage* +fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +GetLabels( ) const +{ + return( this->m_LabelImage ); +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +void fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +SetLabels( const TLabelImage* image ) +{ + this->m_LabelImage = image; +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +LabelledSeedsInterface( itk::ProcessObject* filter ) + : Superclass( filter ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TVertex, class _TInputValue, class _TOutputValue, class _TFrontId, class _TCompare > +fpa::Image::LabelledSeedsInterface< _TVertex, _TInputValue, _TOutputValue, _TFrontId, _TCompare >:: +~LabelledSeedsInterface( ) +{ +} + +#endif // __fpa__Image__LabelledSeedsInterface__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/MinimumSpanningTree.h b/lib/fpa/Image/MinimumSpanningTree.h new file mode 100644 index 0000000..a93157c --- /dev/null +++ b/lib/fpa/Image/MinimumSpanningTree.h @@ -0,0 +1,71 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__MinimumSpanningTree__h__ +#define __fpa__Image__MinimumSpanningTree__h__ + +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< unsigned int _VDim > + class MinimumSpanningTree + : public fpa::Base::MinimumSpanningTree< itk::Index< _VDim >, itk::Image< itk::Offset< _VDim >, _VDim > > + { + public: + typedef itk::Index< _VDim > TVertex; + typedef itk::Image< itk::Offset< _VDim >, _VDim > TBaseImage; + + typedef MinimumSpanningTree Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + typedef fpa::Base::MinimumSpanningTree< TVertex, TBaseImage > Superclass; + + typedef typename Superclass::TCollision TCollision; + typedef typename Superclass::TCollisionsRow TCollisionsRow; + typedef typename Superclass::TCollisions TCollisions; + typedef typename Superclass::TVertices TVertices; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Image::MinimumSpanningTree, + fpa::Base::MinimumSpanningTree + ); + + public: + virtual TVertex GetParent( const TVertex& v ) const override + { + return( v + this->GetPixel( v ) ); + } + virtual void SetParent( const TVertex& v, const TVertex& p ) override + { + this->SetPixel( v, p - v ); + } + + protected: + MinimumSpanningTree( ) + : Superclass( ) + { } + virtual ~MinimumSpanningTree( ) + { } + + private: + MinimumSpanningTree( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Image__MinimumSpanningTree__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/PathsToImageFilter.h b/lib/fpa/Image/PathsToImageFilter.h new file mode 100644 index 0000000..dd467cd --- /dev/null +++ b/lib/fpa/Image/PathsToImageFilter.h @@ -0,0 +1,84 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__PathsToImageFilter__h__ +#define __fpa__Image__PathsToImageFilter__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TMST, class _TOutputPixelValue > + class PathsToImageFilter + : public itk::ImageToImageFilter< _TMST, itk::Image< itk::RGBAPixel< _TOutputPixelValue >, _TMST::ImageDimension > > + { + public: + typedef _TMST TMST; + typedef _TOutputPixelValue TOutputPixelValue; + typedef itk::RGBAPixel< TOutputPixelValue > TOutputPixel; + typedef itk::Image< TOutputPixel, TMST::ImageDimension > TOutputImage; + + typedef PathsToImageFilter Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + typedef itk::ImageToImageFilter< TMST, TOutputImage > Superclass; + + typedef typename TMST::IndexType TIndex; + struct TPathData + { + TIndex Start; + TIndex End; + TOutputPixelValue Red; + TOutputPixelValue Green; + TOutputPixelValue Blue; + }; + typedef std::vector< TPathData > TPaths; + + public: + itkNewMacro( Self ); + itkTypeMacro( + fpa::Image::PathsToImageFilter, + itk::ImageToImageFilter + ); + + public: + void AddPath( + const TIndex& start, const TIndex& end, + const TOutputPixelValue& r = TOutputPixelValue( 1 ), + const TOutputPixelValue& g = TOutputPixelValue( 0 ), + const TOutputPixelValue& b = TOutputPixelValue( 0 ) + ); + + protected: + PathsToImageFilter( ); + virtual ~PathsToImageFilter( ); + + virtual void GenerateData( ) override; + + private: + PathsToImageFilter( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TPaths m_Paths; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__PathsToImageFilter__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/PathsToImageFilter.hxx b/lib/fpa/Image/PathsToImageFilter.hxx new file mode 100644 index 0000000..487b9c8 --- /dev/null +++ b/lib/fpa/Image/PathsToImageFilter.hxx @@ -0,0 +1,79 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__PathsToImageFilter__hxx__ +#define __fpa__Image__PathsToImageFilter__hxx__ + +// ------------------------------------------------------------------------- +template< class _TMST, class _TOutputPixelValue > +void fpa::Image::PathsToImageFilter< _TMST, _TOutputPixelValue >:: +AddPath( + const TIndex& start, const TIndex& end, + const TOutputPixelValue& r, + const TOutputPixelValue& g, + const TOutputPixelValue& b + ) +{ + if( start != end ) + { + TPathData d; + d.Start = start; + d.End = end; + d.Red = r; + d.Green = g; + d.Blue = b; + this->m_Paths.push_back( d ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TMST, class _TOutputPixelValue > +fpa::Image::PathsToImageFilter< _TMST, _TOutputPixelValue >:: +PathsToImageFilter( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TMST, class _TOutputPixelValue > +fpa::Image::PathsToImageFilter< _TMST, _TOutputPixelValue >:: +~PathsToImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TMST, class _TOutputPixelValue > +void fpa::Image::PathsToImageFilter< _TMST, _TOutputPixelValue >:: +GenerateData( ) +{ + TOutputPixel color; + color.Fill( 0 ); + + const TMST* mst = this->GetInput( ); + TOutputImage* output = this->GetOutput( ); + output->SetBufferedRegion( mst->GetBufferedRegion( ) ); + output->Allocate( ); + output->FillBuffer( color ); + + typename TPaths::const_iterator d = this->m_Paths.begin( ); + for( ; d != this->m_Paths.end( ); ++d ) + { + typename TMST::TVertices path = mst->GetPath( d->Start, d->End ); + color[ 0 ] = d->Red; + color[ 1 ] = d->Green; + color[ 2 ] = d->Blue; + color[ 3 ] = std::numeric_limits< TOutputPixelValue >::max( ); + typename TMST::TVertices::const_iterator i = path.begin( ); + for( ; i != path.end( ); ++i ) + output->SetPixel( *i, color ); + + } // rof +} + +#endif // __fpa__Image__PathsToImageFilter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/PolyLineParametricPath.h b/lib/fpa/Image/PolyLineParametricPath.h new file mode 100644 index 0000000..7fd6489 --- /dev/null +++ b/lib/fpa/Image/PolyLineParametricPath.h @@ -0,0 +1,97 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__PolyLineParametricPath__h__ +#define __fpa__Image__PolyLineParametricPath__h__ + +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< unsigned int _VDim > + class PolyLineParametricPath + : public itk::PolyLineParametricPath< _VDim > + { + public: + typedef PolyLineParametricPath Self; + typedef itk::PolyLineParametricPath< _VDim > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef itk::ImageBase< _VDim > TImageBase; + typedef typename TImageBase::SpacingType TSpacing; + typedef typename TImageBase::PointType TPoint; + typedef typename TImageBase::DirectionType TDirection; + typedef typename Superclass::ContinuousIndexType TContinuousIndex; + typedef typename TContinuousIndex::IndexType TIndex; + + public: + itkNewMacro( Self ); + itkTypeMacro( PolyLineParametricPath, itk::PolyLineParametricPath ); + + itkGetConstReferenceMacro( Spacing, TSpacing ); + itkGetConstReferenceMacro( Origin, TPoint ); + itkGetConstReferenceMacro( Direction, TDirection ); + itkGetConstReferenceMacro( InverseDirection, TDirection ); + + itkSetMacro( Origin, TPoint ); + + public: + unsigned long GetSize( ) const; + TContinuousIndex GetContinuousVertex( unsigned long i ) const; + TIndex GetVertex( unsigned long i ) const; + TPoint GetPoint( unsigned long i ) const; + + virtual void SetSpacing( const TSpacing& spac ); + virtual void SetSpacing( const double spac[ _VDim ] ); + virtual void SetSpacing( const float spac[ _VDim ] ); + virtual void SetOrigin( const double ori[ _VDim ] ); + virtual void SetOrigin( const float ori[ _VDim ] ); + virtual void SetDirection( const TDirection& dir ); + + template< class _TRefImage > + inline void SetReferenceImage( const _TRefImage* image ) + { + this->SetSpacing( image->GetSpacing( ) ); + this->SetOrigin( image->GetOrigin( ) ); + this->SetDirection( image->GetDirection( ) ); + } + + protected: + PolyLineParametricPath( ); + virtual ~PolyLineParametricPath( ); + + virtual void _ComputeIndexToPhysicalPointMatrices( ); + + private: + // Purposely not implemented + PolyLineParametricPath( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TSpacing m_Spacing; + TPoint m_Origin; + TDirection m_Direction; + TDirection m_InverseDirection; + TDirection m_IndexToPhysicalPoint; + TDirection m_PhysicalPointToIndex; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__PolyLineParametricPath__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/PolyLineParametricPath.hxx b/lib/fpa/Image/PolyLineParametricPath.hxx new file mode 100644 index 0000000..4616dcf --- /dev/null +++ b/lib/fpa/Image/PolyLineParametricPath.hxx @@ -0,0 +1,194 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__PolyLineParametricPath__hxx__ +#define __fpa__Image__PolyLineParametricPath__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +unsigned long fpa::Image::PolyLineParametricPath< _VDim >:: +GetSize( ) const +{ + return( this->GetVertexList( )->Size( ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::Image::PolyLineParametricPath< _VDim >:: +TContinuousIndex +fpa::Image::PolyLineParametricPath< _VDim >:: +GetContinuousVertex( unsigned long i ) const +{ + return( this->GetVertexList( )->GetElement( i ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::Image::PolyLineParametricPath< _VDim >:: +TIndex fpa::Image::PolyLineParametricPath< _VDim >:: +GetVertex( unsigned long i ) const +{ + TContinuousIndex cidx = this->GetContinuousVertex( i ); + TIndex idx; + for( unsigned int d = 0; d < _VDim; ++d ) + idx[ d ] = cidx[ d ]; + return( idx ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +typename fpa::Image::PolyLineParametricPath< _VDim >:: +TPoint fpa::Image::PolyLineParametricPath< _VDim >:: +GetPoint( unsigned long i ) const +{ + typedef typename TPoint::CoordRepType _TCoordRep; + TPoint pnt; + TContinuousIndex idx = this->GetVertex( i ); + for( unsigned int r = 0; r < _VDim; ++r ) + { + _TCoordRep sum = itk::NumericTraits< _TCoordRep >::ZeroValue( ); + for( unsigned int c = 0; c < _VDim; ++c ) + sum += this->m_IndexToPhysicalPoint( r, c ) * idx[ c ]; + pnt[ r ] = sum + this->m_Origin[ r ]; + + } // rof + return( pnt ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::Image::PolyLineParametricPath< _VDim >:: +SetSpacing( const TSpacing& spac ) +{ + if( this->m_Spacing != spac ) + { + this->m_Spacing = spac; + this->_ComputeIndexToPhysicalPointMatrices( ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::Image::PolyLineParametricPath< _VDim >:: +SetSpacing( const double spac[ _VDim ] ) +{ + this->SetSpacing( TSpacing( spac ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::Image::PolyLineParametricPath< _VDim >:: +SetSpacing( const float spac[ _VDim ] ) +{ + TSpacing s; + for( unsigned int d = 0; d < _VDim; ++d ) + s[ d ] = spac[ d ]; + this->SetSpacing( s ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::Image::PolyLineParametricPath< _VDim >:: +SetOrigin( const double ori[ _VDim ] ) +{ + this->SetOrigin( TPoint( ori ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::Image::PolyLineParametricPath< _VDim >:: +SetOrigin( const float ori[ _VDim ] ) +{ + this->SetOrigin( TPoint( ori ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::Image::PolyLineParametricPath< _VDim >:: +SetDirection( const TDirection& dir ) +{ + bool modified = false; + for( unsigned int r = 0; r < _VDim; r++ ) + { + for( unsigned int c = 0; c < _VDim; c++ ) + { + if( + itk::Math::NotExactlyEquals( + this->m_Direction[ r ][ c ], dir[ r ][ c ] + ) + ) + { + this->m_Direction[ r ][ c ] = dir[ r ][ c ]; + modified = true; + } // fi + + } // rof + + } // rof + if( modified ) + { + this->_ComputeIndexToPhysicalPointMatrices( ); + this->m_InverseDirection = this->m_Direction.GetInverse( ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::Image::PolyLineParametricPath< _VDim >:: +PolyLineParametricPath( ) + : Superclass( ) +{ + this->m_Spacing.Fill( 1.0 ); + this->m_Origin.Fill( 0.0 ); + this->m_Direction.SetIdentity( ); + this->m_InverseDirection.SetIdentity( ); + this->m_IndexToPhysicalPoint.SetIdentity( ); + this->m_PhysicalPointToIndex.SetIdentity( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::Image::PolyLineParametricPath< _VDim >:: +~PolyLineParametricPath( ) +{ +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::Image::PolyLineParametricPath< _VDim >:: +_ComputeIndexToPhysicalPointMatrices( ) +{ + TDirection scale; + scale.Fill( 0.0 ); + for( unsigned int i = 0; i < _VDim; i++ ) + { + if( this->m_Spacing[ i ] == 0.0 ) + itkExceptionMacro( + "A spacing of 0 is not allowed: Spacing is " << this->m_Spacing + ); + scale[ i ][ i ] = this->m_Spacing[ i ]; + + } // rof + + if( vnl_determinant( this->m_Direction.GetVnlMatrix( ) ) == 0.0 ) + itkExceptionMacro( + << "Bad direction, determinant is 0. Direction is " + << this->m_Direction + ); + this->m_IndexToPhysicalPoint = this->m_Direction * scale; + this->m_PhysicalPointToIndex = this->m_IndexToPhysicalPoint.GetInverse( ); + this->Modified( ); +} + +#endif // __fpa__Image__PolyLineParametricPath__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/RandomWalker.h b/lib/fpa/Image/RandomWalker.h new file mode 100644 index 0000000..9e41147 --- /dev/null +++ b/lib/fpa/Image/RandomWalker.h @@ -0,0 +1,78 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__RandomWalker__h__ +#define __fpa__Image__RandomWalker__h__ + +#include + +#include +#include +#include +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TLabelImage, class _TScalar > + class RandomWalker + : public fpa::Base::DijkstraBase< fpa::Image::Algorithm< _TInputImage, itk::Image< _TScalar, _TInputImage::ImageDimension >, fpa::Base::MarksInterface< typename _TInputImage::IndexType >, fpa::Image::LabelledSeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::PixelType, _TScalar, typename _TLabelImage::PixelType, typename _TInputImage::IndexType::LexicographicCompare > > > + { + public: + typedef _TInputImage TInputImage; + typedef _TLabelImage TLabelImage; + typedef _TScalar TScalar; + typedef typename TInputImage::IndexType TVertex; + typedef typename TVertex::LexicographicCompare TVertexCompare; + typedef typename TInputImage::PixelType TInputValue; + typedef typename TLabelImage::PixelType TFrontId; + + typedef itk::Image< TScalar, _TInputImage::ImageDimension > TOutputImage; + typedef fpa::Base::MarksInterface< TVertex > TMarksInterface; + typedef fpa::Image::LabelledSeedsInterface< TVertex, TInputValue, _TScalar, TFrontId, TVertexCompare > TSeedsInterface; + typedef fpa::Image::Algorithm< _TInputImage, TOutputImage, TMarksInterface, TSeedsInterface > TAlgorithm; + + typedef RandomWalker Self; + typedef fpa::Base::DijkstraBase< TAlgorithm > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef fpa::Image::Functors::Dijkstra::Function< TInputImage, TScalar > TWeightFunction; + + public: + itkNewMacro( Self ); + itkTypeMacro( fpa::Image::RandomWalker, fpa::Base::RandomWalker ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const override; + + protected: + RandomWalker( ); + virtual ~RandomWalker( ); + + virtual void _BeforeGenerateData( ) override; + virtual void _QueueInit( ) override; + + private: + // Purposely not implemented. + RandomWalker( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__RandomWalker__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/RandomWalker.hxx b/lib/fpa/Image/RandomWalker.hxx new file mode 100644 index 0000000..9016e97 --- /dev/null +++ b/lib/fpa/Image/RandomWalker.hxx @@ -0,0 +1,124 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__RandomWalker__hxx__ +#define __fpa__Image__RandomWalker__hxx__ + +#include + +#include +#include + +#include + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TLabelImage, class _TScalar > +itk::ModifiedTimeType +fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >:: +GetMTime( ) const +{ + const TLabelImage* labels = this->GetLabels( ); + itk::ModifiedTimeType t = this->Superclass::GetMTime( ); + if( labels != NULL ) + { + itk::ModifiedTimeType q = labels->GetMTime( ); + t = ( q < t )? q: t; + + } // fi + return( t ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TLabelImage, class _TScalar > +fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >:: +RandomWalker( ) + : Superclass( ) +{ + typedef fpa::Image::Functors::Dijkstra::Gaussian< TInputImage, TScalar > _TDefaultFunction; + this->SetWeightFunction( _TDefaultFunction::New( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TLabelImage, class _TScalar > +fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >:: +~RandomWalker( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TLabelImage, class _TScalar > +void fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >:: +_BeforeGenerateData( ) +{ + this->Superclass::_BeforeGenerateData( ); + TWeightFunction* wf = + dynamic_cast< TWeightFunction* >( this->GetWeightFunction( ) ); + if( wf != NULL ) + wf->SetImage( this->GetInput( ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TLabelImage, class _TScalar > +void fpa::Image::RandomWalker< _TInputImage, _TLabelImage, _TScalar >:: +_QueueInit( ) +{ + this->m_Seeds.clear( ); + const TLabelImage* lbl = this->GetLabels( ); + if( lbl == NULL ) + { + std::ostringstream msg; + msg << "itk::ERROR: fpa::Image::RandomWalker (" << this + << "): Labelled image not defined."; + ::itk::ExceptionObject e( + __FILE__, __LINE__, msg.str( ).c_str( ), ITK_LOCATION + ); + throw e; + + } // fi + + // Iterate over labels + typename TLabelImage::RegionType reg = lbl->GetRequestedRegion( ); + itk::ImageRegionConstIteratorWithIndex< TLabelImage > lIt( lbl, reg ); + for( lIt.GoToBegin( ); !lIt.IsAtEnd( ); ++lIt ) + { + if( lIt.Get( ) > 0 ) + { + bool is_seed = false; + for( unsigned int d = 0; d < TLabelImage::ImageDimension; ++d ) + { + for( int s = -1; s <= 1; s += 2 ) + { + TVertex neigh = lIt.GetIndex( ); + neigh[ d ] += s; + is_seed |= ( lbl->GetPixel( neigh ) == 0 ); + + } // rof + + } // rof + + typename TSeedsInterface::TNode node; + node.Vertex = lIt.GetIndex( ); + node.Parent = lIt.GetIndex( ); + node.FrontId = lIt.Get( ); + node.Value = TScalar( 0 ); + if( !is_seed ) + { + this->_Mark( lIt.GetIndex( ), lIt.Get( ) ); + this->_UpdateOutputValue( node ); + } + else + this->m_Seeds.insert( node ); + + } // fi + + } // rof + + // Ok, finish initialization + this->Superclass::_QueueInit( ); +} + +#endif // __fpa__Image__RandomWalker__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/RegionGrow.h b/lib/fpa/Image/RegionGrow.h new file mode 100644 index 0000000..6a09487 --- /dev/null +++ b/lib/fpa/Image/RegionGrow.h @@ -0,0 +1,68 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__RegionGrow__h__ +#define __fpa__Image__RegionGrow__h__ + +#include +#include +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TOutputImage, class _TFrontId = unsigned char > + class RegionGrow + : public fpa::Base::RegionGrow< fpa::Image::Algorithm< _TInputImage, _TOutputImage, fpa::Base::MarksInterfaceWithCollisions< typename _TInputImage::IndexType >, fpa::Base::SeedsInterface< typename _TInputImage::IndexType, typename _TInputImage::PixelType, typename _TOutputImage::PixelType, _TFrontId, typename _TInputImage::IndexType::LexicographicCompare > > > + { + public: + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + typedef _TFrontId TFrontId; + + typedef typename TInputImage::IndexType TVertex; + typedef typename TVertex::LexicographicCompare TVertexCompare; + typedef typename TInputImage::PixelType TInputValue; + typedef typename TOutputImage::PixelType TOutputValue; + + typedef fpa::Base::MarksInterfaceWithCollisions< TVertex > TMarksInterface; + typedef fpa::Base::SeedsInterface< TVertex, TInputValue, TOutputValue, TFrontId, TVertexCompare > TSeedsInterface; + typedef fpa::Image::Algorithm< TInputImage, TOutputImage, TMarksInterface, TSeedsInterface > TAlgorithm; + + typedef RegionGrow Self; + typedef fpa::Base::RegionGrow< TAlgorithm > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( fpa::Image::RegionGrow, fpa::Base::RegionGrow ); + + protected: + RegionGrow( ) + : Superclass( ) + { + } + virtual ~RegionGrow( ) + { + } + + private: + // Purposely not implemented. + RegionGrow( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __fpa__Image__RegionGrow__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Skeleton.h b/lib/fpa/Image/Skeleton.h new file mode 100644 index 0000000..4942702 --- /dev/null +++ b/lib/fpa/Image/Skeleton.h @@ -0,0 +1,67 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__Skeleton__h__ +#define __fpa__Image__Skeleton__h__ + +#include +#include +#include + +namespace fpa +{ + namespace Image + { + /** + */ + template< unsigned int _VDim > + class Skeleton + : public fpa::Base::Graph< typename fpa::Image::PolyLineParametricPath< _VDim >::TIndex, typename fpa::Image::PolyLineParametricPath< _VDim >::Pointer, typename fpa::Image::PolyLineParametricPath< _VDim >::TIndex, typename fpa::Image::PolyLineParametricPath< _VDim >::TIndex::LexicographicCompare > + { + public: + typedef fpa::Image::PolyLineParametricPath< _VDim > TPath; + typedef typename TPath::TIndex TIndex; + typedef typename TIndex::LexicographicCompare TIndexCompare; + typedef typename TPath::Pointer TPathPointer; + + itkStaticConstMacro( Dimension, unsigned int, _VDim ); + + typedef fpa::Base::Graph< TIndex, TPathPointer, TIndex, TIndexCompare > Superclass; + typedef Skeleton Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( Skeleton, fpa::Image::Graph ); + + public: + void AddBranch( TPath* path ); + const TPath* GetBranch( const TIndex& a, const TIndex& b ) const; + + std::vector< TIndex > GetEndPoints( ) const; + std::vector< TIndex > GetBifurcations( ) const; + + protected: + Skeleton( ); + virtual ~Skeleton( ); + + private: + // Purposely not implemented + Skeleton( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__Skeleton__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/Skeleton.hxx b/lib/fpa/Image/Skeleton.hxx new file mode 100644 index 0000000..99424e9 --- /dev/null +++ b/lib/fpa/Image/Skeleton.hxx @@ -0,0 +1,99 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__Skeleton__hxx__ +#define __fpa__Image__Skeleton__hxx__ + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +void fpa::Image::Skeleton< _VDim >:: +AddBranch( TPath* path ) +{ + // Check inputs + if( path == NULL ) + return; + unsigned long size = path->GetSize( ); + if( size == 0 ) + return; + TIndex a = path->GetVertex( 0 ); + TIndex b = path->GetVertex( size - 1 ); + if( this->HasEdge( a, b ) ) + return; + + // Add path + this->SetVertex( a, a ); + this->SetVertex( b, b ); + this->AddEdge( a, b, path ); + this->AddEdge( b, a, path ); + // TODO: this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +const typename fpa::Image::Skeleton< _VDim >:: +TPath* fpa::Image::Skeleton< _VDim >:: +GetBranch( const TIndex& a, const TIndex& b ) const +{ + static const TPath* null_path = NULL; + if( this->HasEdge( a, b ) ) + return( this->GetEdges( a, b ).front( ) ); + else + return( null_path ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +std::vector< typename fpa::Image::Skeleton< _VDim >::TIndex > +fpa::Image::Skeleton< _VDim >:: +GetEndPoints( ) const +{ + std::vector< TIndex > res; + typename Superclass::TMatrix::const_iterator mIt = this->BeginEdgesRows( ); + for( ; mIt != this->EndEdgesRows( ); ++mIt ) + { + unsigned long count = mIt->second.size( ); + if( count == 1 ) + res.push_back( mIt->first ); + + } // rof + return( res ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +std::vector< typename fpa::Image::Skeleton< _VDim >::TIndex > +fpa::Image::Skeleton< _VDim >:: +GetBifurcations( ) const +{ + std::vector< TIndex > res; + typename Superclass::TMatrix::const_iterator mIt = this->BeginEdgesRows( ); + for( ; mIt != this->EndEdgesRows( ); ++mIt ) + { + unsigned long count = mIt->second.size( ); + if( count > 1 ) + res.push_back( mIt->first ); + + } // rof + return( res ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::Image::Skeleton< _VDim >:: +Skeleton( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< unsigned int _VDim > +fpa::Image::Skeleton< _VDim >:: +~Skeleton( ) +{ +} + +#endif // __fpa__Image__Skeleton__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/SkeletonFilter.h b/lib/fpa/Image/SkeletonFilter.h new file mode 100644 index 0000000..296ac87 --- /dev/null +++ b/lib/fpa/Image/SkeletonFilter.h @@ -0,0 +1,160 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__SkeletonFilter__h__ +#define __fpa__Image__SkeletonFilter__h__ + +#include +#include +#include +#include + +/* + #include + #include + + + #include + + #include + #include +*/ + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TInputImage, class _TDistanceMap = itk::SignedMaurerDistanceMapImageFilter< _TInputImage, itk::Image< double, _TInputImage::ImageDimension > > > + class SkeletonFilter + : public itk::ProcessObject + { + public: + typedef SkeletonFilter Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TInputImage TInputImage; + typedef _TDistanceMap TDistanceMap; + itkStaticConstMacro( + Dimension, + unsigned int, + TInputImage::ImageDimension + ); + + typedef typename TDistanceMap::OutputImageType TOutputImage; + typedef typename TInputImage::IndexType TIndex; + typedef typename TOutputImage::PixelType TScalar; + + typedef fpa::Image::Skeleton< Self::Dimension > TSkeleton; + + protected: + typedef std::multimap< TScalar, TIndex > _TSkeletonQueue; + + /** + */ + class _TDijkstra + : public fpa::Image::Dijkstra< TOutputImage, TOutputImage > + { + public: + typedef _TDijkstra Self; + typedef fpa::Image::Dijkstra< TOutputImage, TOutputImage > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TNode TNode; + typedef typename Superclass::TMST TMST; + + public: + itkNewMacro( Self ); + itkTypeMacro( _TDijkstra, fpa::Image::Dijkstra ); + + itkGetConstReferenceMacro( SkeletonQueue, _TSkeletonQueue ); + + protected: + _TDijkstra( ); + virtual ~_TDijkstra( ); + + virtual void _BeforeGenerateData( ) override; + virtual void _UpdateOutputValue( const TNode& n ) override; + + private: + // Purposely not implemented + _TDijkstra( const Self& other ); + Self& operator=( const Self& other ); + + protected: + _TSkeletonQueue m_SkeletonQueue; + }; + typedef typename _TDijkstra::TMST _TMST; + + public: + itkNewMacro( Self ); + itkTypeMacro( fpa::Image::SkeletonFilter, fpa::Image::Dijkstra ); + + itkBooleanMacro( SeedFromMaximumDistance ); + itkGetConstMacro( SeedFromMaximumDistance, bool ); + itkSetMacro( SeedFromMaximumDistance, bool ); + + itkGetConstObjectMacro( DistanceMap, TDistanceMap ); + itkGetObjectMacro( DistanceMap, TDistanceMap ); + + itkGetConstMacro( Seed, TIndex ); + itkSetMacro( Seed, TIndex ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const override; + + void SetInput( TInputImage* input ); + TInputImage* GetInput( ); + const TInputImage* GetInput( ) const; + + TSkeleton* GetOutput( ); + const TSkeleton* GetOutput( ) const; + + protected: + SkeletonFilter( ); + virtual ~SkeletonFilter( ); + + virtual void GenerateData( ) override; + + template< class _TMarksPointer > + void _MarkSphere( + _TMarksPointer& marks, + const TOutputImage* dmap, + const TIndex& center + ); + + void _EndPoints( + std::vector< TIndex >& end_points, + const TOutputImage* dmap, + const _TMST* mst, + const _TSkeletonQueue& queue + ); + + private: + // Purposely not implemented. + SkeletonFilter( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TDistanceMap::Pointer m_DistanceMap; + bool m_SeedFromMaximumDistance; + TIndex m_Seed; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__SkeletonFilter__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/SkeletonFilter.hxx b/lib/fpa/Image/SkeletonFilter.hxx new file mode 100644 index 0000000..0f33388 --- /dev/null +++ b/lib/fpa/Image/SkeletonFilter.hxx @@ -0,0 +1,359 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__SkeletonFilter__hxx__ +#define __fpa__Image__SkeletonFilter__hxx__ + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::_TDijkstra:: +_TDijkstra( ) + : Superclass( ) +{ + // Prepare weight function + typedef fpa::Image::Functors::Dijkstra::Invert< TOutputImage, TScalar > _TWeight; + typename _TWeight::Pointer weight = _TWeight::New( ); + weight->SetAlpha( 1 ); + weight->SetBeta( 1 ); + this->SetWeightFunction( weight ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::_TDijkstra:: +~_TDijkstra( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::_TDijkstra:: +_BeforeGenerateData( ) +{ + this->Superclass::_BeforeGenerateData( ); + this->m_SkeletonQueue.clear( ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >::_TDijkstra:: +_UpdateOutputValue( const TNode& n ) +{ + typedef typename _TSkeletonQueue::value_type _TSkeletonQueueValue; + + this->Superclass::_UpdateOutputValue( n ); + double d = double( this->GetInput( )->GetPixel( n.Vertex ) ); + if( d >= double( 0 ) ) + { + // Update skeleton candidates + d += double( 1e-5 ); + double v = double( n.Value ) / ( d * d ); + this->m_SkeletonQueue.insert( _TSkeletonQueueValue( v, n.Vertex ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +itk::ModifiedTimeType +fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +GetMTime( ) const +{ + itk::ModifiedTimeType t = this->Superclass::GetMTime( ); + itk::ModifiedTimeType q = this->m_DistanceMap->GetMTime( ); + return( ( q < t )? q: t ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +SetInput( TInputImage* input ) +{ + this->Superclass::SetNthInput( 0, input ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +typename fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +TInputImage* fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +GetInput( ) +{ + return( dynamic_cast< TInputImage* >( this->Superclass::GetInput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +const typename fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +TInputImage* fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +GetInput( ) const +{ + return( + dynamic_cast< const TInputImage* >( this->Superclass::GetInput( 0 ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +typename fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +TSkeleton* fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +GetOutput( ) +{ + return( dynamic_cast< TSkeleton* >( this->Superclass::GetOutput( 0 ) ) ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +const typename fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +TSkeleton* fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +GetOutput( ) const +{ + return( + dynamic_cast< const TSkeleton* >( this->Superclass::GetOutput( 0 ) ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +SkeletonFilter( ) + : Superclass( ), + m_SeedFromMaximumDistance( false ) +{ + this->SetNumberOfRequiredInputs( 1 ); + this->SetNumberOfRequiredOutputs( 1 ); + this->SetNthOutput( 0, TSkeleton::New( ) ); + + this->m_DistanceMap = TDistanceMap::New( ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +~SkeletonFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +GenerateData( ) +{ + // Update distance map + this->m_DistanceMap->SetInput( this->GetInput( ) ); + this->m_DistanceMap->Update( ); + + // Correct seed + if( this->m_SeedFromMaximumDistance ) + { + typedef itk::MinimumMaximumImageCalculator< TOutputImage > _TMinMax; + typename _TMinMax::Pointer minmax = _TMinMax::New( ); + minmax->SetImage( this->m_DistanceMap->GetOutput( ) ); + minmax->Compute( ); + this->m_Seed = minmax->GetIndexOfMaximum( ); + + } // fi + + // Compute MST + typename _TDijkstra::Pointer dijkstra = _TDijkstra::New( ); + dijkstra->SetInput( this->m_DistanceMap->GetOutput( ) ); + dijkstra->AddSeed( this->m_Seed ); + dijkstra->Update( ); + + // Compute end-points + std::vector< TIndex > end_points; + this->_EndPoints( + end_points, + this->m_DistanceMap->GetOutput( ), + dijkstra->GetMinimumSpanningTree( ), + dijkstra->GetSkeletonQueue( ) + ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +template< class _TMarksPointer > +void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +_MarkSphere( + _TMarksPointer& marks, const TOutputImage* dmap, const TIndex& center + ) +{ + typedef typename _TMarksPointer::ObjectType _TMarks; + typedef itk::ImageRegionIteratorWithIndex< _TMarks > _TMarksIt; + + static const double _eps = std::sqrt( double( Self::Dimension + 1 ) ); + typename _TMarks::SpacingType spac = dmap->GetSpacing( ); + typename _TMarks::RegionType region = dmap->GetRequestedRegion( ); + + typename _TMarks::PointType cnt; + dmap->TransformIndexToPhysicalPoint( center, cnt ); + double r = double( dmap->GetPixel( center ) ) * _eps; + + TIndex i0, i1; + for( unsigned int d = 0; d < Self::Dimension; ++d ) + { + long off = long( std::ceil( r / double( spac[ d ] ) ) ); + if( off < 3 ) + off = 3; + i0[ d ] = center[ d ] - off; + i1[ d ] = center[ d ] + off; + + if( i0[ d ] < region.GetIndex( )[ d ] ) + i0[ d ] = region.GetIndex( )[ d ]; + + if( i1[ d ] >= region.GetIndex( )[ d ] + region.GetSize( )[ d ] ) + i1[ d ] = region.GetIndex( )[ d ] + region.GetSize( )[ d ] - 1; + + } // rof + + typename _TMarks::SizeType size; + for( unsigned int d = 0; d < Self::Dimension; ++d ) + size[ d ] = i1[ d ] - i0[ d ] + 1; + + typename _TMarks::RegionType neighRegion; + neighRegion.SetIndex( i0 ); + neighRegion.SetSize( size ); + + _TMarksIt mIt( marks, neighRegion ); + for( mIt.GoToBegin( ); !mIt.IsAtEnd( ); ++mIt ) + mIt.Set( true ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TDistanceMap > +void fpa::Image::SkeletonFilter< _TInputImage, _TDistanceMap >:: +_EndPoints( + std::vector< TIndex >& end_points, + const TOutputImage* dmap, + const _TMST* mst, + const _TSkeletonQueue& queue + ) +{ + typedef typename _TSkeletonQueue::value_type _TSkeletonQueueValue; + + // Some values + typedef itk::Image< bool, Self::Dimension > _TMarks; + typename _TMarks::Pointer marks = _TMarks::New( ); + marks->SetLargestPossibleRegion( mst->GetLargestPossibleRegion( ) ); + marks->SetRequestedRegion( mst->GetRequestedRegion( ) ); + marks->SetBufferedRegion( mst->GetBufferedRegion( ) ); + marks->SetSpacing( mst->GetSpacing( ) ); + marks->SetOrigin( mst->GetOrigin( ) ); + marks->SetDirection( mst->GetDirection( ) ); + marks->Allocate( ); + marks->FillBuffer( false ); + + // Get candidates in maximum to minimum iteration + typename _TSkeletonQueue::const_reverse_iterator nIt = queue.rbegin( ); + for( ; nIt != queue.rend( ); ++nIt ) + { + // Mark it and update end-points + if( !( marks->GetPixel( nIt->second ) ) ) + { + marks->SetPixel( nIt->second, true ); + end_points.push_back( nIt->second ); + + // Mark path + TIndex it = nIt->second; + TIndex p = mst->GetParent( it ); + while( it != p ) + { + this->_MarkSphere( marks, dmap, it ); + it = p; + p = mst->GetParent( it ); + + } // elihw + this->_MarkSphere( marks, dmap, it ); + + } // fi + + } // rof +} + + + +/* TODO + this->m_DistanceMap = TDistanceMap::New( ); + this->m_DistanceMap->InsideIsPositiveOn( ); + this->m_DistanceMap->SquaredDistanceOff( ); + this->m_DistanceMap->UseImageSpacingOn( ); + + template< class _TImage, class _TScalar > + void fpa::Image::SkeletonFilter< _TImage, _TScalar >:: + _Skeleton( const std::vector< TVertex >& end_points, _TAdjacencies& A ) + { + typedef typename TSkeleton::TPath _TPath; + typedef itk::Image< unsigned long, TImage::ImageDimension > _TTagsImage; + + TMST* mst = this->GetMinimumSpanningTree( ); + TSkeleton* skeleton = this->GetSkeleton( ); + + // Tag branches + typename _TTagsImage::Pointer tags = _TTagsImage::New( ); + tags->SetLargestPossibleRegion( mst->GetLargestPossibleRegion( ) ); + tags->SetRequestedRegion( mst->GetRequestedRegion( ) ); + tags->SetBufferedRegion( mst->GetBufferedRegion( ) ); + tags->Allocate( ); + tags->FillBuffer( 0 ); + typename std::vector< TVertex >::const_iterator eIt = end_points.begin( ); + for( ; eIt != end_points.end( ); ++eIt ) + { + TVertex it = *eIt; + TVertex p = mst->GetParent( it ); + while( it != p ) + { + tags->SetPixel( it, tags->GetPixel( it ) + 1 ); + it = p; + p = mst->GetParent( it ); + + } // elihw + tags->SetPixel( it, tags->GetPixel( it ) + 1 ); + + } // rof + + // Build paths (branches) + eIt = end_points.begin( ); + for( ; eIt != end_points.end( ); ++eIt ) + { + TVertex it = *eIt; + TVertex p = mst->GetParent( it ); + TVertex sIdx = it; + typename _TPath::Pointer path = _TPath::New( ); + path->SetReferenceImage( mst ); + while( it != p ) + { + if( tags->GetPixel( sIdx ) != tags->GetPixel( it ) ) + { + // Ok, a new branch has been added + path->AddVertex( it ); + skeleton->AddBranch( path ); + + // Update a new starting index + path = _TPath::New( ); + path->SetReferenceImage( mst ); + sIdx = it; + } + else + path->AddVertex( it ); + it = p; + p = mst->GetParent( it ); + + } // elihw + + // Finally, add last branch + path->AddVertex( it ); + skeleton->AddBranch( path ); + + } // rof + } +*/ + +#endif // __fpa__Image__SkeletonFilter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/VisualDebugger.h b/lib/fpa/Image/VisualDebugger.h new file mode 100644 index 0000000..90e94e1 --- /dev/null +++ b/lib/fpa/Image/VisualDebugger.h @@ -0,0 +1,98 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__VisualDebugger__h__ +#define __fpa__Image__VisualDebugger__h__ + +#include + +#include + +#include +#include +#include + +#ifdef USE_ivq +#include +#endif // USE_ivq + +class vtkRenderer; +class vtkRenderWindowInteractor; + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TFilter > + class VisualDebugger + : public itk::Command + { + public: + typedef VisualDebugger Self; + typedef itk::Command Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef _TFilter TFilter; + typedef typename TFilter::TInputImage TImage; + + typedef itk::RGBAPixel< unsigned char > TLabel; + typedef itk::Image< TLabel, TImage::ImageDimension > TLabels; +#ifdef USE_ivq + typedef itk::ImageToVTKImageFilter< TLabels > TVTKLabels; +#endif // USE_ivq + + public: + itkTypeMacro( fpa::Image::VisualDebugger, itk::Command ); + + itkGetConstObjectMacro( Labels, TLabels ); + + public: + void SetVisualization( + vtkRenderer* renderer, vtkRenderWindowInteractor* iren + ); + virtual void Execute( + itk::Object* caller, const itk::EventObject& event + ) override; + virtual void Execute( + const itk::Object* caller, const itk::EventObject& event + ) override; + + virtual void Render( ) = 0; + virtual void StartVisualization( ) = 0; + virtual void EndVisualization( ) = 0; + + protected: + VisualDebugger( ); + virtual ~VisualDebugger( ); + + private: + // Purposely not implemented. + VisualDebugger( const Self& other ); + Self& operator=( const Self& other ); + + protected: + std::vector< TLabel > m_Colors; + typename TLabels::Pointer m_Labels; +#ifdef USE_ivq + vtkRenderer* m_Renderer; + vtkRenderWindowInteractor* m_Interactor; + typename TVTKLabels::Pointer m_VTKLabels; +#endif // USE_ivq + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__VisualDebugger__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/VisualDebugger.hxx b/lib/fpa/Image/VisualDebugger.hxx new file mode 100644 index 0000000..d45a803 --- /dev/null +++ b/lib/fpa/Image/VisualDebugger.hxx @@ -0,0 +1,134 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__VisualDebugger__hxx__ +#define __fpa__Image__VisualDebugger__hxx__ + +// ------------------------------------------------------------------------- +template< class _TFilter > +void fpa::Image::VisualDebugger< _TFilter >:: +SetVisualization( vtkRenderer* renderer, vtkRenderWindowInteractor* iren ) +{ +#ifdef USE_ivq + this->m_Renderer = renderer; + this->m_Interactor = iren; + this->Modified( ); +#endif // USE_ivq +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +void fpa::Image::VisualDebugger< _TFilter >:: +Execute( itk::Object* caller, const itk::EventObject& event ) +{ + this->Execute( const_cast< const itk::Object* >( caller ), event ); +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +void fpa::Image::VisualDebugger< _TFilter >:: +Execute( const itk::Object* caller, const itk::EventObject& event ) +{ + typedef itk::StartEvent _TStart; + typedef itk::EndEvent _TEnd; + typedef typename _TFilter::TEvent _TEvent; + + // Check validity + const TFilter* filter = dynamic_cast< const TFilter* >( caller ); + if( filter == NULL ) + return; + + // Get correct event type + const _TEvent* ev_fpa = dynamic_cast< const _TEvent* >( &event ); + const _TStart* ev_start = dynamic_cast< const _TStart* >( &event ); + const _TEnd* ev_end = dynamic_cast< const _TEnd* >( &event ); + if( ev_fpa != NULL ) + { + if( this->m_Labels.IsNotNull( ) ) + { + TLabel new_color; + if( ev_fpa->IntoQueue ) + new_color = this->m_Colors[ this->m_Colors.size( ) - 2 ]; + else + new_color = + this->m_Colors[ + ( ev_fpa->FrontId - 1 ) % ( this->m_Colors.size( ) - 2 ) + ]; + TLabel old_color = this->m_Labels->GetPixel( ev_fpa->Vertex ); + if( !( new_color == old_color ) ) + { + this->m_Labels->SetPixel( ev_fpa->Vertex, new_color ); + this->m_VTKLabels->Modified( ); + this->Render( ); + + } // fi + + } // fi + } + else if( ev_start != NULL ) + { + const TImage* image = filter->GetInput( ); + this->m_Labels = TLabels::New( ); + this->m_Labels-> + SetLargestPossibleRegion( image->GetLargestPossibleRegion( ) ); + this->m_Labels->SetRequestedRegion( image->GetRequestedRegion( ) ); + this->m_Labels->SetBufferedRegion( image->GetBufferedRegion( ) ); + this->m_Labels->SetOrigin( image->GetOrigin( ) ); + this->m_Labels->SetSpacing( image->GetSpacing( ) ); + this->m_Labels->SetDirection( image->GetDirection( ) ); + this->m_Labels->Allocate( ); + this->m_Labels->FillBuffer( this->m_Colors.back( ) ); +#ifdef USE_ivq + this->m_VTKLabels = TVTKLabels::New( ); + this->m_VTKLabels->SetInput( this->m_Labels ); + this->m_VTKLabels->Update( ); + this->StartVisualization( ); +#endif // USE_ivq + } + else if( ev_end != NULL ) + { + this->EndVisualization( ); + this->m_Labels = NULL; + this->m_VTKLabels = NULL; + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +fpa::Image::VisualDebugger< _TFilter >:: +VisualDebugger( ) + : Superclass( ) +{ + unsigned char colors[ 8 ][ 4 ] = + { + { 255, 0, 0, 128 }, + { 0, 255, 0, 128 }, + { 0, 0, 255, 128 }, + { 0, 255, 255, 128 }, + { 255, 0, 255, 128 }, + { 255, 255, 0, 128 }, + { 255, 128, 64, 255 }, + { 0, 0, 0, 0 } + }; + for( unsigned int i = 0; i < 8; ++i ) + this->m_Colors.push_back( TLabel( colors[ i ] ) ); + +#ifdef USE_ivq + this->m_Renderer = NULL; + this->m_Interactor = NULL; +#endif // USE_ivq +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +fpa::Image::VisualDebugger< _TFilter >:: +~VisualDebugger( ) +{ +} + +#endif // __fpa__Image__VisualDebugger__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/VisualDebugger2D.h b/lib/fpa/Image/VisualDebugger2D.h new file mode 100644 index 0000000..21346d9 --- /dev/null +++ b/lib/fpa/Image/VisualDebugger2D.h @@ -0,0 +1,76 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__VisualDebugger2D__h__ +#define __fpa__Image__VisualDebugger2D__h__ + +#include +#ifdef USE_ivq +#include +#include +#endif // USE_ivq + +namespace fpa +{ + namespace Image + { + /** + */ + template< class _TFilter > + class VisualDebugger2D + : public fpa::Image::VisualDebugger< _TFilter > + { + public: + typedef VisualDebugger2D Self; + typedef fpa::Image::VisualDebugger< _TFilter > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::TFilter TFilter; + typedef typename Superclass::TImage TImage; + typedef typename Superclass::TLabel TLabel; + typedef typename Superclass::TLabels TLabels; +#ifdef USE_ivq + typedef typename Superclass::TVTKLabels TVTKLabels; + typedef ivq::VTK::ImageActor TImageActor; +#endif // USE_ivq + + public: + itkNewMacro( Self ); + itkTypeMacro( fpa::Image::VisualDebugger2D, fpa::Image::VisualDebugger ); + + public: + virtual void Render( ) override; + virtual void StartVisualization( ) override; + virtual void EndVisualization( ) override; + + protected: + VisualDebugger2D( ); + virtual ~VisualDebugger2D( ); + + private: + // Purposely not implemented. + VisualDebugger2D( const Self& other ); + Self& operator=( const Self& other ); + + protected: +#ifdef USE_ivq + vtkSmartPointer< TImageActor > m_Actor; + unsigned long m_NumberOfPixels; + unsigned long m_RenderCount; +#endif // USE_ivq + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __fpa__Image__VisualDebugger2D__h__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Image/VisualDebugger2D.hxx b/lib/fpa/Image/VisualDebugger2D.hxx new file mode 100644 index 0000000..91eff97 --- /dev/null +++ b/lib/fpa/Image/VisualDebugger2D.hxx @@ -0,0 +1,74 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__Image__VisualDebugger2D__hxx__ +#define __fpa__Image__VisualDebugger2D__hxx__ + +#include +#include + +// ------------------------------------------------------------------------- +template< class _TFilter > +void fpa::Image::VisualDebugger2D< _TFilter >:: +Render( ) +{ +#ifdef USE_ivq + if( this->m_Renderer == NULL || this->m_Interactor == NULL ) + return; + this->m_Actor->Modified( ); + this->m_RenderCount = ( this->m_RenderCount + 1 ) % this->m_NumberOfPixels; + if( this->m_RenderCount == 0 ) + this->m_Interactor->Render( ); +#endif // USE_ivq +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +void fpa::Image::VisualDebugger2D< _TFilter >:: +StartVisualization( ) +{ +#ifdef USE_ivq + if( this->m_Renderer == NULL || this->m_Interactor == NULL ) + return; + this->m_Actor = vtkSmartPointer< TImageActor >::New( ); + this->m_Actor->SetInputData( this->m_VTKLabels->GetOutput( ) ); + this->m_Actor->Update( ); + this->m_Renderer->AddViewProp( this->m_Actor ); + + this->m_NumberOfPixels = + double( + this->m_VTKLabels->GetInput( )-> + GetRequestedRegion( ).GetNumberOfPixels( ) + ) * 0.005; + this->m_RenderCount = 0; + +#endif // USE_ivq +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +void fpa::Image::VisualDebugger2D< _TFilter >:: +EndVisualization( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +fpa::Image::VisualDebugger2D< _TFilter >:: +VisualDebugger2D( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TFilter > +fpa::Image::VisualDebugger2D< _TFilter >:: +~VisualDebugger2D( ) +{ +} + +#endif // __fpa__Image__VisualDebugger2D__hxx__ + +// eof - $RCSfile$ diff --git a/lib/fpa/Version.cxx.in b/lib/fpa/Version.cxx.in new file mode 100644 index 0000000..1bac65e --- /dev/null +++ b/lib/fpa/Version.cxx.in @@ -0,0 +1,7 @@ + +#include +#include + +std::string FPA_EXPORT version( ) { return( "@prj_VERSION@" ); } + +// eof - $RCSfile$ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..dc97055 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,10 @@ +option(BUILD_TESTS "Build command line tests." OFF) +if(BUILD_TESTS) + include_directories( + ${PROJECT_SOURCE_DIR}/lib + ${PROJECT_BINARY_DIR}/lib + ) + subdirs(image) +endif(BUILD_TESTS) + +## eof - $RCSfile$ diff --git a/tests/image/BaseFunctions.h b/tests/image/BaseFunctions.h new file mode 100644 index 0000000..21200d0 --- /dev/null +++ b/tests/image/BaseFunctions.h @@ -0,0 +1,315 @@ +// ========================================================================= +// @author Leonardo Florez Valencia +// @email florez-l@javeriana.edu.co +// ========================================================================= + +#ifndef __fpa__tests__image__BaseFunctions__h__ +#define __fpa__tests__image__BaseFunctions__h__ + +#include +#include + +#include +#include + +#include +#ifdef USE_ivq +# include +# include +# include +# include +# include +# include +# include +# include +#endif // USE_ivq + +namespace fpa +{ + namespace tests + { + namespace image + { + // ------------------------------------------------------------------- + template< class _TPointer > + void CreateImage( + _TPointer& img, + const typename _TPointer::ObjectType::PixelType& zero, + ... + ) + { + typedef typename _TPointer::ObjectType _TImage; + + va_list vl; + va_start( vl, zero ); + + typename _TImage::SizeType size; + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + size[ d ] = va_arg( vl, int ); + + typename _TImage::SpacingType spac; + for( unsigned int d = 0; d < _TImage::ImageDimension; ++d ) + spac[ d ] = va_arg( vl, double ); + + img = _TImage::New( ); + img->SetRegions( size ); + img->SetSpacing( spac ); + img->Allocate( ); + img->FillBuffer( zero ); + + va_end( vl ); + } + + // ------------------------------------------------------------------- + template< class _TPointer > + std::string Read( _TPointer& img, const std::string& fname ) + { + typedef typename _TPointer::ObjectType _TImage; + typedef itk::ImageFileReader< _TImage > _TReader; + + typename _TReader::Pointer reader = _TReader::New( ); + reader->SetFileName( fname ); + try + { + reader->Update( ); + } + catch( std::exception& err ) + { + return( err.what( ) ); + + } // ytr + img = reader->GetOutput( ); + img->DisconnectPipeline( ); + return( "" ); + } + + // ------------------------------------------------------------------- + template< class _TImage > + std::string Write( const _TImage* img, const std::string& fname ) + { + typedef itk::ImageFileWriter< _TImage > _TWriter; + + typename _TWriter::Pointer writer = _TWriter::New( ); + writer->SetInput( img ); + writer->SetFileName( fname ); + try + { + writer->Update( ); + } + catch( std::exception& err ) + { + return( err.what( ) ); + + } // ytr + return( "" ); + } + + // ------------------------------------------------------------------- + template< class _TFilter > + class Viewer + { + public: + typedef _TFilter TFilter; + typedef typename _TFilter::TInputImage TInputImage; + + public: + Viewer( const TInputImage* image ) + { +#ifdef USE_ivq + this->m_VTKInputImage = TVTKInputImage::New( ); + this->m_VTKInputImage->SetInput( image ); + this->m_VTKInputImage->Update( ); + + this->m_Viewer = vtkSmartPointer< ivq::VTK::ImageViewer >::New( ); + this->m_Viewer->SetInputData( this->m_VTKInputImage->GetOutput( ) ); +#endif // USE_ivq + } + + virtual ~Viewer( ) + { + } + + void ActivateSeedWidget( ) + { +#ifdef USE_ivq + this->m_SeedWidget = + vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor >::New( ); + this->m_SeedWidget->SetActor( this->m_Viewer->GetImageActor( ) ); + this->m_SeedWidget->SetInteractor( + this->m_Viewer->GetRenderWindow( )->GetInteractor( ) + ); +#endif // USE_ivq + } + + void ActivateBrushWidget( ) + { +#ifdef USE_ivq + this->m_BrushWidget = + vtkSmartPointer< ivq::VTK::BrushWidget >::New( ); + this->m_BrushWidget->SetImageActor( this->m_Viewer->GetImageActor( ) ); + this->m_BrushWidget->SetInteractor( + this->m_Viewer->GetRenderWindow( )->GetInteractor( ) + ); +#endif // USE_ivq + } + + void Show( ) + { +#ifdef USE_ivq + this->m_Viewer->Render( ); + this->m_Viewer->ResetCamera( ); + this->m_Viewer->Initialize( ); + this->m_Viewer->Render( ); + if( this->m_SeedWidget.GetPointer( ) != NULL ) + this->m_SeedWidget->EnabledOn( ); + if( this->m_BrushWidget.GetPointer( ) != NULL ) + this->m_BrushWidget->EnabledOn( ); + this->m_Viewer->Start( ); + if( this->m_SeedWidget.GetPointer( ) != NULL ) + this->m_SeedWidget->EnabledOff( ); + if( this->m_BrushWidget.GetPointer( ) != NULL ) + this->m_BrushWidget->EnabledOff( ); +#endif // USE_ivq + } + + void AssociateSeedsTo( TFilter* filter ) + { +#ifdef USE_ivq + if( this->m_SeedWidget.GetPointer( ) != NULL ) + { + const ivq::VTK::SeedWidgetOverImageActor::TSeeds& wdg_seeds = + this->m_SeedWidget->GetSeeds( ); + ivq::VTK::SeedWidgetOverImageActor::TSeeds::const_iterator wsIt; + for( wsIt = wdg_seeds.begin( ); wsIt != wdg_seeds.end( ); ++wsIt ) + { + typename TInputImage::PointType pnt; + for( unsigned int i = 0; i < wsIt->second.size( ); i += 3 ) + { + pnt[ 0 ] = wsIt->second[ i ]; + pnt[ 1 ] = wsIt->second[ i + 1 ]; + + typename TInputImage::IndexType idx; + filter->GetInput( )->TransformPhysicalPointToIndex( pnt, idx ); + filter->AddSeed( idx ); + + } // rof + + } // rof + + } // fi +#endif // USE_ivq + } + + void AssociateLabelsTo( TFilter* filter ) + { +#ifdef USE_ivq + if( this->m_BrushWidget.GetPointer( ) != NULL ) + { + typedef typename TFilter::TLabelImage _TLabelImage; + typedef itk::VTKImageToImageFilter< _TLabelImage > TITKImage; + typename TITKImage::Pointer itk_image = TITKImage::New( ); + itk_image->SetInput( this->m_BrushWidget->GetCanvas( ) ); + itk_image->Update( ); + filter->SetLabels( itk_image->GetOutput( ) ); + + } // fi +#endif // USE_ivq + } + + void ObserveFilter( TFilter* filter ) + { +#ifdef USE_ivq + typedef fpa::Image::VisualDebugger2D< TFilter > _TDeb; + typedef typename TFilter::TEvent _TEvent; + typename _TDeb::Pointer deb = _TDeb::New( ); + deb->SetVisualization( + this->m_Viewer->GetRenderer( ), + this->m_Viewer->GetRenderWindow( )->GetInteractor( ) + ); + this->m_Observer1 = filter->AddObserver( itk::StartEvent( ), deb ); + this->m_Observer2 = filter->AddObserver( itk::EndEvent( ), deb ); + this->m_Observer3 = filter->AddObserver( _TEvent( ), deb ); + filter->VisualDebugOn( ); +#endif // USE_ivq + } + + protected: +#ifdef USE_ivq + typedef itk::ImageToVTKImageFilter< TInputImage > TVTKInputImage; + typename TVTKInputImage::Pointer m_VTKInputImage; + vtkSmartPointer< ivq::VTK::ImageViewer > m_Viewer; + vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor > m_SeedWidget; + vtkSmartPointer< ivq::VTK::BrushWidget > m_BrushWidget; + unsigned long m_Observer1; + unsigned long m_Observer2; + unsigned long m_Observer3; +#endif // USE_ivq + + + /* TODO + #ifdef USE_ivq + // VTK image + typedef itk::ImageToVTKImageFilter< TImage > TVTKImage; + TVTKImage::Pointer vtk_input; + vtkSmartPointer< ivq::VTK::ImageViewer > view; + vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor > widget; + + if( visual_debug ) + { + vtk_input = TVTKImage::New( ); + vtk_input->SetInput( input ); + vtk_input->Update( ); + + // Viewer + view = vtkSmartPointer< ivq::VTK::ImageViewer >::New( ); + view->SetInputData( vtk_input->GetOutput( ) ); + view->SetSlice( 0 ); + + // Widget + widget = vtkSmartPointer< ivq::VTK::SeedWidgetOverImageActor >::New( ); + widget->SetActor( view->GetImageActor( ) ); + widget->SetInteractor( view->GetRenderWindow( )->GetInteractor( ) ); + + // Visualize + view->Render( ); + view->ResetCamera( ); + view->Initialize( ); + view->Render( ); + widget->EnabledOn( ); + view->Start( ); + widget->EnabledOff( ); + + const ivq::VTK::SeedWidgetOverImageActor::TSeeds& wdg_seeds = + widget->GetSeeds( ); + ivq::VTK::SeedWidgetOverImageActor::TSeeds::const_iterator wsIt; + for( wsIt = wdg_seeds.begin( ); wsIt != wdg_seeds.end( ); ++wsIt ) + { + TImage::PointType pnt; + for( unsigned int i = 0; i < wsIt->second.size( ); i += 3 ) + { + pnt[ 0 ] = wsIt->second[ i ]; + pnt[ 1 ] = wsIt->second[ i + 1 ]; + + TImage::IndexType idx; + input->TransformPhysicalPointToIndex( pnt, idx ); + seeds.push_back( idx ); + + } // rof + + } // rof + + } // fi + #endif // USE_ivq + */ + }; + + } // ecapseman + + } // ecapseman + +} // ecapseman + + +#endif // __fpa__tests__image__BaseFunctions__h__ + +// eof - $RCSfile$ diff --git a/tests/image/CMakeLists.txt b/tests/image/CMakeLists.txt new file mode 100644 index 0000000..00facdf --- /dev/null +++ b/tests/image/CMakeLists.txt @@ -0,0 +1,19 @@ +set(_pfx test_fpa_image_) +set( + _examples + RegionGrow_Tautology + Dijkstra_Identity + Dijkstra_Gaussian + RandomWalker + SkeletonFilter + ) +foreach(_e ${_examples}) + add_executable(${_pfx}${_e} ${_e}.cxx) + if(ivq_FOUND) + target_link_libraries(${_pfx}${_e} fpa ivq::ivq) + else(ivq_FOUND) + target_link_libraries(${_pfx}${_e} fpa) + endif(ivq_FOUND) +endforeach(_e) + +## eof - $RCSfile$ diff --git a/tests/image/Dijkstra_Gaussian.cxx b/tests/image/Dijkstra_Gaussian.cxx new file mode 100644 index 0000000..d0461ff --- /dev/null +++ b/tests/image/Dijkstra_Gaussian.cxx @@ -0,0 +1,99 @@ +#include "BaseFunctions.h" +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; +typedef float TScalar; + +typedef itk::Image< TPixel, Dim > TInputImage; +typedef itk::Image< TScalar, Dim > TScalarImage; +typedef fpa::Image::Dijkstra< TInputImage, TScalarImage > TFilter; +typedef fpa::Image::Functors::Dijkstra::Gaussian< TInputImage, TScalar > TWeight; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 8 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_image output_marks alpha beta" + << " stop_at_one_front visual_debug ..." + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string output_image_filename = argv[ 2 ]; + std::string output_marks_filename = argv[ 3 ]; + double alpha = std::atoi( argv[ 4 ] ); + double beta = std::atoi( argv[ 5 ] ); + bool stop_at_one_front = ( argv[ 6 ][ 0 ] == '1' ); + bool visual_debug = ( argv[ 7 ][ 0 ] == '1' ); + + // Create image + TInputImage::Pointer image; + std::string err0 = fpa::tests::image::Read( image, input_image_filename ); + if( err0 != "" ) + { + std::cerr << "Error caught: " << err0 << std::endl; + return( 1 ); + + } // fi + + // Interact with image + fpa::tests::image::Viewer< TFilter > viewer( image ); + if( visual_debug ) + { + viewer.ActivateSeedWidget( ); + viewer.Show( ); + + } // fi + + // Prepare weight + TWeight::Pointer weight = TWeight::New( ); + weight->SetAlpha( alpha ); + weight->SetBeta( beta ); + + // Prepare filter + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( image ); + filter->SetWeightFunction( weight ); + filter->SetStopAtOneFront( stop_at_one_front ); + + // Get all seeds + for( int i = 8; i < argc; i += 2 ) + { + if( i + 1 < argc ) + { + TInputImage::IndexType seed; + seed[ 0 ] = std::atoi( argv[ i ] ); + seed[ 1 ] = std::atoi( argv[ i + 1 ] ); + filter->AddSeed( seed ); + + } // fi + + } // rof + viewer.AssociateSeedsTo( filter ); + + // Prepare visual debug and update + if( visual_debug ) + viewer.ObserveFilter( filter ); + filter->Update( ); + + // Save results + std::string err1 = + fpa::tests::image::Write( filter->GetOutput( ), output_image_filename ); + std::string err2 = + fpa::tests::image::Write( filter->GetMarks( ), output_marks_filename ); + if( err1 != "" ) std::cerr << "Error caught: " << err1 << std::endl; + if( err2 != "" ) std::cerr << "Error caught: " << err2 << std::endl; + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/Dijkstra_Identity.cxx b/tests/image/Dijkstra_Identity.cxx new file mode 100644 index 0000000..57f3593 --- /dev/null +++ b/tests/image/Dijkstra_Identity.cxx @@ -0,0 +1,87 @@ +#include "BaseFunctions.h" +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; +typedef float TScalar; + +typedef itk::Image< TPixel, Dim > TInputImage; +typedef itk::Image< TScalar, Dim > TScalarImage; +typedef fpa::Image::Dijkstra< TInputImage, TScalarImage > TFilter; +typedef fpa::Image::Functors::Dijkstra::Identity< TInputImage, TScalar > TWeight; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 6 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " output_image output_marks width height visual_debug ..." + << std::endl; + return( 1 ); + + } // fi + std::string output_image_filename = argv[ 1 ]; + std::string output_marks_filename = argv[ 2 ]; + int width = std::atoi( argv[ 3 ] ); + int height = std::atoi( argv[ 4 ] ); + bool visual_debug = ( argv[ 5 ][ 0 ] == '1' ); + + // Create image + TInputImage::Pointer image; + fpa::tests::image::CreateImage( image, 1, width, height, 1.0, 1.0 ); + + // Interact with image + fpa::tests::image::Viewer< TFilter > viewer( image ); + if( visual_debug ) + { + viewer.ActivateSeedWidget( ); + viewer.Show( ); + + } // fi + + // Prepare weight + TWeight::Pointer weight = TWeight::New( ); + + // Prepare filter + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( image ); + filter->SetWeightFunction( weight ); + + // Get all seeds + for( int i = 6; i < argc; i += 2 ) + { + if( i + 1 < argc ) + { + TInputImage::IndexType seed; + seed[ 0 ] = std::atoi( argv[ i ] ); + seed[ 1 ] = std::atoi( argv[ i + 1 ] ); + filter->AddSeed( seed ); + + } // fi + + } // rof + viewer.AssociateSeedsTo( filter ); + + // Prepare visual debug and update + if( visual_debug ) + viewer.ObserveFilter( filter ); + filter->Update( ); + + // Save results + std::string err1 = + fpa::tests::image::Write( filter->GetOutput( ), output_image_filename ); + std::string err2 = + fpa::tests::image::Write( filter->GetMarks( ), output_marks_filename ); + if( err1 != "" ) std::cerr << err1 << std::endl; + if( err2 != "" ) std::cerr << err2 << std::endl; + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/RandomWalker.cxx b/tests/image/RandomWalker.cxx new file mode 100644 index 0000000..59c9105 --- /dev/null +++ b/tests/image/RandomWalker.cxx @@ -0,0 +1,113 @@ +#include "BaseFunctions.h" +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef short TPixel; +typedef unsigned char TLabel; +typedef float TScalar; + +typedef itk::Image< TPixel, Dim > TInputImage; +typedef itk::Image< TLabel, Dim > TLabelImage; +typedef fpa::Image::RandomWalker< TInputImage, TLabelImage, TScalar > TFilter; +typedef fpa::Image::Functors::Dijkstra::Gaussian< TInputImage, TScalar > TWeight; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 7 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image [labels_image] output_image output_costs" + << " alpha beta visual_debug" + << std::endl; + return( 1 ); + + } // fi + int idx = ( argc == 7 )? 2: 3; + std::string input_image_filename = argv[ 1 ]; + std::string labels_image_filename = ( argc == 8 )? argv[ 2 ]: ""; + std::string output_image_filename = argv[ idx ]; + std::string output_costs_filename = argv[ idx + 1 ]; + double alpha = std::atof( argv[ idx + 2 ] ); + double beta = std::atof( argv[ idx + 3 ] ); + bool visual_debug = ( argv[ idx + 4 ][ 0 ] == '1' ); + + // Read image + TInputImage::Pointer image; + std::string err0 = fpa::tests::image::Read( image, input_image_filename ); + if( err0 != "" ) + { + std::cerr << "Error caught: " << err0 << std::endl; + return( 1 ); + + } // fi + + // Read label + TLabelImage::Pointer labels; + if( labels_image_filename != "" ) + { + std::string err1 = fpa::tests::image::Read( labels, labels_image_filename ); + if( err1 != "" ) + { + std::cerr << "Error caught: " << err1 << std::endl; + return( 1 ); + + } // fi + + } // fi + + // Interact with image + fpa::tests::image::Viewer< TFilter > viewer( image ); + if( visual_debug ) + { + if( labels.IsNull( ) ) + viewer.ActivateBrushWidget( ); + viewer.Show( ); + + } // fi + + // Prepare weight + TWeight::Pointer weight = TWeight::New( ); + weight->SetAlpha( alpha ); + weight->SetBeta( beta ); + + // Prepare filter + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( image ); + filter->SetWeightFunction( weight ); + if( labels.IsNull( ) ) + viewer.AssociateLabelsTo( filter ); + else + filter->SetLabels( labels ); + + // Prepare visual debug and update + if( visual_debug ) + viewer.ObserveFilter( filter ); + try + { + filter->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Save results + std::string err1 = + fpa::tests::image::Write( filter->GetMarks( ), output_image_filename ); + std::string err2 = + fpa::tests::image::Write( filter->GetOutput( ), output_costs_filename ); + if( err1 != "" ) std::cerr << "Error caught: " << err1 << std::endl; + if( err2 != "" ) std::cerr << "Error caught: " << err2 << std::endl; + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/RegionGrow_Tautology.cxx b/tests/image/RegionGrow_Tautology.cxx new file mode 100644 index 0000000..7cdffa5 --- /dev/null +++ b/tests/image/RegionGrow_Tautology.cxx @@ -0,0 +1,87 @@ +#include "BaseFunctions.h" +#include +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 2; +typedef unsigned char TPixel; + +typedef itk::Image< TPixel, Dim > TImage; +typedef fpa::Image::RegionGrow< TImage, TImage > TFilter; +typedef fpa::Base::Functors::RegionGrow::Tautology< TPixel > TPredicate; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 6 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " output_image output_marks width height visual_debug ..." + << std::endl; + return( 1 ); + + } // fi + std::string output_image_filename = argv[ 1 ]; + std::string output_marks_filename = argv[ 2 ]; + int width = std::atoi( argv[ 3 ] ); + int height = std::atoi( argv[ 4 ] ); + bool visual_debug = ( argv[ 5 ][ 0 ] == '1' ); + + // Create image + TImage::Pointer image; + fpa::tests::image::CreateImage( image, 0, width, height, 1.0, 1.0 ); + + // Interact with image + fpa::tests::image::Viewer< TFilter > viewer( image ); + if( visual_debug ) + { + viewer.ActivateSeedWidget( ); + viewer.Show( ); + + } // fi + + // Prepare predicate + TPredicate::Pointer predicate = TPredicate::New( ); + + // Prepare filter + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( image ); + filter->SetPredicate( predicate ); + filter->SetInsideValue( 255 ); + filter->SetOutsideValue( 0 ); + + // Get all seeds + for( int i = 6; i < argc; i += 2 ) + { + if( i + 1 < argc ) + { + TImage::IndexType seed; + seed[ 0 ] = std::atoi( argv[ i ] ); + seed[ 1 ] = std::atoi( argv[ i + 1 ] ); + filter->AddSeed( seed ); + + } // fi + + } // rof + viewer.AssociateSeedsTo( filter ); + + // Prepare visual debug and update + if( visual_debug ) + viewer.ObserveFilter( filter ); + filter->Update( ); + + // Save results + std::string err1 = + fpa::tests::image::Write( filter->GetOutput( ), output_image_filename ); + std::string err2 = + fpa::tests::image::Write( filter->GetMarks( ), output_marks_filename ); + if( err1 != "" ) std::cerr << err1 << std::endl; + if( err2 != "" ) std::cerr << err2 << std::endl; + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/tests/image/SkeletonFilter.cxx b/tests/image/SkeletonFilter.cxx new file mode 100644 index 0000000..ec0aa74 --- /dev/null +++ b/tests/image/SkeletonFilter.cxx @@ -0,0 +1,74 @@ +#include "BaseFunctions.h" +#include +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 3; +typedef short TPixel; + +typedef itk::Image< TPixel, Dim > TInputImage; +typedef fpa::Image::SkeletonFilter< TInputImage > TFilter; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Get arguments + if( argc < 3 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_image output_skeleton ..." + << std::endl; + return( 1 ); + + } // fi + std::string input_image_filename = argv[ 1 ]; + std::string output_skeleton_filename = argv[ 2 ]; + + // Read image + TInputImage::Pointer image; + std::string err1 = fpa::tests::image::Read( image, input_image_filename ); + if( err1 != "" ) + { + std::cerr << "Error caught: " << err1 << std::endl; + return( 1 ); + + } // fi + + // Prepare filter + TFilter::Pointer filter = TFilter::New( ); + filter->SetInput( image ); + + // Configure seed + if( argc == 6 ) + { + TInputImage::PointType pnt; + pnt[ 0 ] = std::atof( argv[ 3 ] ); + pnt[ 1 ] = std::atof( argv[ 4 ] ); + pnt[ 2 ] = std::atof( argv[ 5 ] ); + + TInputImage::IndexType seed; + image->TransformPhysicalPointToIndex( pnt, seed ); + + filter->SeedFromMaximumDistanceOff( ); + filter->SetSeed( seed ); + } + else + filter->SeedFromMaximumDistanceOn( ); + + // Update + filter->Update( ); + + // Save results + /* TODO + std::string err1 = + fpa::tests::image::Write( filter->GetOutput( ), output_image_filename ); + std::string err2 = + fpa::tests::image::Write( filter->GetMarks( ), output_marks_filename ); + if( err1 != "" ) std::cerr << err1 << std::endl; + if( err2 != "" ) std::cerr << err2 << std::endl; + */ + return( 0 ); +} + +// eof - $RCSfile$ -- 2.45.0