PageRenderTime 1879ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Modules/Segmentation/Voronoi/test/itkVoronoiSegmentationRGBImageFilterTest.cxx

https://github.com/paniwani/ITK
C++ | 449 lines | 326 code | 54 blank | 69 comment | 65 complexity | 584d967ec0c7073692353ff33801f491 MD5 | raw file
  1. /*=========================================================================
  2. *
  3. * Copyright Insight Software Consortium
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0.txt
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. *=========================================================================*/
  18. #include "itkImage.h"
  19. #include "itkRGBPixel.h"
  20. #include "itkImageFileReader.h"
  21. #include "itkVoronoiSegmentationRGBImageFilter.h"
  22. #include "itkImageRegionIterator.h"
  23. #include "vnl/vnl_sample.h"
  24. #include <iostream>
  25. #include <string.h>
  26. // typedefs for all functions
  27. typedef itk::RGBPixel<unsigned char> PixelType;
  28. typedef itk::Image<PixelType,2> ImageType;
  29. typedef itk::Image<unsigned char,2> SegmentationType;
  30. typedef itk::ImageFileReader<ImageType> ReaderType;
  31. typedef itk::VoronoiSegmentationRGBImageFilter<ImageType, SegmentationType> FilterType;
  32. typedef FilterType::BinaryObjectImage BinaryObjectImage;
  33. namespace VoronoiSegRGBTest
  34. {
  35. //
  36. // global constants
  37. //
  38. const unsigned int width = 256;
  39. const unsigned int height = 256;
  40. const unsigned char bgMean = 64;
  41. const unsigned char bgStd = 10;
  42. const unsigned char fgMean = 128;
  43. const unsigned char fgStd = 5;
  44. const unsigned int objAStartX = 30;
  45. const unsigned int objAEndX = 94;
  46. const unsigned int objAStartY = 30;
  47. const unsigned int objAEndY = 94;
  48. const unsigned int objBStartX = 150;
  49. const unsigned int objBEndX = 214;
  50. const unsigned int objBStartY = 150;
  51. const unsigned int objBEndY = 214;
  52. const double minCorrectRate = .875; // .875 is all classified as background
  53. //
  54. // Function to set up input image
  55. //
  56. ImageType::Pointer SetUpInputImage()
  57. {
  58. // initialize the test input image
  59. ImageType::Pointer inputImage = ImageType::New();
  60. ImageType::SizeType size = {{width,height}};
  61. ImageType::RegionType region;
  62. region.SetSize(size);
  63. inputImage->SetLargestPossibleRegion(region);
  64. inputImage->SetBufferedRegion(region);
  65. inputImage->SetRequestedRegion(region);
  66. inputImage->Allocate();
  67. // add background random field
  68. itk::ImageRegionIterator<ImageType> iter(inputImage, region);
  69. while (!iter.IsAtEnd())
  70. {
  71. PixelType px;
  72. px[0] = (unsigned char)(vnl_sample_uniform(bgMean-bgStd,bgMean+bgStd));
  73. px[1] = (unsigned char)(vnl_sample_uniform(bgMean-bgStd,bgMean+bgStd));
  74. px[2] = (unsigned char)(vnl_sample_uniform(bgMean-bgStd,bgMean+bgStd));
  75. iter.Set(px);
  76. ++iter;
  77. }
  78. // add objects to image
  79. for (unsigned int x = objAStartX; x < objAEndX; x++)
  80. {
  81. for (unsigned int y = objAStartY; y < objAEndY; y++)
  82. {
  83. ImageType::IndexType idx;
  84. idx[0] = x;
  85. idx[1] = y;
  86. PixelType px;
  87. px[0] = (unsigned char)(vnl_sample_uniform(fgMean-fgStd,fgMean+fgStd));
  88. px[1] = (unsigned char)(vnl_sample_uniform(fgMean-fgStd,fgMean+fgStd));
  89. px[2] = (unsigned char)(vnl_sample_uniform(fgMean-fgStd,fgMean+fgStd));
  90. inputImage->SetPixel(idx, px);
  91. }
  92. }
  93. for (unsigned int x = objBStartX; x < objBEndX; x++)
  94. {
  95. for (unsigned int y = objBStartY; y < objBEndY; y++)
  96. {
  97. ImageType::IndexType idx;
  98. idx[0] = x;
  99. idx[1] = y;
  100. PixelType px;
  101. px[0] = (unsigned char)(vnl_sample_uniform(fgMean-fgStd,fgMean+fgStd));
  102. px[1] = (unsigned char)(vnl_sample_uniform(fgMean-fgStd,fgMean+fgStd));
  103. px[2] = (unsigned char)(vnl_sample_uniform(fgMean-fgStd,fgMean+fgStd));
  104. inputImage->SetPixel(idx, px);
  105. }
  106. }
  107. return inputImage;
  108. }
  109. //
  110. // Function to check the results
  111. //
  112. double CheckResults(SegmentationType::Pointer outputImage)
  113. {
  114. // walk the image and count the correctly segmented pixels
  115. unsigned int correctInterior = 0;
  116. unsigned int correctExterior = 0;
  117. unsigned int falseInterior = 0;
  118. unsigned int falseExterior = 0;
  119. for (unsigned int x = 0; x < width; x++)
  120. {
  121. for (unsigned int y = 0; y < height; y++)
  122. {
  123. SegmentationType::IndexType idx;
  124. idx[0] = x;
  125. idx[1] = y;
  126. bool inInterior = false;
  127. // check if in objA
  128. if (x >= objAStartX && x < objAEndX && y >= objAStartY && y < objAEndY)
  129. {
  130. inInterior = true;
  131. }
  132. // check if in objB
  133. else if (x >= objBStartX && x < objBEndX && y >= objBStartY && y < objBEndY)
  134. {
  135. inInterior = true;
  136. }
  137. if (inInterior)
  138. {
  139. if (outputImage->GetPixel(idx) == 1)
  140. {
  141. correctInterior++;
  142. }
  143. else
  144. {
  145. falseExterior++;
  146. }
  147. }
  148. else
  149. {
  150. if (outputImage->GetPixel(idx) == 0)
  151. {
  152. correctExterior++;
  153. }
  154. else
  155. {
  156. falseInterior++;
  157. }
  158. }
  159. }
  160. }
  161. // report the results and fail if too many incorrectly segmented
  162. std::cout << "Correct Interior: " << correctInterior << std::endl;
  163. std::cout << "Correct Exterior: " << correctExterior << std::endl;
  164. std::cout << "False Interior: " << falseInterior << std::endl;
  165. std::cout << "False Exterior: " << falseExterior << std::endl;
  166. double percentCorrect = (double)(correctInterior+correctExterior)/(double)(width*height);
  167. std::cout << "Percent Correct = " << percentCorrect *100 << "%" << std::endl;
  168. return percentCorrect;
  169. }
  170. //
  171. // Test with no prior
  172. //
  173. int TestNoPrior(ImageType::Pointer inputImage)
  174. {
  175. std::cout << "Beginning no-prior test" << std::endl;
  176. // set up the filter
  177. FilterType::Pointer filter = FilterType::New();
  178. std::cout << "Setting filter input" << std::endl;
  179. filter->SetInput(inputImage);
  180. // explicitly set mean and std
  181. std::cout << "Setting up mean and std for filter" << std::endl;
  182. double mean[6];
  183. mean[0] = fgMean;
  184. mean[1] = fgMean;
  185. mean[2] = fgMean;
  186. mean[3] = 0;
  187. mean[4] = 0;
  188. mean[5] = 50;
  189. filter->SetMean(mean);
  190. double std[6];
  191. std[0] = fgStd;
  192. std[1] = fgStd;
  193. std[2] = fgStd;
  194. std[3] = 255;
  195. std[4] = 10;
  196. std[5] = 10;
  197. filter->SetSTD(std);
  198. filter->SetNumberOfSeeds(400);
  199. filter->SetSteps(5);
  200. filter->SetMaxValueOfRGB(255);
  201. // test GetMaxValueOfRGB
  202. std::cout << "Checking GetMaxValueOfRGB" << std::endl;
  203. if (filter->GetMaxValueOfRGB() != 255)
  204. {
  205. std::cout << "[FAILED] Didn't set max RGB correctly" << std::endl;
  206. return EXIT_FAILURE;
  207. }
  208. // run the filter
  209. std::cout << "Running the filter" << std::endl;
  210. filter->Update();
  211. // check the results
  212. std::cout << "Checking the filter results" << std::endl;
  213. double percentCorrect = CheckResults(filter->GetOutput());
  214. if (percentCorrect <= minCorrectRate)
  215. {
  216. std::cout << "[FAILED] Did not segment over "<< minCorrectRate*100 <<"% correctly" << std::endl;
  217. return EXIT_FAILURE;
  218. }
  219. // return successfully
  220. return EXIT_SUCCESS;
  221. }
  222. //
  223. // Test with a prior
  224. //
  225. int TestWithPrior(ImageType::Pointer inputImage)
  226. {
  227. // set up the filter
  228. std::cout << "Setting up the filter and image" << std::endl;
  229. FilterType::Pointer filter = FilterType::New();
  230. filter->SetInput(inputImage);
  231. // set up the prior
  232. std::cout << "Setting up the prior image" << std::endl;
  233. BinaryObjectImage::Pointer prior = BinaryObjectImage::New();
  234. BinaryObjectImage::SizeType size = {{width,height}};
  235. BinaryObjectImage::RegionType region;
  236. region.SetSize(size);
  237. prior->SetLargestPossibleRegion(region);
  238. prior->SetBufferedRegion(region);
  239. prior->SetRequestedRegion(region);
  240. prior->Allocate();
  241. // create prior as 100% segmentation
  242. for (unsigned int x = 0; x < width; x++)
  243. {
  244. for (unsigned int y = 0; y < height; y++)
  245. {
  246. SegmentationType::IndexType idx;
  247. idx[0] = x;
  248. idx[1] = y;
  249. bool inInterior = false;
  250. // check if in objA
  251. if (x >= objAStartX && x < objAEndX && y >= objAStartY && y < objAEndY)
  252. {
  253. inInterior = true;
  254. }
  255. // check if in objB
  256. else if (x >= objBStartX && x < objBEndX && y >= objBStartY && y < objBEndY)
  257. {
  258. inInterior = true;
  259. }
  260. if (inInterior)
  261. {
  262. prior->SetPixel(idx,1);
  263. }
  264. else
  265. {
  266. prior->SetPixel(idx,0);
  267. }
  268. }
  269. }
  270. // add prior to filter
  271. filter->TakeAPrior(prior);
  272. // run the filter
  273. std::cout << "Running the filter" << std::endl;
  274. filter->Update();
  275. // check the results
  276. std::cout << "Checking the results of the filter" << std::endl;
  277. double percentCorrect = CheckResults(filter->GetOutput());
  278. if (percentCorrect <= minCorrectRate)
  279. {
  280. std::cout << "[FAILED] Did not segment over "<< minCorrectRate*100 <<"% correctly" << std::endl;
  281. return EXIT_FAILURE;
  282. }
  283. // return successfully
  284. return EXIT_SUCCESS;
  285. }
  286. } // end namespace VoronoiSegRGBTest
  287. //
  288. // Main test function
  289. //
  290. int itkVoronoiSegmentationRGBImageFilterTest(int, char* [] )
  291. {
  292. // set up the input image
  293. ImageType::Pointer inputImage = VoronoiSegRGBTest::SetUpInputImage();
  294. // test without prior
  295. std::cout << "[Running test without prior]" << std::endl;
  296. int noPriorTestResult = VoronoiSegRGBTest::TestNoPrior(inputImage);
  297. if (noPriorTestResult == EXIT_FAILURE)
  298. {
  299. std::cout << "Failed on test without prior" << std::endl;
  300. return EXIT_FAILURE;
  301. }
  302. std::cout << std::endl;
  303. // test with prior
  304. std::cout << "[Running test with prior]" << std::endl;
  305. int priorTestResult = VoronoiSegRGBTest::TestWithPrior(inputImage);
  306. if (priorTestResult == EXIT_FAILURE)
  307. {
  308. std::cout << "Failed on test with prior" << std::endl;
  309. return EXIT_FAILURE;
  310. }
  311. // test set/get TestMean
  312. FilterType::Pointer filter = FilterType::New();
  313. filter->SetTestMean(VoronoiSegRGBTest::fgMean,VoronoiSegRGBTest::fgMean,VoronoiSegRGBTest::fgMean);
  314. unsigned int testMean[3];
  315. filter->GetTestMean(testMean);
  316. if (testMean[0] != VoronoiSegRGBTest::fgMean ||
  317. testMean[1] != VoronoiSegRGBTest::fgMean ||
  318. testMean[2] != VoronoiSegRGBTest::fgMean)
  319. {
  320. std::cout << "[FAILED] Didn't set/get TestMean correctly" << std::endl;
  321. return EXIT_FAILURE;
  322. }
  323. // test set/get TestSTD
  324. filter->SetTestSTD(VoronoiSegRGBTest::fgStd,VoronoiSegRGBTest::fgStd,VoronoiSegRGBTest::fgStd);
  325. unsigned int testStd[3];
  326. filter->GetTestSTD(testStd);
  327. if (testStd[0] != VoronoiSegRGBTest::fgStd ||
  328. testStd[1] != VoronoiSegRGBTest::fgStd ||
  329. testStd[2] != VoronoiSegRGBTest::fgStd)
  330. {
  331. std::cout << "[FAILED] Didn't set/get TestSTD correctly" << std::endl;
  332. return EXIT_FAILURE;
  333. }
  334. // test set/get MeanPercentError
  335. double meanPercentErrorIn[6] = {0.1,0.1,0.1,0.1,0.1,0.1};
  336. filter->SetMeanPercentError(meanPercentErrorIn);
  337. double meanPercentErrorOut[6];
  338. filter->GetMeanPercentError(meanPercentErrorOut);
  339. if (meanPercentErrorOut[0] != 0.1 ||
  340. meanPercentErrorOut[1] != 0.1 ||
  341. meanPercentErrorOut[2] != 0.1 ||
  342. meanPercentErrorOut[3] != 0.1 ||
  343. meanPercentErrorOut[4] != 0.1 ||
  344. meanPercentErrorOut[5] != 0.1)
  345. {
  346. std::cout << "[FAILED] Didn't set/get MeanPercentError correctly" << std::endl;
  347. return EXIT_FAILURE;
  348. }
  349. // test set/get STDPercentError
  350. double stdPercentErrorIn[6] = {0.1,0.1,0.1,0.1,0.1,0.1};
  351. filter->SetSTDPercentError(stdPercentErrorIn);
  352. double stdPercentErrorOut[6];
  353. filter->GetSTDPercentError(stdPercentErrorOut);
  354. if (stdPercentErrorOut[0] != 0.1 ||
  355. stdPercentErrorOut[1] != 0.1 ||
  356. stdPercentErrorOut[2] != 0.1 ||
  357. stdPercentErrorOut[3] != 0.1 ||
  358. stdPercentErrorOut[4] != 0.1 ||
  359. stdPercentErrorOut[5] != 0.1)
  360. {
  361. std::cout << "[FAILED] Didn't set/get STDPercentError correctly" << std::endl;
  362. return EXIT_FAILURE;
  363. }
  364. // test get mean/std tolerance
  365. double meanTolerance[6];
  366. filter->GetMeanTolerance(meanTolerance);
  367. std::cout << "Mean Tolerance = ("
  368. << meanTolerance[0] << ","
  369. << meanTolerance[1] << ","
  370. << meanTolerance[2] << ","
  371. << meanTolerance[3] << ","
  372. << meanTolerance[4] << ","
  373. << meanTolerance[5] << ")"
  374. << std::endl;
  375. double stdTolerance[6];
  376. filter->GetSTDTolerance(stdTolerance);
  377. std::cout << "STD Tolerance = ("
  378. << stdTolerance[0] << ","
  379. << stdTolerance[1] << ","
  380. << stdTolerance[2] << ","
  381. << stdTolerance[3] << ","
  382. << stdTolerance[4] << ","
  383. << stdTolerance[5] << ")"
  384. << std::endl;
  385. // test type information
  386. if (strcmp(filter->GetNameOfClass(),"VoronoiSegmentationRGBImageFilter") != 0)
  387. {
  388. std::cout << "[FAILED] Didn't report class name correctly" << std::endl;
  389. return EXIT_FAILURE;
  390. }
  391. // test printing
  392. std::cout << filter << std::endl;
  393. // return successfully
  394. return EXIT_SUCCESS;
  395. }