18 #ifndef __otbImageToPathListAlignFilter_txx
19 #define __otbImageToPathListAlignFilter_txx
26 #include "itkNumericTraits.h"
43 template <
class TInputImage,
class TOutputPath>
47 this->SetNumberOfRequiredInputs(1);
49 m_isMeaningfulSegment =
false;
50 m_NbGradDirection = 16;
51 m_NbLineDirection = 96;
55 for (
unsigned int i = 0; i < InputImageDimension; ++i)
62 m_PathValue = itk::NumericTraits<ValueType>::One;
63 m_BackgroundValue = itk::NumericTraits<ValueType>::Zero;
67 template <
class TInputImage,
class TOutputPath>
74 template <
class TInputImage,
class TOutputPath>
80 for (i = 0; i < InputImageDimension; ++i)
82 if (spacing[i] != m_Spacing[i])
87 if (i < InputImageDimension)
89 for (i = 0; i < InputImageDimension; ++i)
91 m_Spacing[i] = spacing[i];
97 template <
class TInputImage,
class TOutputPath>
103 for (i = 0; i < InputImageDimension; ++i)
105 if ((
double) spacing[i] != m_Spacing[i])
110 if (i < InputImageDimension)
112 for (i = 0; i < InputImageDimension; ++i)
114 m_Spacing[i] = spacing[i];
120 template <
class TInputImage,
class TOutputPath>
129 template <
class TInputImage,
class TOutputPath>
135 for (i = 0; i < InputImageDimension; ++i)
137 if (origin[i] != m_Origin[i])
142 if (i < InputImageDimension)
144 for (i = 0; i < InputImageDimension; ++i)
146 m_Origin[i] = origin[i];
151 template <
class TInputImage,
class TOutputPath>
157 for (i = 0; i < InputImageDimension; ++i)
159 if ((
double) origin[i] != m_Origin[i])
164 if (i < InputImageDimension)
166 for (i = 0; i < InputImageDimension; ++i)
168 m_Origin[i] = origin[i];
173 template <
class TInputImage,
class TOutputPath>
183 template <
class TInputImage,
class TOutputPath>
188 std::vector<double> out;
189 int adr1, adr2, x, y;
194 out.resize((n + 1) * (n + 1));
199 for (y = 1, adr2 = 0; y <= n; ++y)
203 out[adr2] = q * out[adr1];
204 for (x = 1; x <= y; ++x)
205 out[adr2 + x] = p * out[adr1 + x - 1] + q * out[adr1 + x];
209 for (y = 1, adr1 = n + 1; y <= n; ++y, adr1 += n + 1)
210 for (x = y - 1; x >= 0; x--)
211 out[adr1 + x] += out[adr1 + x + 1];
214 for (adr1 = (n + 1) * (n + 1); --adr1 >= 0; )
220 template <
class TInputImage,
class TOutputPath>
228 typename InputImageType::SizeType Taille;
231 Taille = InputImage->GetLargestPossibleRegion().GetSize();
234 region.SetSize(InputImage->GetLargestPossibleRegion().GetSize());
239 m_AngleImage->SetRegions(region);
240 m_AngleImage->SetOrigin(InputImage->GetOrigin());
241 m_AngleImage->SetSpacing(InputImage->GetSpacing());
242 m_AngleImage->Allocate();
247 threshold = m_MinGradNorm;
248 threshold *= threshold;
250 typename InputImageType::IndexType idx;
252 for (x = 0; x < p; ++x)
257 m_AngleImage->SetPixel(idx, static_cast<RealType>(-1000.0));
259 for (y = 0; y < n; ++y)
264 m_AngleImage->SetPixel(idx, static_cast<RealType>(-1000.0));
267 typename InputImageType::IndexType adr;
268 RealType PixelA, PixelB, PixelC, PixelD;
271 for (x = 0; x < p - 1; ++x)
272 for (y = 0; y < n - 1; ++y)
279 PixelA =
static_cast<RealType>(InputImage->GetPixel(idx));
286 PixelB =
static_cast<RealType>(InputImage->GetPixel(idx));
293 PixelC =
static_cast<RealType>(InputImage->GetPixel(idx));
300 PixelD =
static_cast<RealType>(InputImage->GetPixel(idx));
301 com1 = PixelA - PixelB;
302 com2 = PixelC - PixelD;
303 gx = 0.5 * (com1 + com2);
304 gy = 0.5 * (com1 - com2);
305 norm = gx * gx + gy * gy;
307 if (norm <= threshold) m_AngleImage->SetPixel(adr, static_cast<RealType>(-1000.0));
308 else m_AngleImage->SetPixel(adr, static_cast<RealType>(vcl_atan2(gx, -gy)));
312 template <
class TInputImage,
class TOutputPath>
319 typename InputImageType::SizeType Taille;
322 int iseglist, size_seglist;
325 std::vector<double> test;
326 std::vector<int> count, startbloc, endbloc;
327 std::vector<double> seglist;
328 std::vector<one_segment> seg;
329 int mx, my, ox, oy, nx, ny, n;
330 int xx, yy, pos, posmax, nblocs, inbloc, max_nblocs;
331 int cur, i, j, side, l, lphase;
334 double theta, theta0, dtheta, dx, dy, prec;
336 itkDebugMacro(<<
"ImageToPathListAlignFilter::GenerateData() called");
345 Taille = InputImage->GetLargestPossibleRegion().GetSize();
348 max_nfa = vcl_pow(10.0, -(m_Eps));
353 n = (int) vcl_ceil(hypot((
double) nx, (
double) ny)) + 1;
358 this->AngleCalculate(InputImage);
361 test = tab(n, 1.0 / (
double) (m_NbGradDirection), (
double) (nx * ny) * (
double) (nx * ny));
364 prec =
CONST_PI / (double) (m_NbGradDirection);
365 ntheta = m_NbLineDirection / 2;
366 dtheta =
CONST_PI / (double) ntheta;
370 max_nblocs = n / 2 + 1;
371 count.resize(max_nblocs);
372 startbloc.resize(max_nblocs);
373 endbloc.resize(max_nblocs);
376 seg.resize(size_seg);
378 size_seglist = 10000;
379 seglist.resize(5 * size_seglist);
386 for (side = 0; side < 4; side++)
388 printf(
"side %d/4 ", side + 1);
391 mx = ((side == 0 || side == 2) ? 1 : 0);
392 my = ((side == 1 || side == 3) ? 1 : 0);
393 ox = ((side == 1) ? nx - 1 : 0);
394 oy = ((side == 2) ? ny - 1 : 0);
396 posmax = nx * mx + ny * my;
399 for (itheta = 0; itheta < ntheta; itheta++)
403 theta = theta0 + (double) (itheta) * dtheta;
404 dx = (double) vcl_cos((
double) theta);
405 dy = (double) vcl_sin((
double) theta);
408 for (pos = 0; pos < posmax; ++pos)
415 for (lphase = 0; lphase < 2; lphase++)
419 inbloc = nblocs = cur = l = count[0] = 0;
420 xx = ox + pos * mx + (int) (dx * (
double) (l * 2 + lphase));
421 yy = oy + pos * my + (int) (dy * (
double) (l * 2 + lphase));
423 for (; xx >= 0 && xx < nx && yy >= 0 && yy < ny; )
428 assert(indexAngle[0] < nx);
429 assert(indexAngle[1] < ny);
430 assert(indexAngle[0] >= 0);
431 assert(indexAngle[1] >= 0);
433 error =
static_cast<double>(m_AngleImage->GetPixel(indexAngle));
441 if (error < 0.0) error = -error;
447 startbloc[nblocs] = l;
455 endbloc[nblocs] = l - 1;
464 xx = ox + pos * mx + (int) (dx * (
double) (l * 2 + lphase));
465 yy = oy + pos * my + (int) (dy * (
double) (l * 2 + lphase));
469 for (i = 0; i < nblocs; ++i)
470 for (j = i; j < nblocs; ++j)
471 if ((nfa = test[count[j + 1] - count[i]
472 + (n + 1) * (1 + endbloc[j] - startbloc[i])]) < max_nfa)
474 seg[iseg].start = startbloc[i] * 2 + lphase;
475 seg[iseg].end = endbloc[j] * 2 + lphase;
480 if (iseg == size_seg)
482 size_seg = (size_seg * 3) / 2;
483 seg.resize(size_seg);
492 if (!m_isMeaningfulSegment)
493 for (i = 0; i < iseg; ++i)
494 for (j = 0; j < iseg; ++j)
498 if (seg[i].start >= seg[j].start && seg[i].end <= seg[j].end)
502 if (seg[i].nfa < seg[j].nfa) seg[j].ok = 0;
508 for (i = 0; i < iseg; ++i)
511 seglist[iseglist * 5] = (double) (ox + pos * mx) + dx * (double) (seg[i].start);
512 seglist[iseglist * 5 + 1] = (double) (oy + pos * my) + dy * (double) (seg[i].start);
513 seglist[iseglist * 5 + 2] = (double) (ox + pos * mx) + dx * (double) (seg[i].end);
514 seglist[iseglist * 5 + 3] = (double) (oy + pos * my) + dy * (double) (seg[i].end);
515 seglist[iseglist * 5 + 4] = -(double) log10(seg[i].nfa);
518 if (iseglist == size_seglist)
520 size_seglist = (size_seglist * 3) / 2;
521 seglist.resize(size_seglist);
530 printf(
" nb de segments: %d\n", iseglist);
541 seglist.resize(5 * iseglist);
547 typedef typename OutputPathType::ContinuousIndexType ContinuousIndexType;
548 typename InputImageType::PointType point;
550 ContinuousIndexType cindex;
551 for (i = 0; i < iseglist; ++i)
557 point[0] = seglist[i * 5];
558 point[1] = seglist[i * 5 + 1];
559 InputImage->TransformPhysicalPointToContinuousIndex(point, cindex);
560 path->AddVertex(cindex);
561 cindex[0] = seglist[i * 5 + 2];
562 cindex[1] = seglist[i * 5 + 3];
563 path->AddVertex(cindex);
567 itkDebugMacro(<<
"ImageToPathListAlignFilter::GenerateData() finished");
571 template <
class TInputImage,
class TOutputPath>
576 Superclass::PrintSelf(os, indent);