Skeleton.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/rp/Skeleton.cpp
22  \brief Creation of skeleton imagems.
23 */
24 
25 #include "Skeleton.h"
26 #include "Macros.h"
27 #include "Functions.h"
28 
29 #include "../raster/Band.h"
30 #include "../raster/Utils.h"
31 #include "../common/PlatformUtils.h"
32 
33 #include <boost/lexical_cast.hpp>
34 #include <boost/scoped_array.hpp>
35 
36 #include <memory>
37 #include <cmath>
38 #include <cstring>
39 
40 #define DIFFUSENEIGHBOR( neighborRow, neighborCol ) \
41  if( bufferMag[ neighborRow ][ neighborCol ] >= centerMag ) \
42  { \
43  ++validNeigborsNumber; \
44  newCenterX += bufferX[ neighborRow ][ neighborCol ]; \
45  newCenterY += bufferY[ neighborRow ][ neighborCol ]; \
46  }
47 
48 #define SKELSTRENGTHNEIGHBOR( neighborRow, neighborCol ) \
49  neiX = inputX[ neighborRow ][ neighborCol ]; \
50  neiY = inputY[ neighborRow ][ neighborCol ]; \
51  diffX = neiX - centerX; \
52  diffY = neiY - centerY; \
53  diffMag = std::sqrt( ( diffX * diffX ) + ( diffY * diffY ) ); \
54  if( diffMag != 0.0 ) \
55  { \
56  strength += ( ( ( diffX * neiX ) + ( diffY * neiY ) ) / diffMag ); \
57  }
58 
59 namespace te
60 {
61  namespace rp
62  {
63 
65  {
66  reset();
67  }
68 
70  {
71  reset();
72  operator=( other );
73  }
74 
76  {
77  reset();
78  }
79 
81  {
82  m_inputRasterPtr = nullptr;
84  m_inputMaskRasterPtr = nullptr;
88  m_enableMultiThread = true;
89  m_skeletonThreshold = 0.75;
90  m_enableProgress = false;
91  }
92 
94  const Skeleton::InputParameters& params )
95  {
96  reset();
97 
107 
108  return *this;
109  }
110 
112  {
113  return new InputParameters( *this );
114  }
115 
117  {
118  reset();
119  }
120 
122  {
123  reset();
124  operator=( other );
125  }
126 
128  {
129  reset();
130  }
131 
133  {
134  m_rType.clear();
135  m_rInfo.clear();
136  m_outputRasterPtr.reset();
137  }
138 
140  const Skeleton::OutputParameters& params )
141  {
142  reset();
143 
144  m_rType = params.m_rType;
145  m_rInfo = params.m_rInfo;
146 
147  return *this;
148  }
149 
151  {
152  return new OutputParameters( *this );
153  }
154 
156  {
157  reset();
158  }
159 
160  Skeleton::~Skeleton() = default;
161 
163  _NOEXCEPT_OP(false)
164  {
165  if( ! m_isInitialized ) return false;
166 
167  Skeleton::OutputParameters* outParamsPtr = dynamic_cast<
168  Skeleton::OutputParameters* >( &outputParams );
169  TERP_TRUE_OR_THROW( outParamsPtr, "Invalid paramters" );
170 
171  // progress
172 
173  std::unique_ptr< te::common::TaskProgress > progressPtr;
175  {
176  progressPtr.reset( new te::common::TaskProgress );
177 
178  progressPtr->setTotalSteps( 7 );
179 
180  progressPtr->setMessage( "Generating the skeleton" );
181  }
182 
183  // loading raster data
184 
185  std::unique_ptr< te::rp::Matrix< double > > rasterDataPtr(
186  new te::rp::Matrix< double > ); ;
187  rasterDataPtr->reset( te::rp::Matrix< double >::AutoMemPol );
188  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( loadData( *rasterDataPtr ),
189  "Gradient maps build error" );
190 // CreateRasterFileFromMatrix( *rasterDataPtr, true, "rasterData.tif" );
191 
193  {
194  progressPtr->pulse();
195  if( ! progressPtr->isActive() ) return false;
196  }
197 
198  // Applying the smooth filter
199 
200  {
201  std::unique_ptr< te::rp::Matrix< double > > smoothedRasterDataPtr(
202  new te::rp::Matrix< double > ); ;
203  smoothedRasterDataPtr->reset( te::rp::Matrix< double >::AutoMemPol );
204  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( applyMeanSmooth( *rasterDataPtr, *smoothedRasterDataPtr ),
205  "Raster data smoothing error" );
206 // CreateRasterFileFromMatrix( *smoothedRasterDataPtr, true, "smoothedRasterData.tif" );
207  rasterDataPtr.reset( smoothedRasterDataPtr.release() );
208  }
209 
211  {
212  progressPtr->pulse();
213  if( ! progressPtr->isActive() ) return false;
214  }
215 
216  // calculating the edge strength map
217 
218  te::rp::Matrix< double > edgeStrengthMap;
219  edgeStrengthMap.reset( te::rp::Matrix< double >::AutoMemPol );
221  edgeStrengthMap ), "Edge strength map build error" );
222 // CreateRasterFileFromMatrix( edgeStrengthMap, true, "edgeStrengthMap.tif" );
223 
224  rasterDataPtr.reset();
225 
227  {
228  progressPtr->pulse();
229  if( ! progressPtr->isActive() ) return false;
230  }
231 
232  // Generating the initial vector field
233 
234  te::rp::Matrix< double > vecXMap;
236  te::rp::Matrix< double > vecYMap;
238 // TERP_INSTANCE_TRUE_OR_RETURN_FALSE( getEdgeVecField( edgeStrengthMap, true,
239 // vecXMap, vecYMap ),
240  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( getGradientMaps( edgeStrengthMap, true, vecXMap, vecYMap ),
241  "Vector maps build error" );
242 // {
243 // CreateRasterFileFromMatrix( vecXMap, true, "vecXMap.tif" );
244 // CreateRasterFileFromMatrix( vecYMap, true, "vecYMap.tif" );
245 // createTifFromVecField( vecXMap, vecYMap, &edgeStrengthMap, 3, "vecMap" );
246 // te::rp::Matrix< double > vecMagMap;
247 // getMagnitude( vecXMap, vecYMap, vecMagMap );
248 // CreateRasterFileFromMatrix( vecMagMap, true, "vecMagMap.tif" );
249 // }
250 
252  {
253  progressPtr->pulse();
254  if( ! progressPtr->isActive() ) return false;
255  }
256 
257  // Applying a vector diffusion
258 
259  te::rp::Matrix< double > diffusedVecXMap;
260  diffusedVecXMap.reset( te::rp::Matrix< double >::AutoMemPol );
261  te::rp::Matrix< double > diffusedVecYMap;
262  diffusedVecYMap.reset( te::rp::Matrix< double >::AutoMemPol );
263  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( applyVecDiffusion( vecXMap, vecYMap, nullptr,
264  progressPtr.get(), diffusedVecXMap, diffusedVecYMap ),
265  "Vector maps build error" );
266 // {
267 // CreateRasterFileFromMatrix( diffusedVecXMap, true, "diffusedVecXMap.tif" );
268 // CreateRasterFileFromMatrix( diffusedVecYMap, true, "diffusedVecYMap.tif" );
269 // createTifFromVecField( diffusedVecXMap, diffusedVecYMap, rasterDataPtr.get(),
270 // 4, "diffusedVecMap" );
271 // te::rp::Matrix< double > diffusedVecXMagMap;
272 // getMagnitude( diffusedVecXMap, diffusedVecYMap, diffusedVecXMagMap );
273 // CreateRasterFileFromMatrix( diffusedVecXMagMap, true, "diffusedVecXMagMap.tif" );
274 // }
275 
276  vecXMap.reset();
277  vecYMap.reset();
278 
280  {
281  progressPtr->pulse();
282  if( ! progressPtr->isActive() ) return false;
283  }
284 
285  // Calculating the skeleton strength map
286 
287  te::rp::Matrix< double > skelSMap;
290  diffusedVecYMap, edgeStrengthMap, skelSMap ),
291  "Skeleton strength map build error" );
292 // CreateRasterFileFromMatrix( skelSMap, true, "skelSMap.tif" );
293 
294  diffusedVecXMap.reset();
295  diffusedVecYMap.reset();
296 
298  {
299  progressPtr->pulse();
300  if( ! progressPtr->isActive() ) return false;
301  }
302 
303  // creating the output raster
304 
305  {
306  std::vector< te::rst::BandProperty* > bandsProperties;
307  bandsProperties.push_back( new te::rst::BandProperty(
310  bandsProperties[ 0 ]->m_noDataValue = 0;
311  bandsProperties[ 0 ]->m_colorInterp = te::rst::GrayIdxCInt;
312  bandsProperties[ 0 ]->m_type = te::dt::UCHAR_TYPE;
313 
314  outParamsPtr->m_outputRasterPtr.reset(
316  outParamsPtr->m_rType,
318  bandsProperties,
319  outParamsPtr->m_rInfo,
320  nullptr,
321  nullptr ) );
323  "Output raster creation error" );
324 
325  te::rst::Band& outBand = *( outParamsPtr->m_outputRasterPtr->getBand( 0 ) );
326  const unsigned int nRows = outParamsPtr->m_outputRasterPtr->getNumberOfRows();
327  const unsigned int nCols = outParamsPtr->m_outputRasterPtr->getNumberOfColumns();
328  const unsigned int rowsBound = nRows - 4;
329  const unsigned int colsBound = nCols - 4;
330  unsigned int row = 0;
331  unsigned int col = 0;
332 
333  for( row = 0 ; row < nRows ; ++row )
334  {
335  for( col = 0 ; col < nCols ; ++col )
336  {
337  if(
338  ( skelSMap[ row ][ col ] > m_inputParameters.m_skeletonThreshold )
339  && ( row > 0 ) && ( row < rowsBound )
340  && ( col > 0 ) && ( col < colsBound )
341  )
342  {
343  outBand.setValue( col, row, 255 );
344  }
345  else
346  {
347  outBand.setValue( col, row, 0 );
348  }
349  }
350  }
351  }
352 
354  {
355  progressPtr->pulse();
356  if( ! progressPtr->isActive() ) return false;
357  }
358 
359  return true;
360  }
361 
363  {
365 
367  m_isInitialized = false;
368  }
369 
371  _NOEXCEPT_OP(false)
372  {
373  reset();
374 
375  Skeleton::InputParameters const* inputParamsPtr = dynamic_cast<
376  Skeleton::InputParameters const* >( &inputParams );
377  TERP_TRUE_OR_THROW( inputParamsPtr, "Invalid paramters pointer" );
378 
379  m_inputParameters = *inputParamsPtr;
380 
381  // Checking the input raster
382 
384  "Invalid m_inputRasterPtr" )
385 
388  "Invalid raster" );
389 
393  "Invalid raster band" );
394 
396  {
399  "Invalid mask raster" );
400 
403  "Invalid mask raster band" );
404 
408  "Invalid mask raster number of rows" );
409 
413  "Invalid mask raster number of columns" );
414  }
415 
419  "Invalid diffusion threshold" );
420 
424  "Invalid diffusion regularization" );
425 
429  "Invalid diffusion regularization" );
430 
431  m_isInitialized = true;
432 
433  return true;
434  }
435 
437  {
438  return m_isInitialized;
439  }
440 
442  {
443  const unsigned int nRows = m_inputParameters.m_inputRasterPtr->getNumberOfRows();
445 
446  if( ! rasterData.reset( nRows,nCols ) )
447  return false;
448 
449  unsigned int row = 0;
450  unsigned int col = 0;
453  te::rst::Band const * const maskBandPtr = m_inputParameters.m_inputMaskRasterPtr ?
455  double maskValue = 0;
456 
457  for( row = 0 ; row < nRows ; ++row )
458  {
459  for( col = 0 ; col < nCols ; ++col )
460  {
461  if( maskBandPtr )
462  {
463  maskBandPtr->getValue( col, row, maskValue );
464  if( maskValue == 0.0 )
465  {
466  rasterData[ row ][ col ] = 0;
467  continue;
468  }
469  }
470 
471  band.getValue( col, row , rasterData[ row ][ col ] );
472  }
473  }
474 
475  return true;
476  }
477 
479  const bool unitVectors,
480  te::rp::Matrix< double >& gradXMap,
481  te::rp::Matrix< double >& gradYMap ) const
482  {
483  const unsigned int nRows = inputData.getLinesNumber();
484  TERP_TRUE_OR_RETURN_FALSE( nRows > 2, "Invalid rows number" );
485 
486  const unsigned int nCols = inputData.getColumnsNumber();
487  TERP_TRUE_OR_RETURN_FALSE( nCols > 2, "Invalid columns number" );
488 
489  const unsigned int lastRowIdx = nRows - 1;
490  const unsigned int lastColIdx = nCols - 1;
491 
492  if( ! gradXMap.reset( nRows,nCols ) )
493  return false;
494  if( ! gradYMap.reset( nRows,nCols ) )
495  return false;
496 
497  unsigned int row = 0;
498  unsigned int col = 0;
499 
500  for( row = 0 ; row < nRows ; ++row )
501  {
502  for( col = 0 ; col < nCols ; ++col )
503  {
504  gradXMap[ row ][ col ] = 0;
505  gradYMap[ row ][ col ] = 0;
506  }
507  }
508 
509  double value1 = 0;
510  double value2 = 0;
511  double value3 = 0;
512  double value4 = 0;
513  double value5 = 0;
514  double value6 = 0;
515  double value7 = 0;
516  double value8 = 0;
517  unsigned int nextRow = 0;
518  unsigned int nextCol = 0;
519  unsigned int prevRow = 0;
520  unsigned int prevCol = 0;
521  double gradX = 0;
522  double gradY = 0;
523  double mag = 0;
524 
525  for( row = 1 ; row < lastRowIdx ; ++row )
526  {
527  prevRow = row - 1;
528  nextRow = row + 1;
529 
530  for( col = 1 ; col < lastColIdx ; ++col )
531  {
532  prevCol = col - 1;
533  nextCol = col + 1;
534 
535  value1 = inputData[ prevRow ][ prevCol ];
536  value2 = inputData[ prevRow ][ col ];
537  value3 = inputData[ prevRow ][ nextCol ];
538  value4 = inputData[ row ][ prevCol ];
539  value5 = inputData[ row ][ nextCol ];
540  value6 = inputData[ nextRow ][ prevCol ];
541  value7 = inputData[ nextRow ][ col ];
542  value8 = inputData[ nextRow ][ nextCol ];
543 
544  if(
545  ( inputData[ row ][ col ] == DBL_MAX ) ||
546  ( value1 == DBL_MAX ) || ( value2 == DBL_MAX ) ||
547  ( value3 == DBL_MAX ) || ( value4 == DBL_MAX ) ||
548  ( value5 == DBL_MAX ) || ( value6 == DBL_MAX ) ||
549  ( value7 == DBL_MAX ) || ( value8 == DBL_MAX )
550  )
551  {
552  continue;
553  }
554  else
555  {
556  gradX = ( ( value3 + value5 + value8 ) -
557  ( value1 + value4 + value6 ) );
558  gradY = ( ( value1 + value2 + value3 ) -
559  ( value6 + value7 + value8 ) );
560 
561  if( unitVectors && ( gradX != 0.0 ) && ( gradY != 0.0 ) )
562  {
563  mag = std::sqrt( ( gradX * gradX ) + ( gradY * gradY ) );
564  gradX /= mag;
565  gradY /= mag;
566  }
567 
568  gradXMap[ row ][ col ] = gradX;
569  gradYMap[ row ][ col ] = gradY;
570  }
571  }
572  }
573 
574  return true;
575  }
576 
578  const te::rp::Matrix< double >& inputMap,
579  te::rp::Matrix< double >& edgeStrengthMap ) const
580  {
581  const unsigned int nRows = inputMap.getLinesNumber();
582  TERP_TRUE_OR_RETURN_FALSE( nRows > 4, "Invalid rows number" );
583 
584  const unsigned int nCols = inputMap.getColumnsNumber();
585  TERP_TRUE_OR_RETURN_FALSE( nCols > 4, "Invalid columns number" );
586 
587  const unsigned int lastRowIdx = nRows - 1;
588  const unsigned int lastColIdx = nCols - 1;
589 
590  if( ! edgeStrengthMap.reset( nRows,nCols ) )
591  return false;
592 
593  te::rp::Matrix< double > gradXMap;
595  te::rp::Matrix< double > gradYMap;
597  TERP_TRUE_OR_RETURN_FALSE( getGradientMaps( inputMap, false, gradXMap, gradYMap ),
598  "Gradient maps build error" );
599 
600  unsigned int row = 0;
601  unsigned int col = 0;
602 
603  for( row = 0 ; row < nRows ; ++row )
604  {
605  edgeStrengthMap[ row ][ 0 ] = 0;
606  edgeStrengthMap[ row ][ lastColIdx ] = 0;
607  }
608 
609  for( col = 0 ; col < nCols ; ++col )
610  {
611  edgeStrengthMap[ 0 ][ col ] = 0;
612  edgeStrengthMap[ lastRowIdx ][ col ] = 0;
613  }
614 
615  double x1 = 0;
616  double y1 = 0;
617  double y2 = 0;
618  double x3 = 0;
619  double y3 = 0;
620  double x4 = 0;
621  double x5 = 0;
622  double x6 = 0;
623  double y6 = 0;
624  double y7 = 0;
625  double x8 = 0;
626  double y8 = 0;
627  unsigned int nextRow = 0;
628  unsigned int nextCol = 0;
629  unsigned int prevRow = 0;
630  unsigned int prevCol = 0;
631  double strengthYUp = 0;
632  double strengthYDown = 0;
633  double strengthXLeft = 0;
634  double strengthXRight = 0;
635  double strength = 0;
636  double diffX = 0;
637  double diffY = 0;
638  double minStrength = DBL_MAX;
639  double maxStrength = -1.0 * DBL_MAX;
640 
641  for( row = 1 ; row < lastRowIdx ; ++row )
642  {
643  prevRow = row - 1;
644  nextRow = row + 1;
645 
646  for( col = 1 ; col < lastColIdx ; ++col )
647  {
648  prevCol = col - 1;
649  nextCol = col + 1;
650 
651  x1 = gradXMap[ prevRow ][ prevCol ];
652  x3 = gradXMap[ prevRow ][ nextCol ];
653  x4 = gradXMap[ row ][ prevCol ];
654  x5 = gradXMap[ row ][ nextCol ];
655  x6 = gradXMap[ nextRow ][ prevCol ];
656  x8 = gradXMap[ nextRow ][ nextCol ];
657 
658  y1 = gradYMap[ prevRow ][ prevCol ];
659  y2 = gradYMap[ prevRow ][ col ];
660  y3 = gradYMap[ prevRow ][ nextCol ];
661  y6 = gradYMap[ nextRow ][ prevCol ];
662  y7 = gradYMap[ nextRow ][ col ];
663  y8 = gradYMap[ nextRow ][ nextCol ];
664 
665  strengthXRight = x1 + x4 + x6;
666  strengthXLeft = x3 + x5 + x8;
667  strengthYUp = y6 + y7 + y8;
668  strengthYDown = y1 + y2 + y3;
669 
670  diffX = std::abs( strengthXRight - strengthXLeft );
671  diffY = std::abs( strengthYUp - strengthYDown );
672 
673  strength = std::max( diffX, diffY );
674 
675  edgeStrengthMap[ row ][ col ] = strength;
676 
677  if( minStrength > strength ) minStrength = strength;
678  if( maxStrength < strength ) maxStrength = strength;
679  }
680  }
681 
682  const double gain = ( minStrength == maxStrength ) ? 0.0 :
683  ( 1.0 / ( maxStrength - minStrength ) );
684 
685  for( row = 1 ; row < lastRowIdx ; ++row )
686  {
687  for( col = 1 ; col < lastColIdx ; ++col )
688  {
689  strength = edgeStrengthMap[ row ][ col ] - minStrength;
690  strength *= gain;
691  edgeStrengthMap[ row ][ col ] = strength;
692  }
693  }
694 
695  return true;
696  }
697 
699  const te::rp::Matrix< double >& inputVecFieldX,
700  const te::rp::Matrix< double >& inputVecFieldY,
701  te::rp::Matrix< double > const * const backGroundMapPtr,
702  const unsigned int vecPixelStep,
703  const std::string& tifFileName ) const
704  {
705  assert( inputVecFieldX.getColumnsNumber() == inputVecFieldY.getColumnsNumber() );
706  assert( inputVecFieldX.getLinesNumber() == inputVecFieldY.getLinesNumber() );
707  assert( backGroundMapPtr ? inputVecFieldX.getColumnsNumber() ==
708  backGroundMapPtr->getColumnsNumber() : true );
709  assert( backGroundMapPtr ? inputVecFieldX.getLinesNumber() ==
710  backGroundMapPtr->getLinesNumber() : true );
711 
712  std::map<std::string, std::string> rInfo;
713  rInfo["URI"] = tifFileName + ".tif";
714 
715  std::vector<te::rst::BandProperty*> bandsProperties;
716  bandsProperties.push_back(new te::rst::BandProperty( 0, te::dt::UCHAR_TYPE, "" ));
717  bandsProperties[0]->m_colorInterp = te::rst::RedCInt;
718  bandsProperties[0]->m_noDataValue = -1.0 * DBL_MAX;
719  bandsProperties.push_back(new te::rst::BandProperty( *bandsProperties[0] ));
720  bandsProperties[0]->m_colorInterp = te::rst::GreenCInt;
721  bandsProperties.push_back(new te::rst::BandProperty( *bandsProperties[0] ));
722  bandsProperties[0]->m_colorInterp = te::rst::BlueCInt;
723 
724  te::rst::Grid* newgrid = new te::rst::Grid( inputVecFieldX.getColumnsNumber(),
725  inputVecFieldX.getLinesNumber(), nullptr, -1 );
726 
727  std::unique_ptr< te::rst::Raster > outputRasterPtr(
728  te::rst::RasterFactory::make( "GDAL", newgrid, bandsProperties, rInfo, nullptr, nullptr));
729  TERP_TRUE_OR_THROW( outputRasterPtr.get(), "Output raster creation error");
730 
731  unsigned int line = 0;
732  unsigned int col = 0;
733  const unsigned int nLines = inputVecFieldX.getLinesNumber();
734  const unsigned int nCols = inputVecFieldX.getColumnsNumber();
735  const unsigned int lastLineIdx = inputVecFieldX.getLinesNumber() - 1;
736  const unsigned int lastColIdx = inputVecFieldX.getColumnsNumber() - 1;
737  double x = 0.0;
738  double y = 0.0;
739 
740  if( backGroundMapPtr )
741  {
742  double minBGValue = DBL_MAX;
743  double maxBGValue = -1.0 * DBL_MAX;
744  double bGValue = 0;
745 
746  for( line = 0 ; line < nLines ; ++line )
747  {
748  for( col = 0 ; col < nCols ; ++col )
749  {
750  bGValue = backGroundMapPtr->operator[]( line )[ col ];
751 
752  if( minBGValue > bGValue )
753  {
754  minBGValue = bGValue;
755  }
756 
757  if( maxBGValue < bGValue )
758  {
759  maxBGValue = bGValue;
760  }
761  }
762  }
763 
764  for( line = 0 ; line < nLines ; ++line )
765  {
766  for( col = 0 ; col < nCols ; ++col )
767  {
768  bGValue = backGroundMapPtr->operator[]( line )[ col ];
769  bGValue -= minBGValue;
770  bGValue *= ( 128.0 / ( maxBGValue - minBGValue ) );
771 
772  outputRasterPtr->setValue( col, line, bGValue, 0 );
773  outputRasterPtr->setValue( col, line, bGValue, 1 );
774  outputRasterPtr->setValue( col, line, bGValue, 2 );
775  }
776  }
777  }
778  else
779  {
780  for( line = 0 ; line < nLines ; ++line )
781  {
782  for( col = 0 ; col < nCols ; ++col )
783  {
784  outputRasterPtr->setValue( col, line, 0, 0 );
785  outputRasterPtr->setValue( col, line, 0, 1 );
786  outputRasterPtr->setValue( col, line, 0, 2 );
787  }
788  }
789  }
790 
791  for( line = 1 ; line < lastLineIdx ; line += vecPixelStep )
792  {
793  for( col = 1 ; col < lastColIdx ; col += vecPixelStep )
794  {
795  x = inputVecFieldX[ line ][ col ];
796  y = inputVecFieldY[ line ][ col ];
797  outputRasterPtr->setValue( col, line, 255, 0 );
798 
799  if( x == 0 )
800  {
801  if( y > 0 )
802  {
803  outputRasterPtr->setValue( col, line - 1, 255, 1 );
804  }
805  else if ( y < 0 )
806  {
807  outputRasterPtr->setValue( col, line + 1, 255, 1 );
808  }
809  }
810  else if( x > 0 )
811  {
812  if( y == 0 )
813  {
814  outputRasterPtr->setValue( col + 1, line, 255, 1 );
815  }
816  else if( y > 0 )
817  {
818  outputRasterPtr->setValue( col + 1, line - 1, 255, 1 );
819  }
820  else
821  {
822  outputRasterPtr->setValue( col + 1, line + 1, 255, 1 );
823  }
824  }
825  else // x < 0
826  {
827  if( y == 0 )
828  {
829  outputRasterPtr->setValue( col - 1, line, 255, 1 );
830  }
831  else if( y > 0 )
832  {
833  outputRasterPtr->setValue( col - 1, line - 1, 255, 1 );
834  }
835  else
836  {
837  outputRasterPtr->setValue( col - 1, line + 1, 255, 1 );
838  }
839  }
840  }
841  }
842  }
843 
845  const te::rp::Matrix< double >& inputX,
846  const te::rp::Matrix< double >& inputY,
847  te::rp::Matrix< double > const * const/* backgroundDataPtr*/,
848  te::common::TaskProgress* progressPtr,
849  te::rp::Matrix< double >& outputX,
850  te::rp::Matrix< double >& outputY ) const
851  {
852  assert( inputX.getColumnsNumber() == inputY.getColumnsNumber() );
853  assert( inputX.getLinesNumber() == inputY.getLinesNumber() );
854 
855  const unsigned int nRows = inputX.getLinesNumber();
856  TERP_TRUE_OR_RETURN_FALSE( nRows > 8, "Invalid rows number" );
857 
858  const unsigned int nCols = inputX.getColumnsNumber();
859  TERP_TRUE_OR_RETURN_FALSE( nCols > 8, "Invalid columns number" );
860 
861  const unsigned int rowSizeBytes = sizeof( double ) * nCols;
862 
863  if( ! outputX.reset( nRows,nCols ) )
864  return false;
865  if( ! outputY.reset( nRows,nCols ) )
866  return false;
867 
868  std::unique_ptr< te::rp::Matrix< double > > xBuf1Ptr;
869  xBuf1Ptr.reset( new te::rp::Matrix< double >() );
870  if( ! xBuf1Ptr->reset( nRows,nCols ) )
871  return false;
872 
873  std::unique_ptr< te::rp::Matrix< double > > yBuf1Ptr;
874  yBuf1Ptr.reset( new te::rp::Matrix< double >() );
875  if( ! yBuf1Ptr->reset( nRows,nCols ) )
876  return false;
877 
878  std::unique_ptr< te::rp::Matrix< double > > xBuf2Ptr;
879  xBuf2Ptr.reset( new te::rp::Matrix< double >() );
880  if( ! xBuf2Ptr->reset( nRows,nCols ) )
881  return false;
882 
883  std::unique_ptr< te::rp::Matrix< double > > yBuf2Ptr;
884  yBuf2Ptr.reset( new te::rp::Matrix< double >() );
885  if( ! yBuf2Ptr->reset( nRows,nCols ) )
886  return false;
887 
888  std::unique_ptr< te::rp::Matrix< double > > magBuf1Ptr;
889  magBuf1Ptr.reset( new te::rp::Matrix< double >() );
890  if( ! magBuf1Ptr->reset( nRows,nCols ) )
891  return false;
892 
893  std::unique_ptr< te::rp::Matrix< double > > magBuf2Ptr;
894  magBuf2Ptr.reset( new te::rp::Matrix< double >() );
895  if( ! magBuf2Ptr->reset( nRows,nCols ) )
896  return false;
897  if( ! getMagnitude( inputX, inputY, *magBuf2Ptr ) ) return false;
898 
899  double currentIterationResidue = DBL_MAX;
900 
901  boost::mutex mutex;
902 
903  ApplyVecDiffusionThreadParams threadParams;
904  threadParams.m_initialXBufPtr = &inputX;
905  threadParams.m_initialYBufPtr = &inputY;
906  threadParams.m_currentIterationResiduePtr = &currentIterationResidue;
907  threadParams.m_mutexPtr = &mutex;
909 
910  const unsigned int threadsNumber = m_inputParameters.m_enableMultiThread ?
912  const unsigned int rowsPerThread = m_inputParameters.m_enableMultiThread ?
913  static_cast<const unsigned int>(std::ceil( (static_cast<double>(nRows - 8 )) / (static_cast<double>(threadsNumber)))) : nRows;
914 
915  unsigned int iteration = 0;
916 
917  while(
918  (
920  ?
922  :
923  true
924  )
925  &&
926  ( currentIterationResidue > m_inputParameters.m_diffusionThreshold )
927  )
928  {
929  if( progressPtr )
930  {
931  if( ! progressPtr->isActive() ) return false;
932  }
933 
934  currentIterationResidue = 0;
935 
936  if( iteration == 0 )
937  {
938  threadParams.m_inputMagBufPtr = magBuf2Ptr.get();
939  threadParams.m_inputBufXPtr = &inputX;
940  threadParams.m_inputBufYPtr = &inputY;
941  threadParams.m_outputMagBufPtr = magBuf1Ptr.get();
942  threadParams.m_outputBufXPtr = xBuf1Ptr.get();
943  threadParams.m_outputBufYPtr = yBuf1Ptr.get();
944  }
945  else
946  {
947  if( threadParams.m_outputBufXPtr == xBuf1Ptr.get() )
948  {
949  threadParams.m_inputMagBufPtr = magBuf1Ptr.get();
950  threadParams.m_inputBufXPtr = xBuf1Ptr.get();
951  threadParams.m_inputBufYPtr = yBuf1Ptr.get();
952  threadParams.m_outputMagBufPtr = magBuf2Ptr.get();
953  threadParams.m_outputBufXPtr = xBuf2Ptr.get();
954  threadParams.m_outputBufYPtr = yBuf2Ptr.get();
955  }
956  else
957  {
958  threadParams.m_inputMagBufPtr = magBuf2Ptr.get();
959  threadParams.m_inputBufXPtr = xBuf2Ptr.get();
960  threadParams.m_inputBufYPtr = yBuf2Ptr.get();
961  threadParams.m_outputMagBufPtr = magBuf1Ptr.get();
962  threadParams.m_outputBufXPtr = xBuf1Ptr.get();
963  threadParams.m_outputBufYPtr = yBuf1Ptr.get();
964  }
965  }
966 
967  memcpy( threadParams.m_outputMagBufPtr->operator[]( 0 ),
968  threadParams.m_inputMagBufPtr->operator[]( 0 ), rowSizeBytes );
969  memcpy( threadParams.m_outputMagBufPtr->operator[]( 1 ),
970  threadParams.m_inputMagBufPtr->operator[]( 1 ), rowSizeBytes );
971  memcpy( threadParams.m_outputMagBufPtr->operator[]( 2 ),
972  threadParams.m_inputMagBufPtr->operator[]( 2 ), rowSizeBytes );
973  memcpy( threadParams.m_outputMagBufPtr->operator[]( 3 ),
974  threadParams.m_inputMagBufPtr->operator[]( 3 ), rowSizeBytes );
975 
976  memcpy( threadParams.m_outputMagBufPtr->operator[]( nRows - 4 ),
977  threadParams.m_inputMagBufPtr->operator[]( nRows - 4 ), rowSizeBytes );
978  memcpy( threadParams.m_outputMagBufPtr->operator[]( nRows - 3 ),
979  threadParams.m_inputMagBufPtr->operator[]( nRows - 3 ), rowSizeBytes );
980  memcpy( threadParams.m_outputMagBufPtr->operator[]( nRows - 2 ),
981  threadParams.m_inputMagBufPtr->operator[]( nRows - 2 ), rowSizeBytes );
982  memcpy( threadParams.m_outputMagBufPtr->operator[]( nRows - 1 ),
983  threadParams.m_inputMagBufPtr->operator[]( nRows - 1 ), rowSizeBytes );
984 
985  memcpy( threadParams.m_outputBufXPtr->operator[]( 0 ),
986  threadParams.m_inputBufXPtr->operator[]( 0 ), rowSizeBytes );
987  memcpy( threadParams.m_outputBufXPtr->operator[]( 1 ),
988  threadParams.m_inputBufXPtr->operator[]( 1 ), rowSizeBytes );
989  memcpy( threadParams.m_outputBufXPtr->operator[]( 2 ),
990  threadParams.m_inputBufXPtr->operator[]( 2 ), rowSizeBytes );
991  memcpy( threadParams.m_outputBufXPtr->operator[]( 3 ),
992  threadParams.m_inputBufXPtr->operator[]( 3 ), rowSizeBytes );
993 
994  memcpy( threadParams.m_outputBufXPtr->operator[]( nRows - 4 ),
995  threadParams.m_inputBufXPtr->operator[]( nRows - 4 ), rowSizeBytes );
996  memcpy( threadParams.m_outputBufXPtr->operator[]( nRows - 3 ),
997  threadParams.m_inputBufXPtr->operator[]( nRows - 3 ), rowSizeBytes );
998  memcpy( threadParams.m_outputBufXPtr->operator[]( nRows - 2 ),
999  threadParams.m_inputBufXPtr->operator[]( nRows - 2 ), rowSizeBytes );
1000  memcpy( threadParams.m_outputBufXPtr->operator[]( nRows - 1 ),
1001  threadParams.m_inputBufXPtr->operator[]( nRows - 1 ), rowSizeBytes );
1002 
1003  memcpy( threadParams.m_outputBufYPtr->operator[]( 0 ),
1004  threadParams.m_inputBufYPtr->operator[]( 0 ), rowSizeBytes );
1005  memcpy( threadParams.m_outputBufYPtr->operator[]( 1 ),
1006  threadParams.m_inputBufYPtr->operator[]( 1 ), rowSizeBytes );
1007  memcpy( threadParams.m_outputBufYPtr->operator[]( 2 ),
1008  threadParams.m_inputBufYPtr->operator[]( 2 ), rowSizeBytes );
1009  memcpy( threadParams.m_outputBufYPtr->operator[]( 3 ),
1010  threadParams.m_inputBufYPtr->operator[]( 3 ), rowSizeBytes );
1011 
1012  memcpy( threadParams.m_outputBufYPtr->operator[]( nRows - 4 ),
1013  threadParams.m_inputBufYPtr->operator[]( nRows - 4 ), rowSizeBytes );
1014  memcpy( threadParams.m_outputBufYPtr->operator[]( nRows - 3 ),
1015  threadParams.m_inputBufYPtr->operator[]( nRows - 3 ), rowSizeBytes );
1016  memcpy( threadParams.m_outputBufYPtr->operator[]( nRows - 2 ),
1017  threadParams.m_inputBufYPtr->operator[]( nRows - 2 ), rowSizeBytes );
1018  memcpy( threadParams.m_outputBufYPtr->operator[]( nRows - 1 ),
1019  threadParams.m_inputBufYPtr->operator[]( nRows - 1 ), rowSizeBytes );
1020 
1021  if( threadsNumber )
1022  {
1023  unsigned int startingRow = 4;
1024  std::vector< ApplyVecDiffusionThreadParams > threadsParamesVec;
1025  threadsParamesVec.resize( threadsNumber, threadParams );
1026  boost::thread_group threads;
1027 
1028  for( unsigned int threadIdx = 0 ; threadIdx < threadsNumber ;
1029  ++threadIdx )
1030  {
1031  threadsParamesVec[ threadIdx ].m_firstRowIdx = startingRow;
1032  threadsParamesVec[ threadIdx ].m_lastRowIdx = std::min( nRows - 5,
1033  startingRow + rowsPerThread - 1 );
1034  threads.add_thread( new boost::thread( applyVecDiffusionThreadEntry,
1035  &threadsParamesVec[ threadIdx ] ) );
1036  startingRow += rowsPerThread;
1037  }
1038 
1039  threads.join_all();
1040  }
1041  else
1042  {
1043  threadParams.m_firstRowIdx = 4;
1044  threadParams.m_lastRowIdx = nRows - 5;
1045  applyVecDiffusionThreadEntry( &threadParams );
1046  };
1047 
1048 // if( ( backgroundDataPtr != 0 ) && ( ( iteration < 10 ) || ( iteration % 100 == 0 ) ) )
1049 // {
1050 // CreateRasterFileFromMatrix( *threadParams.m_inputBufXPtr, true,
1051 // boost::lexical_cast< std::string >( iteration ) + "_diffusedInX.tif" );
1052 // CreateRasterFileFromMatrix( *threadParams.m_inputBufYPtr, true,
1053 // boost::lexical_cast< std::string >( iteration ) + "_diffusedInY.tif");
1054 // createTifFromVecField( *threadParams.m_inputBufXPtr, *threadParams.m_inputBufYPtr,
1055 // backgroundDataPtr, 3,
1056 // boost::lexical_cast< std::string >( iteration ) + "_diffusedInVecs");
1057 // CreateRasterFileFromMatrix( *threadParams.m_inputMagBufPtr, true,
1058 // boost::lexical_cast< std::string >( iteration ) + "_diffusedInMag.tif");
1059 //
1060 // CreateRasterFileFromMatrix( *threadParams.m_outputBufXPtr, true,
1061 // boost::lexical_cast< std::string >( iteration ) + "_diffusedOutX.tif" );
1062 // CreateRasterFileFromMatrix( *threadParams.m_outputBufYPtr, true,
1063 // boost::lexical_cast< std::string >( iteration ) + "_diffusedOutY.tif");
1064 // createTifFromVecField( *threadParams.m_outputBufXPtr, *threadParams.m_outputBufYPtr,
1065 // backgroundDataPtr, 3,
1066 // boost::lexical_cast< std::string >( iteration ) + "_diffusedOutVecs");
1067 // CreateRasterFileFromMatrix( *threadParams.m_outputMagBufPtr, true,
1068 // boost::lexical_cast< std::string >( iteration ) + "_diffusedOutMag.tif");
1069 // }
1070 //
1071 // std::cout << std::endl << "currentIteration=" << iteration << std::endl;
1072 // std::cout << std::endl << "currentIterationResidue=" << currentIterationResidue << std::endl;
1073 
1074  ++iteration;
1075  }
1076 
1077  for( unsigned int row = 0 ; row < nRows ; ++row )
1078  {
1079  memcpy( outputX[ row ], threadParams.m_outputBufXPtr->operator[]( row ),
1080  rowSizeBytes );
1081  memcpy( outputY[ row ], threadParams.m_outputBufYPtr->operator[]( row ),
1082  rowSizeBytes );
1083  }
1084 
1085  return true;
1086  }
1087 
1089  {
1090 // const te::rp::Matrix< double >& initBufX = *(paramsPtr->m_initialXBufPtr);
1091 // const te::rp::Matrix< double >& initBufY = *(paramsPtr->m_initialYBufPtr);
1092  const te::rp::Matrix< double >& iBufMag = *(paramsPtr->m_inputMagBufPtr);
1093  const te::rp::Matrix< double >& iBufX = *(paramsPtr->m_inputBufXPtr);
1094  const te::rp::Matrix< double >& iBufY = *(paramsPtr->m_inputBufYPtr);
1095  te::rp::Matrix< double >& oMagBuf = *(paramsPtr->m_outputMagBufPtr);
1096  te::rp::Matrix< double >& oBufX = *(paramsPtr->m_outputBufXPtr);
1097  te::rp::Matrix< double >& oBufY = *(paramsPtr->m_outputBufYPtr);
1098  const double& diffusionRegularization = paramsPtr->m_diffusionRegularization;
1099  const double complementDiffReg = 1.0 - diffusionRegularization;
1100  const unsigned int nCols = iBufX.getColumnsNumber();
1101  const unsigned int rowSizeBytes = sizeof( double ) * nCols;
1102  unsigned int row = 0;
1103  unsigned int col = 0;
1104 
1105  boost::scoped_array< double > bufMagRow0Handler( new double[ nCols ] );
1106  boost::scoped_array< double > bufMagRow1Handler( new double[ nCols ] );
1107  boost::scoped_array< double > bufMagRow2Handler( new double[ nCols ] );
1108  boost::scoped_array< double > bufXRow0Handler( new double[ nCols ] );
1109  boost::scoped_array< double > bufXRow1Handler( new double[ nCols ] );
1110  boost::scoped_array< double > bufXRow2Handler( new double[ nCols ] );
1111  boost::scoped_array< double > bufYRow0Handler( new double[ nCols ] );
1112  boost::scoped_array< double > bufYRow1Handler( new double[ nCols ] );
1113  boost::scoped_array< double > bufYRow2Handler( new double[ nCols ] );
1114 /* boost::scoped_array< double > bufInitXRow0Handler( new double[ nCols ] );
1115  boost::scoped_array< double > bufInitXRow1Handler( new double[ nCols ] );
1116  boost::scoped_array< double > bufInitXRow2Handler( new double[ nCols ] );
1117  boost::scoped_array< double > bufInitYRow0Handler( new double[ nCols ] );
1118  boost::scoped_array< double > bufInitYRow1Handler( new double[ nCols ] );
1119  boost::scoped_array< double > bufInitYRow2Handler( new double[ nCols ] );
1120  double* bufferInitX[ 3 ];
1121  double* bufferInitY[ 3 ]; */
1122  double* bufferMag[ 3 ];
1123  double* bufferX[ 3 ];
1124  double* bufferY[ 3 ];
1125  bufferMag[ 0 ] = bufMagRow0Handler.get();
1126  bufferMag[ 1 ] = bufMagRow1Handler.get();
1127  bufferMag[ 2 ] = bufMagRow2Handler.get();
1128 /* bufferInitX[ 0 ] = bufInitXRow0Handler.get();
1129  bufferInitX[ 1 ] = bufInitXRow1Handler.get();
1130  bufferInitX[ 2 ] = bufInitXRow2Handler.get();
1131  bufferInitY[ 0 ] = bufInitYRow0Handler.get();
1132  bufferInitY[ 1 ] = bufInitYRow1Handler.get();
1133  bufferInitY[ 2 ] = bufInitYRow2Handler.get(); */
1134  bufferX[ 0 ] = bufXRow0Handler.get();
1135  bufferX[ 1 ] = bufXRow1Handler.get();
1136  bufferX[ 2 ] = bufXRow2Handler.get();
1137  bufferY[ 0 ] = bufYRow0Handler.get();
1138  bufferY[ 1 ] = bufYRow1Handler.get();
1139  bufferY[ 2 ] = bufYRow2Handler.get();
1140 
1141  // Loading the two initial rows
1142 
1143  paramsPtr->m_mutexPtr->lock();
1144 
1145  memcpy( bufferMag[ 1 ], iBufMag[ paramsPtr->m_firstRowIdx - 1 ],
1146  rowSizeBytes );
1147  memcpy( bufferMag[ 2 ], iBufMag[ paramsPtr->m_firstRowIdx ],
1148  rowSizeBytes );
1149 
1150 // memcpy( bufferInitX[ 1 ], initBufX[ paramsPtr->m_firstRowIdx - 1 ],
1151 // rowSizeBytes );
1152 // memcpy( bufferInitX[ 2 ], initBufX[ paramsPtr->m_firstRowIdx ],
1153 // rowSizeBytes );
1154 //
1155 // memcpy( bufferInitY[ 1 ], initBufY[ paramsPtr->m_firstRowIdx - 1 ],
1156 // rowSizeBytes );
1157 // memcpy( bufferInitY[ 2 ], initBufY[ paramsPtr->m_firstRowIdx ],
1158 // rowSizeBytes );
1159 
1160  memcpy( bufferX[ 1 ], iBufX[ paramsPtr->m_firstRowIdx - 1 ],
1161  rowSizeBytes );
1162  memcpy( bufferX[ 2 ], iBufX[ paramsPtr->m_firstRowIdx ],
1163  rowSizeBytes );
1164 
1165  memcpy( bufferY[ 1 ], iBufY[ paramsPtr->m_firstRowIdx - 1 ],
1166  rowSizeBytes );
1167  memcpy( bufferY[ 2 ], iBufY[ paramsPtr->m_firstRowIdx ],
1168  rowSizeBytes );
1169 
1170  paramsPtr->m_mutexPtr->unlock();
1171 
1172  const unsigned int rowsBound = paramsPtr->m_lastRowIdx + 2;
1173  const unsigned int colsBound = nCols - 4;
1174 /* double centerInitX = 0;
1175  double centerInitY = 0; */
1176  double centerDiffX = 0;
1177  double centerDiffY = 0;
1178  double centerX = 0;
1179  double centerY = 0;
1180  double centerMag = 0;
1181  double newCenterX = 0;
1182  double newCenterY = 0;
1183  double* rowPtr = nullptr;
1184  unsigned int prevRow = 0;
1185  unsigned int prevCol = 0;
1186  unsigned int nextCol = 0;
1187  double currentIterationResidue = 0;
1188  double validNeigborsNumber = 0.0;
1189 
1190  boost::scoped_array< double > outRowMagBuffHandler( new double[ nCols ] );
1191  double* outRowMagBuff = outRowMagBuffHandler.get();
1192 
1193  boost::scoped_array< double > outRowXBuffHandler( new double[ nCols ] );
1194  double* outRowXBuff = outRowXBuffHandler.get();
1195 
1196  boost::scoped_array< double > outRowYBuffHandler( new double[ nCols ] );
1197  double* outRowYBuff = outRowYBuffHandler.get();
1198 
1199  for( row = ( paramsPtr->m_firstRowIdx + 1 ) ; row < rowsBound ; ++row )
1200  {
1201  prevRow = row - 1;
1202 
1203  // Rolling-up the internal buffers
1204 
1205 /* rowPtr = bufferInitX[ 0 ];
1206  bufferInitX[ 0 ] = bufferInitX[ 1 ];
1207  bufferInitX[ 1 ] = bufferInitX[ 2 ];
1208  bufferInitX[ 2 ] = rowPtr;
1209 
1210  rowPtr = bufferInitY[ 0 ];
1211  bufferInitY[ 0 ] = bufferInitY[ 1 ];
1212  bufferInitY[ 1 ] = bufferInitY[ 2 ];
1213  bufferInitY[ 2 ] = rowPtr; */
1214 
1215  rowPtr = bufferMag[ 0 ];
1216  bufferMag[ 0 ] = bufferMag[ 1 ];
1217  bufferMag[ 1 ] = bufferMag[ 2 ];
1218  bufferMag[ 2 ] = rowPtr;
1219 
1220  rowPtr = bufferX[ 0 ];
1221  bufferX[ 0 ] = bufferX[ 1 ];
1222  bufferX[ 1 ] = bufferX[ 2 ];
1223  bufferX[ 2 ] = rowPtr;
1224 
1225  rowPtr = bufferY[ 0 ];
1226  bufferY[ 0 ] = bufferY[ 1 ];
1227  bufferY[ 1 ] = bufferY[ 2 ];
1228  bufferY[ 2 ] = rowPtr;
1229 
1230  // Getting a new line
1231 
1232  paramsPtr->m_mutexPtr->lock();
1233 /* memcpy( bufferInitX[ 2 ], initBufX[ row ], rowSizeBytes );
1234  memcpy( bufferInitY[ 2 ], initBufY[ row ], rowSizeBytes ); */
1235  memcpy( bufferMag[ 2 ], iBufMag[ row ], rowSizeBytes );
1236  memcpy( bufferX[ 2 ], iBufX[ row ], rowSizeBytes );
1237  memcpy( bufferY[ 2 ], iBufY[ row ], rowSizeBytes );
1238  paramsPtr->m_mutexPtr->unlock();
1239 
1240  // Diffusing the buffer center line
1241 
1242  for( col = 4 ; col < colsBound ; ++col )
1243  {
1244  prevCol = col - 1;
1245  nextCol = col + 1;
1246 
1247 // centerInitX = bufferInitX[ 1 ][ col ];
1248 // centerInitY = bufferInitY[ 1 ][ col ];
1249 
1250  centerMag = bufferMag[ 1 ][ col ];
1251  centerX = bufferX[ 1 ][ col ];
1252  centerY = bufferY[ 1 ][ col ];
1253 
1254  validNeigborsNumber = 0.0;
1255  newCenterX = 0;
1256  newCenterY = 0;
1257 
1258  DIFFUSENEIGHBOR( 0, prevCol );
1259  DIFFUSENEIGHBOR( 0, col );
1260  DIFFUSENEIGHBOR( 0, nextCol );
1261  DIFFUSENEIGHBOR( 1, prevCol );
1262  DIFFUSENEIGHBOR( 1, nextCol );
1263  DIFFUSENEIGHBOR( 2, prevCol );
1264  DIFFUSENEIGHBOR( 2, col );
1265  DIFFUSENEIGHBOR( 2, nextCol );
1266 
1267  if( validNeigborsNumber != 0.0 )
1268  {
1269  newCenterX /= validNeigborsNumber;
1270  newCenterY /= validNeigborsNumber;
1271 
1272  newCenterX = ( newCenterX * diffusionRegularization ) +
1273  ( centerX * complementDiffReg );
1274  newCenterY = ( newCenterY * diffusionRegularization ) +
1275  ( centerY * complementDiffReg );
1276 
1277  centerDiffX = centerX - newCenterX;
1278  centerDiffY = centerY - newCenterY;
1279 
1280  if( centerDiffX != 0.0 )
1281  {
1282  if( centerX == 0.0 )
1283  {
1284  currentIterationResidue = std::max( currentIterationResidue, 1.0 );
1285  }
1286  else
1287  {
1288  currentIterationResidue =
1289  std::max(
1290  currentIterationResidue
1291  ,
1292  std::abs( centerDiffX / centerX )
1293  );
1294  }
1295  }
1296 
1297  if( centerDiffY != 0.0 )
1298  {
1299  if( centerY == 0.0 )
1300  {
1301  currentIterationResidue = std::max( currentIterationResidue, 1.0 );
1302  }
1303  else
1304  {
1305  currentIterationResidue =
1306  std::max(
1307  currentIterationResidue
1308  ,
1309  std::abs( centerDiffY / centerY )
1310  );
1311  }
1312  }
1313 
1314  outRowXBuff[ col ] = newCenterX;
1315  outRowYBuff[ col ] = newCenterY;
1316  outRowMagBuff[ col ] = std::sqrt( ( newCenterX * newCenterX ) + ( newCenterY *
1317  newCenterY ) );
1318  }
1319  else
1320  {
1321  outRowXBuff[ col ] = centerX;
1322  outRowYBuff[ col ] = centerY;
1323  outRowMagBuff[ col ] = centerMag;
1324  }
1325  }
1326 
1327  // copying the result to output
1328 
1329  paramsPtr->m_mutexPtr->lock();
1330 
1331  memcpy( oMagBuf[ prevRow ], outRowMagBuff, rowSizeBytes );
1332  memcpy( oBufX[ prevRow ], outRowXBuff, rowSizeBytes );
1333  memcpy( oBufY[ prevRow ], outRowYBuff, rowSizeBytes );
1334 
1335  oMagBuf[ prevRow ][ 0 ] = iBufMag[ 1 ][ 0 ];
1336  oMagBuf[ prevRow ][ 1 ] = iBufMag[ 1 ][ 1 ];
1337  oMagBuf[ prevRow ][ 2 ] = iBufMag[ 1 ][ 2 ];
1338  oMagBuf[ prevRow ][ 3 ] = iBufMag[ 1 ][ 3 ];
1339  oMagBuf[ prevRow ][ colsBound ] = iBufMag[ 1 ][ colsBound ];
1340  oMagBuf[ prevRow ][ colsBound + 1 ] = iBufMag[ 1 ][ colsBound + 1 ];
1341  oMagBuf[ prevRow ][ colsBound + 2 ] = iBufMag[ 1 ][ colsBound + 2 ];
1342  oMagBuf[ prevRow ][ colsBound + 3 ] = iBufMag[ 1 ][ colsBound + 3 ];
1343 
1344  oBufX[ prevRow ][ 0 ] = bufferX[ 1 ][ 0 ];
1345  oBufX[ prevRow ][ 1 ] = bufferX[ 1 ][ 1 ];
1346  oBufX[ prevRow ][ 2 ] = bufferX[ 1 ][ 2 ];
1347  oBufX[ prevRow ][ 3 ] = bufferX[ 1 ][ 3 ];
1348  oBufX[ prevRow ][ colsBound ] = bufferX[ 1 ][ colsBound ];
1349  oBufX[ prevRow ][ colsBound + 1 ] = bufferX[ 1 ][ colsBound + 1 ];
1350  oBufX[ prevRow ][ colsBound + 2 ] = bufferX[ 1 ][ colsBound + 2 ];
1351  oBufX[ prevRow ][ colsBound + 3 ] = bufferX[ 1 ][ colsBound + 3 ];
1352 
1353  oBufY[ prevRow ][ 0 ] = bufferY[ 1 ][ 0 ];
1354  oBufY[ prevRow ][ 1 ] = bufferY[ 1 ][ 1 ];
1355  oBufY[ prevRow ][ 2 ] = bufferY[ 1 ][ 2 ];
1356  oBufY[ prevRow ][ 3 ] = bufferY[ 1 ][ 3 ];
1357  oBufY[ prevRow ][ colsBound ] = bufferY[ 1 ][ colsBound ];
1358  oBufY[ prevRow ][ colsBound + 1 ] = bufferY[ 1 ][ colsBound + 1 ];
1359  oBufY[ prevRow ][ colsBound + 2 ] = bufferY[ 1 ][ colsBound + 2 ];
1360  oBufY[ prevRow ][ colsBound + 3 ] = bufferY[ 1 ][ colsBound + 3 ];
1361 
1362  (*paramsPtr->m_currentIterationResiduePtr) =
1363  std::max( (*paramsPtr->m_currentIterationResiduePtr),
1364  currentIterationResidue );
1365 
1366  paramsPtr->m_mutexPtr->unlock();
1367  }
1368  }
1369 
1371  const te::rp::Matrix< double >& inputX,
1372  const te::rp::Matrix< double >& inputY,
1373  const te::rp::Matrix< double >& edgeStrengthMap,
1374  te::rp::Matrix< double >& skelMap ) const
1375  {
1376  assert( inputX.getColumnsNumber() == inputY.getColumnsNumber() );
1377  assert( inputX.getLinesNumber() == inputY.getLinesNumber() );
1378 
1379  const unsigned int nRows = inputX.getLinesNumber();
1380  TERP_TRUE_OR_RETURN_FALSE( nRows > 2, "Invalid rows number" );
1381 
1382  const unsigned int nCols = inputX.getColumnsNumber();
1383  TERP_TRUE_OR_RETURN_FALSE( nCols > 2, "Invalid columns number" );
1384 
1385  if( ! skelMap.reset( nRows,nCols ) )
1386  return false;
1387 
1388  const unsigned int lastRowIdx = nRows - 1;
1389  const unsigned int lastColIdx = nCols - 1;
1390  unsigned int row = 0;
1391  unsigned int col = 0;
1392  unsigned int nextRow = 0;
1393  unsigned int nextCol = 0;
1394  unsigned int prevRow = 0;
1395  unsigned int prevCol = 0;
1396  double centerX = 0;
1397  double centerY = 0;
1398  double neiX = 0;
1399  double neiY = 0;
1400  double diffX = 0;
1401  double diffY = 0;
1402  double diffMag = 0;
1403  double strength = 0;
1404  double minStrength = DBL_MAX;
1405  double maxStrength = -1.0 * DBL_MAX;
1406 
1407  for( row = 0 ; row < nRows ; ++row )
1408  {
1409  skelMap[ row ][ 0 ] = 0;
1410  skelMap[ row ][ lastColIdx ] = 0;
1411  }
1412 
1413  for( col = 0 ; col < nCols ; ++col )
1414  {
1415  skelMap[ 0 ][ col ] = 0;
1416  skelMap[ lastRowIdx ][ col ] = 0;
1417  }
1418 
1419  for( row = 1 ; row < lastRowIdx ; ++row )
1420  {
1421  prevRow = row - 1;
1422  nextRow = row + 1;
1423 
1424  for( col = 1 ; col < lastColIdx ; ++col )
1425  {
1426  prevCol = col - 1;
1427  nextCol = col + 1;
1428 
1429  centerX = inputX[ row ][ col ];
1430  centerY = inputY[ row ][ col ];
1431 
1432  strength = 0;
1433 
1434  SKELSTRENGTHNEIGHBOR( prevRow, prevCol )
1435  SKELSTRENGTHNEIGHBOR( prevRow, col )
1436  SKELSTRENGTHNEIGHBOR( prevRow, nextCol )
1437  SKELSTRENGTHNEIGHBOR( row, prevCol )
1438  SKELSTRENGTHNEIGHBOR( row, nextCol )
1439  SKELSTRENGTHNEIGHBOR( nextRow, prevCol )
1440  SKELSTRENGTHNEIGHBOR( nextRow, col )
1441  SKELSTRENGTHNEIGHBOR( nextRow, nextCol )
1442 
1443  strength /= 8.0;
1444  strength = std::max( 0.0, strength );
1445 
1446  skelMap[ row ][ col ] = strength;
1447 
1448  if( minStrength > strength ) minStrength = strength;
1449  if( maxStrength < strength ) maxStrength = strength;
1450  }
1451  }
1452 
1453  const double gain = ( minStrength == maxStrength ) ? 0.0 :
1454  ( 1.0 / ( maxStrength - minStrength ) );
1455 
1456  for( row = 1 ; row < lastRowIdx ; ++row )
1457  {
1458  for( col = 1 ; col < lastColIdx ; ++col )
1459  {
1460  strength = skelMap[ row ][ col ];
1461  strength -= minStrength;
1462  strength *= gain;
1463  strength = ( strength + ( 1.0 - edgeStrengthMap[ row ][ col ] ) ) / 2.0;
1464  skelMap[ row ][ col ] = strength;
1465  }
1466  }
1467 
1468  return true;
1469  }
1470 
1471  } // end namespace rp
1472 
1473 
1474 } // end namespace te
1475 
bool getMagnitude(const te::rp::Matrix< double > &xMap, const te::rp::Matrix< double > &yMap, te::rp::Matrix< MatrixElementT > &magnitude) const
Generate the magnitude map from the input vectors.
Definition: Skeleton.h:313
unsigned int band
te::rp::Matrix< double > const * m_initialYBufPtr
A pointer to the input buffer initial Y component.
Definition: Skeleton.h:173
Index into a lookup table.
#define SKELSTRENGTHNEIGHBOR(neighborRow, neighborCol)
Definition: Skeleton.cpp:48
std::unique_ptr< te::rst::Raster > m_outputRasterPtr
The generated output registered raster.
Definition: Skeleton.h:128
double * m_currentIterationResiduePtr
A pointer the the current iteration residue;.
Definition: Skeleton.h:183
A raster band description.
Definition: BandProperty.h:61
Skeleton::InputParameters m_inputParameters
Input execution parameters.
Definition: Skeleton.h:215
Skeleton output parameters.
Definition: Skeleton.h:120
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
te::rp::Matrix< double > const * m_inputMagBufPtr
A pointer to the input magnitude buffer.
Definition: Skeleton.h:174
bool m_isInitialized
Tells if this instance is initialized.
Definition: Skeleton.h:217
void reset() _NOEXCEPT_OP(false)
Clear all internal allocated resources and reset the parameters instance to its initial state...
Definition: Skeleton.cpp:80
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
Raster Processing algorithm output parameters base interface.
double m_diffusionRegularization
A regularization parameter to control the variation from one iteration to the next one (higher values...
Definition: Skeleton.h:90
bool loadData(te::rp::Matrix< double > &rasterData) const
Load data from the input raster.
Definition: Skeleton.cpp:441
Red channel color interpretation.
std::string m_rType
Output raster data source type (as described in te::raster::RasterFactory ).
Definition: Skeleton.h:124
#define DIFFUSENEIGHBOR(neighborRow, neighborCol)
Definition: Skeleton.cpp:40
bool execute(AlgorithmOutputParameters &outputParams) _NOEXCEPT_OP(false)
Executes the algorithm using the supplied parameters.
Definition: Skeleton.cpp:162
#define _NOEXCEPT_OP(x)
double m_diffusionRegularization
The diffusion regularization parameter.
Definition: Skeleton.h:184
double m_diffusionThreshold
A threshold over the residue from one iteration to another, if the residue drops below this value the...
Definition: Skeleton.h:88
bool isActive() const
Verify if the task is active.
te::rp::Matrix< double > const * m_initialXBufPtr
A pointer to the input buffer initial X component.
Definition: Skeleton.h:172
boost::mutex * m_mutexPtr
A pointer to the sync mutex.
Definition: Skeleton.h:180
bool applyMeanSmooth(const te::rp::Matrix< MatrixElementT > &input, te::rp::Matrix< MatrixElementT > &output) const
Apply a mean filter.
Definition: Skeleton.h:247
#define TERP_TRUE_OR_RETURN_FALSE(value, message)
Checks if value is true. For false values a warning message will be logged and a return of context wi...
Definition: Macros.h:185
unsigned int line
te::common::AccessPolicy getAccessPolicy() const
Returns the raster access policy.
unsigned int unsigned int nCols
const InputParameters & operator=(const InputParameters &params)
Definition: Skeleton.cpp:93
unsigned int m_inputRasterBand
Bands to process from the input raster.
Definition: Skeleton.h:84
TECOMMONEXPORT unsigned int GetPhysProcNumber()
Returns the number of physical processors.
te::rst::Raster const * m_inputMaskRasterPtr
A pointer to an input raster (where pixels with zero velues will be ignored) or an null pointer if no...
Definition: Skeleton.h:86
bool createSkeletonStrengthMap(const te::rp::Matrix< double > &inputX, const te::rp::Matrix< double > &inputY, const te::rp::Matrix< double > &edgeStrengthMap, te::rp::Matrix< double > &skelMap) const
Create a skeleton strength map.
Definition: Skeleton.cpp:1370
bool getEdgeStrengthMap(const te::rp::Matrix< double > &inputMap, te::rp::Matrix< double > &edgeStrengthMap) const
Create an Edge strenght Map from the input data.
Definition: Skeleton.cpp:577
unsigned int getNumberOfRows() const
Returns the raster number of rows.
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
unsigned int getColumnsNumber() const
The number of current matrix columns.
Definition: Matrix.h:798
unsigned int m_firstRowIdx
First row to process.
Definition: Skeleton.h:181
bool applyVecDiffusion(const te::rp::Matrix< double > &inputX, const te::rp::Matrix< double > &inputY, te::rp::Matrix< double > const *const, te::common::TaskProgress *progressPtr, te::rp::Matrix< double > &outputX, te::rp::Matrix< double > &outputY) const
Apply a vector diffusion over the given vector field.
Definition: Skeleton.cpp:844
BandProperty * getProperty()
Returns the band property.
AbstractParameters * clone() const
Create a clone copy of this instance.
Definition: Skeleton.cpp:150
URI C++ Library.
Definition: Attributes.h:37
te::rp::Matrix< double > const * m_inputBufXPtr
A pointer to the input buffer X component.
Definition: Skeleton.h:175
te::rp::Matrix< double > * m_outputBufXPtr
A pointer to the output buffer X component.
Definition: Skeleton.h:178
void reset() _NOEXCEPT_OP(false)
Clear all internal allocated objects and reset the algorithm to its initial state.
Definition: Skeleton.cpp:362
A raster band description.
unsigned int m_diffusionMaxIterations
The maximum number of iterations to perform (zero: no iterations limit).
Definition: Skeleton.h:92
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
te::rp::Matrix< double > const * m_inputBufYPtr
A pointer to the input buffer Y component.
Definition: Skeleton.h:176
std::map< std::string, std::string > m_rInfo
The necessary information to create the output rasters (as described in te::raster::RasterFactory).
Definition: Skeleton.h:126
Grid * getGrid()
It returns the raster grid.
bool m_enableProgress
Enable/Disable the progress interface (default:false).
Definition: Skeleton.h:98
unsigned int m_lastRowIdx
Last row to process.
Definition: Skeleton.h:182
bool getGradientMaps(const te::rp::Matrix< double > &inputData, const bool unitVectors, te::rp::Matrix< double > &gradXMap, te::rp::Matrix< double > &gradYMap) const
Create an gradient maps from the input image.
Definition: Skeleton.cpp:478
const OutputParameters & operator=(const OutputParameters &params)
Definition: Skeleton.cpp:139
void reset()
Reset (clear) the active instance data.
Definition: Matrix.h:502
static void applyVecDiffusionThreadEntry(ApplyVecDiffusionThreadParams *paramsPtr)
Vector diffusion thread entry.
Definition: Skeleton.cpp:1088
bool isInitialized() const
Returns true if the algorithm instance is initialized and ready for execution.
Definition: Skeleton.cpp:436
Abstract parameters base interface.
te::rp::Matrix< double > * m_outputMagBufPtr
A pointer to the output magnitude buffer.
Definition: Skeleton.h:177
double m_skeletonThreshold
A threshold to select those pixels as being part of the final skeleton - valid range [0...
Definition: Skeleton.h:96
te::rst::Raster const * m_inputRasterPtr
Input raster.
Definition: Skeleton.h:82
AbstractParameters * clone() const
Create a clone copy of this instance.
Definition: Skeleton.cpp:111
bool m_enableMultiThread
Enable (true) the use of threads.
Definition: Skeleton.h:94
static Raster * make()
It creates and returns an empty raster with default raster driver.
void createTifFromVecField(const te::rp::Matrix< double > &inputVecFieldX, const te::rp::Matrix< double > &inputVecFieldY, te::rp::Matrix< double > const *const backGroundMapPtr, const unsigned int vecPixelStep, const std::string &tifFileName) const
Create a tiff file from a vector field.
Definition: Skeleton.cpp:698
Raster Processing algorithm input parameters base interface.
Raster Processing functions.
bool initialize(const AlgorithmInputParameters &inputParams) _NOEXCEPT_OP(false)
Initialize the algorithm instance making it ready for execution.
Definition: Skeleton.cpp:370
virtual void reset() _NOEXCEPT_OP(false)
Clear all internal allocated objects and reset the algorithm to its initial state.
Blue channel color interpretation.
A rectified grid is the spatial support for raster data.
Definition: raster/Grid.h:68
Green channel color interpretation.
#define TERP_INSTANCE_TRUE_OR_RETURN_FALSE(value, message)
Checks if value is true. For false values a warning message will be logged, the current instance erro...
Definition: Macros.h:200
void reset() _NOEXCEPT_OP(false)
Clear all internal allocated resources and reset the parameters instance to its initial state...
Definition: Skeleton.cpp:132
unsigned int nLines
unsigned int getLinesNumber() const
The number of current matrix lines.
Definition: Matrix.h:791
unsigned int col
#define TERP_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:150
Skeleton input parameters.
Definition: Skeleton.h:78
Creation of skeleton imagems.
virtual void getValue(unsigned int c, unsigned int r, double &value) const =0
Returns the cell attribute value.
te::rp::Matrix< double > * m_outputBufYPtr
A pointer to the output buffer X component.
Definition: Skeleton.h:179