PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Examples/Patented/EstimateAffineTransformationExample.cxx

https://github.com/paniwani/OTB
C++ | 377 lines | 130 code | 52 blank | 195 comment | 4 complexity | 50bec243c7218b8e595cb028e54730f8 MD5 | raw file
  1. /*=========================================================================
  2. Program: ORFEO Toolbox
  3. Language: C++
  4. Date: $Date$
  5. Version: $Revision$
  6. Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  7. See OTBCopyright.txt for details.
  8. This software is distributed WITHOUT ANY WARRANTY; without even
  9. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  10. PURPOSE. See the above copyright notices for more information.
  11. =========================================================================*/
  12. // Software Guide : BeginCommandLineArgs
  13. // INPUTS: {QB_Suburb.png}, {QB_SuburbR10X13Y17.png}
  14. // OUTPUTS: {AffineTransformationOutput.png}, {AffineTransformationTxtOutput.txt}
  15. // 2 3 0 0 0.3 1
  16. // Software Guide : EndCommandLineArgs
  17. // Software Guide : BeginLatex
  18. //
  19. // This example demonstrates the use of the
  20. // \doxygen{otb}{KeyPointSetsMatchingFilter} for transformation
  21. // estimation between 2 images. The idea here is to match SIFTs extracted from both the
  22. // fixed and the moving images. The use of SIFTs is demonstrated in
  23. // section \ref{sec:SIFTDetector}. The
  24. // \doxygen{otb}{LeastSquareAffineTransformEstimator} will be used
  25. // to generate a transformation field by using
  26. // mean square optimisation to estimate
  27. // an affine transfrom from the point set.
  28. //
  29. // The first step toward the use of these filters is to include the
  30. // appropriate header files.
  31. //
  32. // Software Guide : EndLatex
  33. // Software Guide : BeginCodeSnippet
  34. #include "otbKeyPointSetsMatchingFilter.h"
  35. #include "otbImageToSIFTKeyPointSetFilter.h"
  36. // Disabling deprecation warning if on visual
  37. #ifdef _MSC_VER
  38. #pragma warning(push)
  39. #pragma warning(disable:4996)
  40. #endif
  41. #include "itkDeformationFieldSource.h"
  42. // Enabling remaining deprecation warning
  43. #ifdef _MSC_VER
  44. #pragma warning(pop)
  45. #endif
  46. // Software Guide : EndCodeSnippet
  47. #include "otbImage.h"
  48. #include "otbMacro.h"
  49. #include "otbImageFileReader.h"
  50. #include "otbImageFileWriter.h"
  51. #include "itkPointSet.h"
  52. #include "otbLeastSquareAffineTransformEstimator.h"
  53. #include "itkResampleImageFilter.h"
  54. int main(int argc, char* argv[])
  55. {
  56. if (argc != 11)
  57. {
  58. std::cerr << "Usage: " << argv[0];
  59. std::cerr <<
  60. " fixedFileName movingFileName resamplingImageFileName transfofname octaves scales threshold ratio secondOrderThreshold useBackMatching"
  61. << std::endl;
  62. return EXIT_FAILURE;
  63. }
  64. const char * fixedfname = argv[1];
  65. const char * movingfname = argv[2];
  66. const char * outputImageFilename = argv[3];
  67. const char * outputTransformationFilename = argv[4];
  68. const unsigned int octaves = atoi(argv[5]);
  69. const unsigned int scales = atoi(argv[6]);
  70. float threshold = atof(argv[7]);
  71. float ratio = atof(argv[8]);
  72. const double secondOrderThreshold = atof(argv[9]);
  73. const bool useBackMatching = atoi(argv[10]);
  74. const unsigned int Dimension = 2;
  75. // Software Guide : BeginLatex
  76. //
  77. // Then we must decide what pixel type to use for the image. We choose to do
  78. // all the computations in floating point precision and rescale the results
  79. // between 0 and 255 in order to export PNG images.
  80. //
  81. // Software Guide : EndLatex
  82. // Software Guide : BeginCodeSnippet
  83. typedef double RealType;
  84. typedef unsigned char OutputPixelType;
  85. typedef otb::Image<RealType, Dimension> ImageType;
  86. typedef otb::Image<OutputPixelType, Dimension> OutputImageType;
  87. // Software Guide : EndCodeSnippet
  88. // Software Guide : BeginLatex
  89. //
  90. // The SIFTs obtained for the matching will be stored in vector
  91. // form inside a point set. So we need the following types:
  92. //
  93. // Software Guide : EndLatex
  94. // Software Guide : BeginCodeSnippet
  95. typedef itk::VariableLengthVector<RealType> RealVectorType;
  96. typedef itk::PointSet<RealVectorType, Dimension> PointSetType;
  97. // Software Guide : EndCodeSnippet
  98. // Software Guide : BeginLatex
  99. //
  100. // The filter for computing the SIFTs has a type defined as follows:
  101. //
  102. // Software Guide : EndLatex
  103. // Software Guide : BeginCodeSnippet
  104. typedef otb::ImageToSIFTKeyPointSetFilter<ImageType, PointSetType>
  105. ImageToSIFTKeyPointSetFilterType;
  106. // Software Guide : EndCodeSnippet
  107. // Software Guide : BeginLatex
  108. //
  109. // Although many choices for evaluating the distances during the
  110. // matching procedure exist, we choose here to use a simple
  111. // Euclidean distance. We can then define the type for the matching filter.
  112. //
  113. // Software Guide : EndLatex
  114. // Software Guide : BeginCodeSnippet
  115. typedef itk::Statistics::EuclideanDistance<RealVectorType> DistanceType;
  116. typedef otb::KeyPointSetsMatchingFilter<PointSetType, DistanceType>
  117. EuclideanDistanceMatchingFilterType;
  118. // Software Guide : EndCodeSnippet
  119. // Software Guide : BeginLatex
  120. //
  121. // The following types are needed for dealing with the matched points.
  122. //
  123. // Software Guide : EndLatex
  124. // Software Guide : BeginCodeSnippet
  125. typedef PointSetType::PointType PointType;
  126. typedef std::pair<PointType, PointType> MatchType;
  127. typedef std::vector<MatchType> MatchVectorType;
  128. typedef EuclideanDistanceMatchingFilterType::LandmarkListType
  129. LandmarkListType;
  130. typedef PointSetType::PointsContainer PointsContainerType;
  131. typedef PointsContainerType::Iterator PointsIteratorType;
  132. typedef PointSetType::PointDataContainer PointDataContainerType;
  133. typedef PointDataContainerType::Iterator PointDataIteratorType;
  134. // Software Guide : EndCodeSnippet
  135. // Software Guide : BeginLatex
  136. //
  137. // We define the type for the image reader.
  138. //
  139. // Software Guide : EndLatex
  140. // Software Guide : BeginCodeSnippet
  141. typedef otb::ImageFileReader<ImageType> ReaderType;
  142. // Software Guide : EndCodeSnippet
  143. // Software Guide : BeginLatex
  144. //
  145. // Two readers are instantiated : one for the fixed image, and one
  146. // for the moving image.
  147. //
  148. // Software Guide : EndLatex
  149. // Software Guide : BeginCodeSnippet
  150. ReaderType::Pointer fixedReader = ReaderType::New();
  151. ReaderType::Pointer movingReader = ReaderType::New();
  152. fixedReader->SetFileName(fixedfname);
  153. movingReader->SetFileName(movingfname);
  154. fixedReader->UpdateOutputInformation();
  155. movingReader->UpdateOutputInformation();
  156. // Software Guide : EndCodeSnippet
  157. // Software Guide : BeginLatex
  158. //
  159. // We will now instantiate the 2 SIFT filters and the filter used
  160. // for the matching of the points.
  161. //
  162. // Software Guide : EndLatex
  163. // Software Guide : BeginCodeSnippet
  164. ImageToSIFTKeyPointSetFilterType::Pointer filter1 =
  165. ImageToSIFTKeyPointSetFilterType::New();
  166. ImageToSIFTKeyPointSetFilterType::Pointer filter2 =
  167. ImageToSIFTKeyPointSetFilterType::New();
  168. EuclideanDistanceMatchingFilterType::Pointer euclideanMatcher =
  169. EuclideanDistanceMatchingFilterType::New();
  170. // Software Guide : EndCodeSnippet
  171. // Software Guide : BeginLatex
  172. //
  173. // We plug the pipeline and set the parameters.
  174. //
  175. // Software Guide : EndLatex
  176. // Software Guide : BeginCodeSnippet
  177. filter1->SetInput(fixedReader->GetOutput());
  178. filter2->SetInput(movingReader->GetOutput());
  179. filter1->SetOctavesNumber(octaves);
  180. filter1->SetScalesNumber(scales);
  181. filter1->SetDoGThreshold(threshold);
  182. filter1->SetEdgeThreshold(ratio);
  183. filter2->SetOctavesNumber(octaves);
  184. filter2->SetScalesNumber(scales);
  185. filter2->SetDoGThreshold(threshold);
  186. filter2->SetEdgeThreshold(ratio);
  187. // Software Guide : EndCodeSnippet
  188. // Software Guide : BeginLatex
  189. //
  190. // We use a simple Euclidean distance to select
  191. // matched points.
  192. //
  193. // Software Guide : EndLatex
  194. // Software Guide : BeginCodeSnippet
  195. euclideanMatcher->SetInput1(filter1->GetOutput());
  196. euclideanMatcher->SetInput2(filter2->GetOutput());
  197. euclideanMatcher->SetDistanceThreshold(secondOrderThreshold);
  198. euclideanMatcher->SetUseBackMatching(useBackMatching);
  199. euclideanMatcher->Update();
  200. // Software Guide : EndCodeSnippet
  201. // Software Guide : BeginLatex
  202. //
  203. // The matched points will be stored into a landmark list.
  204. //
  205. // Software Guide : EndLatex
  206. // Software Guide : BeginCodeSnippet
  207. LandmarkListType::Pointer landmarkList;
  208. landmarkList = euclideanMatcher->GetOutput();
  209. // Software Guide : EndCodeSnippet
  210. // Software Guide : BeginLatex
  211. //
  212. // Apply Mean square algorithm
  213. //
  214. // Software Guide : EndLatex
  215. // Software Guide : BeginCodeSnippet
  216. typedef itk::Point<double, 2> MyPointType;
  217. typedef otb::LeastSquareAffineTransformEstimator<MyPointType> EstimatorType;
  218. // instantiation of the estimator of the affine transformation
  219. EstimatorType::Pointer estimator = EstimatorType::New();
  220. std::cout << "landmark list size " << landmarkList->Size() << std::endl;
  221. for (LandmarkListType::Iterator it = landmarkList->Begin();
  222. it != landmarkList->End(); ++it)
  223. {
  224. estimator->AddTiePoints(it.Get()->GetPoint1(), it.Get()->GetPoint2());
  225. }
  226. // Trigger computation
  227. estimator->Compute();
  228. // Software Guide : EndCodeSnippet
  229. // Software Guide : BeginLatex
  230. //
  231. // Resample the initial image with the transformation evaluated
  232. //
  233. // Software Guide : EndLatex
  234. // Software Guide : BeginLatex
  235. //
  236. // It is common, as the last step of a registration task, to use
  237. // the resulting transform to map the moving image into the fixed
  238. // image space. This is easily done with the
  239. // \doxygen{itk}{ResampleImageFilter}. First, a ResampleImageFilter
  240. // type is instantiated using the image types.
  241. //
  242. // Software Guide : EndLatex
  243. // Software Guide : BeginCodeSnippet
  244. typedef itk::ResampleImageFilter<
  245. ImageType,
  246. OutputImageType> ResampleFilterType;
  247. // Software Guide : EndCodeSnippet
  248. // Software Guide : BeginLatex
  249. //
  250. // A resampling filter is created and the moving image is connected as
  251. // its input.
  252. //
  253. // Software Guide : EndLatex
  254. // Software Guide : BeginCodeSnippet
  255. ResampleFilterType::Pointer resampler = ResampleFilterType::New();
  256. resampler->SetInput(movingReader->GetOutput());
  257. // Software Guide : EndCodeSnippet
  258. // Software Guide : BeginLatex
  259. //
  260. // The Transform that is produced as output do not need to be inversed because
  261. // we apply here the resampling algorithm to the "moving" image
  262. // to produce the fixed image.
  263. //
  264. // Software Guide : EndLatex
  265. // Write the transformation to a file
  266. std::ofstream ofs;
  267. ofs.open(outputTransformationFilename);
  268. // Set floatfield to format properly
  269. ofs.setf(std::ios::fixed, std::ios::floatfield);
  270. ofs.precision(10);
  271. ofs << "Transformation" << std::endl;
  272. ofs << "Estimated affine matrix: " << std::endl;
  273. ofs << estimator->GetMatrix() << std::endl;
  274. ofs << "Estimated affine offset: " << std::endl;
  275. ofs << estimator->GetOffset() << std::endl;
  276. ofs << "RMS error: " << std::endl;
  277. ofs << estimator->GetRMSError() << std::endl;
  278. ofs << "Relative residual: " << std::endl;
  279. ofs << estimator->GetRelativeResidual() << std::endl;
  280. ofs.close();
  281. // Software Guide : BeginCodeSnippet
  282. ImageType::Pointer fixedImage = fixedReader->GetOutput();
  283. resampler->SetTransform(estimator->GetAffineTransform());
  284. resampler->SetSize(fixedImage->GetLargestPossibleRegion().GetSize());
  285. resampler->SetOutputOrigin(fixedImage->GetOrigin());
  286. resampler->SetOutputSpacing(fixedImage->GetSpacing());
  287. resampler->SetDefaultPixelValue(100);
  288. // Software Guide : EndCodeSnippet
  289. // Software Guide : BeginLatex
  290. //
  291. // Write resampled image to png
  292. //
  293. // Software Guide : EndLatex
  294. // Software Guide : BeginCodeSnippet
  295. typedef otb::ImageFileWriter<OutputImageType> WriterType;
  296. WriterType::Pointer writer = WriterType::New();
  297. writer->SetInput(resampler->GetOutput());
  298. writer->SetFileName(outputImageFilename);
  299. writer->Update();
  300. // Software Guide : EndCodeSnippet
  301. // Software Guide : BeginLatex
  302. //
  303. // Figure~\ref{fig:SIFTDME} shows the result of the resampled image using the
  304. // estimated transformation based on SIFT points
  305. //
  306. // \begin{figure}
  307. // \center
  308. // \includegraphics[width=0.40\textwidth]{QB_Suburb.eps}
  309. // \includegraphics[width=0.40\textwidth]{QB_SuburbR10X13Y17.eps}
  310. // \includegraphics[width=0.40\textwidth]{AffineTransformationOutput.eps}
  311. // \itkcaption[Estimation of affine transformation using least square optimisation from SIFT points]{From left
  312. // to right and top to bottom: fixed input image, moving image,
  313. // resampled moving image.}
  314. // \label{fig:SIFTDME}
  315. // \end{figure}
  316. //
  317. // Software Guide : EndLatex
  318. return EXIT_SUCCESS;
  319. }