/Modules/Video/BridgeOpenCV/test/itkOpenCVImageBridgeTest.cxx

https://github.com/krismz/ITK · C++ · 369 lines · 244 code · 47 blank · 78 comment · 47 complexity · a7e0062949840f25288a436bd4f93d37 MD5 · raw file

  1. #include <iostream>
  2. #include "itkOpenCVImageBridge.h"
  3. #include "itkRGBPixel.h"
  4. #include "itkImageFileReader.h"
  5. #include "itkDifferenceImageFilter.h"
  6. #include "itkImageRegionConstIteratorWithIndex.h"
  7. //-----------------------------------------------------------------------------
  8. // Compare RGBPixel Images
  9. //
  10. template<class TPixelValue, unsigned int VDimension>
  11. TPixelValue
  12. RGBImageTotalAbsDifference(
  13. const itk::Image<itk::RGBPixel<TPixelValue>, VDimension>* valid,
  14. const itk::Image<itk::RGBPixel<TPixelValue>, VDimension>* test)
  15. {
  16. typedef itk::RGBPixel<TPixelValue> PixelType;
  17. typedef itk::Image<PixelType, VDimension> RGBImageType;
  18. typedef itk::ImageRegionConstIteratorWithIndex<RGBImageType> IterType;
  19. IterType validIt(valid, valid->GetLargestPossibleRegion());
  20. IterType testIt(test, test->GetLargestPossibleRegion());
  21. TPixelValue totalDiff = 0;
  22. while(!validIt.IsAtEnd())
  23. {
  24. PixelType validPx = validIt.Get();
  25. PixelType testPx = testIt.Get();
  26. totalDiff += std::abs(validPx[0] - testPx[0]);
  27. totalDiff += std::abs(validPx[1] - testPx[1]);
  28. totalDiff += std::abs(validPx[2] - testPx[2]);
  29. ++validIt;
  30. ++testIt;
  31. }
  32. return totalDiff;
  33. }
  34. //-----------------------------------------------------------------------------
  35. // Convert the data in the IplImage to the templated type
  36. //
  37. template<class TPixelType>
  38. IplImage* ConvertIplImageDataType(IplImage* in)
  39. {
  40. // Figure out the right output type
  41. if (typeid(TPixelType) == typeid(unsigned char))
  42. {
  43. IplImage* out = cvCreateImage(cvSize(in->width, in->height), IPL_DEPTH_8U, in->nChannels);
  44. cvConvertScale(in, out);
  45. return out;
  46. }
  47. else if (typeid(TPixelType) == typeid(char))
  48. {
  49. IplImage* out = cvCreateImage(cvSize(in->width, in->height), IPL_DEPTH_8S, in->nChannels);
  50. cvConvertScale(in, out);
  51. return out;
  52. }
  53. else if (typeid(TPixelType) == typeid(unsigned short))
  54. {
  55. IplImage* out = cvCreateImage(cvSize(in->width, in->height), IPL_DEPTH_16U, in->nChannels);
  56. cvConvertScale(in, out);
  57. return out;
  58. }
  59. else if (typeid(TPixelType) == typeid(short))
  60. {
  61. IplImage* out = cvCreateImage(cvSize(in->width, in->height), IPL_DEPTH_16S, in->nChannels);
  62. cvConvertScale(in, out);
  63. return out;
  64. }
  65. else if (typeid(TPixelType) == typeid(float))
  66. {
  67. IplImage* out = cvCreateImage(cvSize(in->width, in->height), IPL_DEPTH_32F, in->nChannels);
  68. cvConvertScale(in, out);
  69. return out;
  70. }
  71. else if (typeid(TPixelType) == typeid(double))
  72. {
  73. IplImage* out = cvCreateImage(cvSize(in->width, in->height), IPL_DEPTH_64F, in->nChannels);
  74. cvConvertScale(in, out);
  75. return out;
  76. }
  77. else
  78. {
  79. itkGenericExceptionMacro("OpenCV doesn't support the requested type");
  80. }
  81. }
  82. //-----------------------------------------------------------------------------
  83. // Templated test function to do the heavy lifting for scalar case
  84. //
  85. template<class TPixelType, unsigned int VDimension>
  86. int itkOpenCVImageBridgeTestTemplatedScalar(char** argv)
  87. {
  88. // typedefs
  89. const unsigned int Dimension = VDimension;
  90. typedef TPixelType PixelType;
  91. typedef itk::Image< PixelType, Dimension > ImageType;
  92. typedef itk::ImageFileReader<ImageType> ReaderType;
  93. typedef itk::DifferenceImageFilter<ImageType, ImageType> DifferenceFilterType;
  94. //
  95. // Read the image directly
  96. //
  97. typename ReaderType::Pointer reader = ReaderType::New();
  98. reader->SetFileName(argv[1]);
  99. reader->Update();
  100. typename ImageType::Pointer baselineImage = reader->GetOutput();
  101. //
  102. // Test IplImage -> itk::Image
  103. //
  104. IplImage* inIpl;
  105. inIpl = cvLoadImage(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
  106. if (!inIpl)
  107. {
  108. std::cerr << "Could not load input as IplImage" << std::endl;
  109. return EXIT_FAILURE;
  110. }
  111. typename ImageType::Pointer outIplITK =
  112. itk::OpenCVImageBridge::IplImageToITKImage< ImageType >(inIpl);
  113. // Check results of IplImage -> itk::Image
  114. typename DifferenceFilterType::Pointer differ = DifferenceFilterType::New();
  115. differ->SetValidInput(baselineImage);
  116. differ->SetTestInput(outIplITK);
  117. differ->Update();
  118. typename DifferenceFilterType::AccumulateType total = differ->GetTotalDifference();
  119. if (total != 0)
  120. {
  121. std::cerr << "Images didn't match for pixel type " << typeid(PixelType).name()
  122. << " for IplImage -> ITK (scalar)" << std::endl;
  123. return EXIT_FAILURE;
  124. }
  125. //
  126. // Test cv::Mat -> itk::Image
  127. //
  128. cv::Mat inMat;
  129. inMat = cv::imread(argv[1]);
  130. typename ImageType::Pointer outMatITK =
  131. itk::OpenCVImageBridge::CVMatToITKImage< ImageType >(inMat);
  132. // Check results of cv::Mat -> itk::Image
  133. differ->SetTestInput(outMatITK);
  134. differ->Update();
  135. total = differ->GetTotalDifference();
  136. if (total != 0)
  137. {
  138. std::cerr << "Images didn't match for pixel type " << typeid(PixelType).name()
  139. << " for cv::Mat -> ITK (scalar)" << std::endl;
  140. return EXIT_FAILURE;
  141. }
  142. //
  143. // Test itk::Image -> IplImage
  144. //
  145. IplImage* outIpl = itk::OpenCVImageBridge::ITKImageToIplImage< ImageType >(baselineImage);
  146. // check results of itk::Image -> IplImage
  147. IplImage* dataConvertedInIpl = ConvertIplImageDataType<PixelType>(inIpl);
  148. double itkIplDiff = cvNorm(outIpl, dataConvertedInIpl);
  149. if (itkIplDiff != 0.0)
  150. {
  151. std::cerr << "Images didn't match for pixel type " << typeid(PixelType).name()
  152. << " for ITK -> IplImage (scalar)" << std::endl;
  153. return EXIT_FAILURE;
  154. }
  155. // Test number of channels after force3Channels (if type is supported for color images)
  156. if (typeid(PixelType) == typeid(unsigned short) ||
  157. typeid(PixelType) == typeid(unsigned char) ||
  158. typeid(PixelType) == typeid(float))
  159. {
  160. cvReleaseImage(&outIpl);
  161. outIpl = itk::OpenCVImageBridge::ITKImageToIplImage< ImageType >(baselineImage, true);
  162. if (outIpl->nChannels != 3)
  163. {
  164. std::cerr << "force3Channels failed" << std::endl;
  165. return EXIT_FAILURE;
  166. }
  167. }
  168. //
  169. // Test itk::Image -> cv::Mat
  170. //
  171. cv::Mat outMat = itk::OpenCVImageBridge::ITKImageToCVMat< ImageType >(baselineImage);
  172. // check results of itk::Image -> IplImage
  173. IplImage outMatAsIpl = outMat;
  174. double itkMatDiff = cvNorm(&outMatAsIpl, dataConvertedInIpl);
  175. if (itkMatDiff != 0.0)
  176. {
  177. std::cerr << "Images didn't match for pixel type " << typeid(PixelType).name()
  178. << " for ITK -> cv::Mat (scalar)" << std::endl;
  179. return EXIT_FAILURE;
  180. }
  181. //
  182. // Clean up and return successfully
  183. //
  184. cvReleaseImage(&dataConvertedInIpl);
  185. cvReleaseImage(&inIpl);
  186. cvReleaseImage(&outIpl);
  187. return EXIT_SUCCESS;
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Templated test function to do the heavy lifting for RGB case
  191. //
  192. template<class TValueType, unsigned int VDimension>
  193. int itkOpenCVImageBridgeTestTemplatedRGB(char** argv)
  194. {
  195. // typedefs
  196. const unsigned int Dimension = VDimension;
  197. typedef TValueType ValueType;
  198. typedef itk::RGBPixel< ValueType > PixelType;
  199. typedef itk::Image< PixelType, Dimension > ImageType;
  200. typedef itk::ImageFileReader<ImageType> ReaderType;
  201. typedef itk::DifferenceImageFilter<ImageType, ImageType> DifferenceFilterType;
  202. //
  203. // Read the image directly
  204. //
  205. typename ReaderType::Pointer reader = ReaderType::New();
  206. reader->SetFileName(argv[3]);
  207. reader->Update();
  208. typename ImageType::Pointer baselineImage = reader->GetOutput();
  209. //
  210. // Test IplImage -> itk::Image
  211. //
  212. IplImage* inIpl;
  213. inIpl = cvLoadImage(argv[2], CV_LOAD_IMAGE_COLOR);
  214. if (!inIpl)
  215. {
  216. std::cerr << "Could not load input as IplImage" << std::endl;
  217. return EXIT_FAILURE;
  218. }
  219. typename ImageType::Pointer outIplITK =
  220. itk::OpenCVImageBridge::IplImageToITKImage< ImageType >(inIpl);
  221. // Check results of IplImage -> itk::Image
  222. if (RGBImageTotalAbsDifference<typename PixelType::ComponentType, Dimension>(
  223. baselineImage, outIplITK) != 0)
  224. {
  225. std::cerr << "Images didn't match for pixel type " << typeid(PixelType).name()
  226. << " for IplImage -> ITK (RGB)" << std::endl;
  227. return EXIT_FAILURE;
  228. }
  229. //
  230. // Test cv::Mat -> itk::Image
  231. //
  232. cv::Mat inMat;
  233. inMat = cv::imread(argv[2]);
  234. typename ImageType::Pointer outMatITK =
  235. itk::OpenCVImageBridge::CVMatToITKImage< ImageType >(inMat);
  236. // Check results of cv::Mat -> itk::Image
  237. if (RGBImageTotalAbsDifference<typename PixelType::ComponentType, Dimension>(
  238. baselineImage, outIplITK) != 0)
  239. {
  240. std::cerr << "Images didn't match for pixel type " << typeid(PixelType).name()
  241. << " for cv::Mat -> ITK (RGB)" << std::endl;
  242. return EXIT_FAILURE;
  243. }
  244. //
  245. // Test itk::Image -> IplImage
  246. //
  247. IplImage* outIpl = itk::OpenCVImageBridge::ITKImageToIplImage< ImageType >(baselineImage);
  248. // check results of itk::Image -> IplImage
  249. IplImage* dataConvertedInIpl = ConvertIplImageDataType<ValueType>(inIpl);
  250. double itkIplDiff = cvNorm(outIpl, dataConvertedInIpl);
  251. if (itkIplDiff != 0.0)
  252. {
  253. std::cerr << "Images didn't match for pixel type " << typeid(ValueType).name()
  254. << " for ITK -> IplImage (RGB)" << std::endl;
  255. return EXIT_FAILURE;
  256. }
  257. //
  258. // Test itk::Image -> cv::Mat
  259. //
  260. cv::Mat outMat = itk::OpenCVImageBridge::ITKImageToCVMat< ImageType >(baselineImage);
  261. // check results of itk::Image -> IplImage
  262. IplImage outMatAsIpl = outMat;
  263. double itkMatDiff = cvNorm(&outMatAsIpl, dataConvertedInIpl);
  264. if (itkMatDiff != 0.0)
  265. {
  266. std::cerr << "Images didn't match for pixel type " << typeid(PixelType).name()
  267. << " for ITK -> cv::Mat (RGB)" << std::endl;
  268. return EXIT_FAILURE;
  269. }
  270. //
  271. // Clean up and return successfully
  272. //
  273. cvReleaseImage(&dataConvertedInIpl);
  274. cvReleaseImage(&inIpl);
  275. cvReleaseImage(&outIpl);
  276. return EXIT_SUCCESS;
  277. }
  278. //-----------------------------------------------------------------------------
  279. // Main test
  280. //
  281. int itkOpenCVImageBridgeTest ( int argc, char *argv[] )
  282. {
  283. //
  284. // Check arguments
  285. //
  286. if (argc < 4)
  287. {
  288. std::cerr << "Usage: " << argv[0] << "scalar_image rgb_jpg_image rgb_mha_image" << std::endl;
  289. return EXIT_FAILURE;
  290. }
  291. #define RUN_SCALAR_TEST(_PixelType)\
  292. if (itkOpenCVImageBridgeTestTemplatedScalar< _PixelType, 2 >(argv) == EXIT_FAILURE)\
  293. {\
  294. return EXIT_FAILURE;\
  295. }
  296. #define RUN_RGB_TEST(_ValueType)\
  297. if (itkOpenCVImageBridgeTestTemplatedRGB< _ValueType, 2 >(argv) == EXIT_FAILURE)\
  298. {\
  299. return EXIT_FAILURE;\
  300. }
  301. //
  302. // Test for scalar types
  303. //
  304. // Note: We don't test signed char because ITK seems to have trouble reading
  305. // images with char pixels.
  306. //
  307. RUN_SCALAR_TEST(unsigned char);
  308. RUN_SCALAR_TEST(short);
  309. RUN_SCALAR_TEST(unsigned short);
  310. RUN_SCALAR_TEST(float);
  311. RUN_SCALAR_TEST(double);
  312. //
  313. // Test for RGB types
  314. //
  315. // Note: OpenCV only supports unsigned char, unsigned short, and float for
  316. // color conversion
  317. //
  318. RUN_RGB_TEST(unsigned char);
  319. RUN_RGB_TEST(unsigned short);
  320. RUN_RGB_TEST(float);
  321. return EXIT_SUCCESS;
  322. }