24 #ifndef otbRegionImageToRectangularPathListFilter_hxx
25 #define otbRegionImageToRectangularPathListFilter_hxx
30 #include "itkImageRegionIterator.h"
31 #include "itkImageRegionIteratorWithIndex.h"
32 #include "itkConstNeighborhoodIterator.h"
33 #include "itkPathIterator.h"
34 #include "itkImageLinearIteratorWithIndex.h"
36 #include "itkNeighborhoodBinaryThresholdImageFunction.h"
37 #include "itkFloodFilledImageFunctionConditionalIterator.h"
38 #include "itkConstNeighborhoodIterator.h"
39 #include "itkConstantBoundaryCondition.h"
45 template <
class TInputImage,
class TOutputPath>
48 this->SetNumberOfRequiredInputs(1);
55 template <
class TInputImage,
class TOutputPath>
62 template <
class TInputImage,
class TOutputPath>
65 typename InputImageType::SizeType Taille;
76 Taille = InputImage->GetLargestPossibleRegion().GetSize();
77 itkDebugMacro(<<
"Input image size : " << Taille);
79 typename InputImageType::PointType origin;
80 typename InputImageType::SpacingType spacing;
81 origin = InputImage->GetOrigin();
82 spacing = InputImage->GetSignedSpacing();
83 std::cout <<
"Image origin : " << origin << std::endl;
84 std::cout <<
"Image spacing : " << spacing << std::endl;
86 typedef itk::ImageRegionConstIterator<InputImageType> IteratorType;
87 IteratorType it(InputImage, InputImage->GetLargestPossibleRegion());
90 int selectedRegionCount = 0;
91 int pixelDebugNumber = 0;
92 int regionDebugNumber = 0;
94 typedef itk::ConstNeighborhoodIterator<InputImageType> NeighborhoodIteratorType;
95 typename NeighborhoodIteratorType::RadiusType radius;
98 NeighborhoodIteratorType nit(radius, InputImage, InputImage->GetLargestPossibleRegion());
99 NeighborhoodIteratorType nit2(radius, InputImage, InputImage->GetLargestPossibleRegion());
101 itk::ConstantBoundaryCondition<TInputImage> BC;
103 BC.SetConstant(itk::NumericTraits<PixelType>::max());
104 nit.OverrideBoundaryCondition(&BC);
105 nit2.OverrideBoundaryCondition(&BC);
108 markerImage = MarkerImageType::New();
111 markerImage->SetLargestPossibleRegion(markerRegion);
112 markerImage->SetBufferedRegion(markerRegion);
113 markerImage->SetRequestedRegion(markerRegion);
114 markerImage->Allocate();
115 unsigned char maxValue = itk::NumericTraits<typename MarkerImageType::PixelType>::max();
116 markerImage->FillBuffer(maxValue);
117 unsigned char zeroValue = itk::NumericTraits<typename MarkerImageType::PixelType>::Zero;
118 unsigned char regionValue;
123 typedef itk::ImageRegionIteratorWithIndex<MarkerImageType> MarkerIteratorType;
124 MarkerIteratorType mit(markerImage, markerRegion);
126 typedef typename TInputImage::IndexType IndexType;
127 std::vector<IndexType> regionContainer;
128 typename std::vector<IndexType>::iterator regionIterator;
130 regionContainer.reserve(Taille[0] * Taille[1]);
131 IndexType explorerIndex;
137 for (nit.GoToBegin(), pixelCount = 0; !nit.IsAtEnd(); ++nit)
140 if (pixelCount <= pixelDebugNumber)
142 std::cout <<
"Pixel #" << pixelCount <<
" : " << nit.GetCenterPixel() << std::endl;
143 for (neighbor = 1; neighbor <= 7; neighbor += 2)
144 std::cout <<
"Neighbor #" << neighbor <<
" : " << nit.GetPixel(neighbor) << std::endl;
146 mit.SetIndex(nit.GetIndex());
147 if (mit.Get() == maxValue)
150 regionContainer.clear();
151 regionContainer.push_back(nit.GetIndex());
152 regionValue = nit.GetCenterPixel();
154 if (pixelCount <= pixelDebugNumber)
156 std::cout <<
"Starting new region at " << nit.GetIndex() <<
" with value " << (
unsigned short)regionValue << std::endl;
159 for (regionIterator = regionContainer.begin(); regionIterator != regionContainer.end(); ++regionIterator )
162 explorerIndex = *regionIterator;
163 nit2.SetLocation(explorerIndex);
164 if (pixelCount <= pixelDebugNumber)
165 std::cout <<
"Exploring neighbors of " << explorerIndex << std::endl;
167 for (neighbor = 1; neighbor <= 7; neighbor += 2)
168 if (nit2.GetPixel(neighbor) == regionValue)
170 mit.SetIndex(nit2.GetIndex(neighbor));
171 if (mit.Get() == maxValue)
174 regionContainer.push_back(nit2.GetIndex(neighbor));
175 if (pixelCount <= pixelDebugNumber)
177 std::cout <<
"Adding " << nit2.GetIndex(neighbor) << std::endl;
178 std::cout <<
"Added " << regionContainer.back() << std::endl;
183 if (pixelCount <= pixelDebugNumber)
185 std::cout <<
"Region queue (" << regionContainer.size() <<
" elements) : " << std::endl;
186 for (regionIterator = regionContainer.begin(); regionIterator != regionContainer.end(); ++regionIterator)
187 std::cout << *regionIterator;
188 std::cout << std::endl;
192 double sumX = 0, sumY = 0, sumX2 = 0, sumY2 = 0, sumXY = 0;
193 double avgX, avgY, varX, varY, covarXY;
194 int n = regionContainer.size();
195 for (regionIterator = regionContainer.begin(); regionIterator != regionContainer.end(); ++regionIterator)
197 explorerIndex = *regionIterator;
198 sumX += explorerIndex[0];
199 sumY += explorerIndex[1];
200 sumX2 += explorerIndex[0] * explorerIndex[0];
201 sumY2 += explorerIndex[1] * explorerIndex[1];
202 sumXY += explorerIndex[0] * explorerIndex[1];
204 avgX = (double)sumX / n;
205 avgY = (double)sumY / n;
206 varX = (double)sumX2 / n - avgX * avgX;
207 varY = (double)sumY2 / n - avgY * avgY;
208 covarXY = (double)sumXY / n - avgX * avgY;
211 double sumAX = 0, sumAY = 0, crossTermAXY = 0;
212 double adevX, adevY, adevXY;
214 for (regionIterator = regionContainer.begin(); regionIterator != regionContainer.end(); ++regionIterator)
216 explorerIndex = *regionIterator;
217 ax = std::abs(explorerIndex[0] - avgX);
218 ay = std::abs(explorerIndex[1] - avgY);
221 crossTermAXY += ax * ay;
225 adevXY = std::sqrt(crossTermAXY) / n;
228 double delta, l1, l2,
233 delta = (varX - varY) * (varX - varY) + 4 * covarXY * covarXY;
234 l1 = (varX + varY + std::sqrt(delta)) / 2;
235 l2 = (varX + varY - std::sqrt(delta)) / 2;
238 y1 = (l1 - varX) / covarXY;
239 y2 = (l2 - varX) / covarXY;
249 double adelta, al1, al2,
253 adelta = (adevX - adevY) * (adevX - adevY) + 4 * adevXY * adevXY;
254 al1 = (adevX + adevY + std::sqrt(adelta)) / 2;
255 al2 = (adevX + adevY - std::sqrt(adelta)) / 2;
258 ay1 = (al1 - adevX) / adevXY;
259 ay2 = (al2 - adevX) / adevXY;
269 alpha = std::atan(1 / y1) * 180 / vnl_math::pi;
276 double length, width;
279 length = std::sqrt(std::abs(al1 / al2) * n);
282 width = std::abs(al2 / al1) * length;
285 length = width = std::sqrt(
static_cast<double>(n));
296 norm = std::sqrt(x1 * x1 + y1 * y1);
303 norm = std::sqrt(x2 * x2 + y2 * y2);
312 norm = std::sqrt(ax1 * ax1 + ay1 * ay1);
319 norm = std::sqrt(ax2 * ax2 + ay2 * ay2);
330 double halfLength = length / 2, halfWidth = width / 2;
332 for (regionIterator = regionContainer.begin(); regionIterator != regionContainer.end(); ++regionIterator)
334 explorerIndex = *regionIterator;
335 vx = explorerIndex[0] - avgX;
336 vy = explorerIndex[1] - avgY;
337 if (std::abs(vx * x1 + vy * y1) <= halfLength && std::abs(vx * x2 + vy * y2) <= halfWidth)
341 if (regionCount <= regionDebugNumber)
343 std::cout << std::endl <<
"Region " << regionCount <<
" (area = " << n <<
" pixels)" << std::endl;
344 std::cout <<
"sumX = " << sumX <<
"; sumY = " << sumY <<
"; sumX2 = " << sumX2 <<
"; sumY2 = " << sumY2 <<
"; sumXY = " << sumXY << std::endl;
345 std::cout <<
"avgX = " << avgX <<
"; avgY = " << avgY << std::endl;
346 std::cout <<
"varX = " << varX <<
"; varY = " << varY <<
"; covarXY = " << covarXY << std::endl;
347 std::cout <<
"adevX = " << adevX <<
"; adevY = " << adevY <<
"; adevXY = " << adevXY << std::endl;
348 std::cout <<
"crossTermAXY = " << crossTermAXY << std::endl;
349 std::cout <<
"eigenvalue 1 = " << l1 <<
"; eigenvalue 2 = " << l2 << std::endl;
350 std::cout <<
"eigenvector 1 = [" << x1 <<
", " << y1 <<
"]; eigenvector 2 = [" << x2 <<
", " << y2 <<
"]" << std::endl;
351 std::cout <<
"A-eigenvalue 1 = " << al1 <<
"; A-eigenvalue 2 = " << al2 << std::endl;
352 std::cout <<
"A-eigenvector 1 = [" << ax1 <<
", " << ay1 <<
"]; A-eigenvector 2 = [" << ax2 <<
", " << ay2 <<
"]" << std::endl;
353 std::cout <<
"length = " << length <<
"; width = " << width << std::endl;
354 std::cout <<
"main direction = " << alpha <<
" degree" << std::endl;
355 std::cout <<
"rectangular fit = " << (float)countWithin / n << std::endl;
359 typedef typename OutputPathType::ContinuousIndexType ContinuousIndexType;
361 ContinuousIndexType point;
366 point[0] = (avgX + x1 * halfLength + x2 * halfWidth) * spacing[0] + origin[0];
367 point[1] = (avgY + y1 * halfLength + y2 * halfWidth) * spacing[1] + origin[1];
368 path->AddVertex(point);
369 if (regionCount <= regionDebugNumber)
370 std::cout <<
"corner 1 : [" << point[0] <<
", " << point[1] <<
"]" << std::endl;
371 point[0] = (avgX - x1 * halfLength + x2 * halfWidth) * spacing[0] + origin[0];
372 point[1] = (avgY - y1 * halfLength + y2 * halfWidth) * spacing[1] + origin[1];
373 path->AddVertex(point);
374 if (regionCount <= regionDebugNumber)
375 std::cout <<
"corner 2 : [" << point[0] <<
", " << point[1] <<
"]" << std::endl;
376 point[0] = (avgX - x1 * halfLength - x2 * halfWidth) * spacing[0] + origin[0];
377 point[1] = (avgY - y1 * halfLength - y2 * halfWidth) * spacing[1] + origin[1];
378 path->AddVertex(point);
379 if (regionCount <= regionDebugNumber)
380 std::cout <<
"corner 3 : [" << point[0] <<
", " << point[1] <<
"]" << std::endl;
381 point[0] = (avgX + x1 * halfLength - x2 * halfWidth) * spacing[0] + origin[0];
382 point[1] = (avgY + y1 * halfLength - y2 * halfWidth) * spacing[1] + origin[1];
383 path->AddVertex(point);
384 if (regionCount <= regionDebugNumber)
385 std::cout <<
"corner 4 : [" << point[0] <<
", " << point[1] <<
"]" << std::endl;
386 point[0] = (avgX + x1 * halfLength + x2 * halfWidth) * spacing[0] + origin[0];
387 point[1] = (avgY + y1 * halfLength + y2 * halfWidth) * spacing[1] + origin[1];
388 path->AddVertex(point);
390 path->SetValue((
double)countWithin / n);
392 if ((
float)countWithin / n >= m_MinimumFit
393 && n >= m_MinimumSize)
396 selectedRegionCount++;
401 catch (std::exception& e)
403 std::cerr <<
"Caught exception " << e.what() << std::endl;
405 std::cout << pixelCount <<
" pixels seen." << std::endl;
406 std::cout << regionCount <<
" regions processed, " << selectedRegionCount <<
" regions selected." << std::endl;
408 itkDebugMacro(<<
"ImageToPathListAlignFilter::GenerateData() finished");
412 template <
class TInputImage,
class TOutputPath>
415 Superclass::PrintSelf(os, indent);