1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
/*=========================================================================
*
* Copyright Insight Software Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#ifndef itkParabolicUtils_h
#define itkParabolicUtils_h
#include <itkArray.h>
#include "itkProgressReporter.h"
namespace itk
{
template <typename LineBufferType, typename RealType, typename TInputPixel, bool doDilate>
void
DoLine(LineBufferType & LineBuf, LineBufferType & tmpLineBuf, const RealType magnitude)
{
static constexpr RealType extreme =
doDilate ? NumericTraits<TInputPixel>::NonpositiveMin() : NumericTraits<TInputPixel>::max();
// contact point algorithm
long koffset = 0, newcontact = 0; // how far away the search starts.
const long LineLength = LineBuf.size();
// negative half of the parabola
for (long pos = 0; pos < LineLength; ++pos)
{
RealType BaseVal = extreme; // the base value for comparison
for (long krange = koffset; krange <= 0; ++krange)
{
// difference needs to be paramaterised
RealType T = LineBuf[pos + krange] - magnitude * krange * krange;
// switch on template parameter - hopefully gets optimized away.
if (doDilate ? (T >= BaseVal) : (T <= BaseVal))
{
BaseVal = T;
newcontact = krange;
}
}
tmpLineBuf[pos] = BaseVal;
koffset = newcontact - 1;
}
// positive half of parabola
koffset = newcontact = 0;
for (long pos = LineLength - 1; pos >= 0; pos--)
{
RealType BaseVal = extreme; // the base value for comparison
for (long krange = koffset; krange >= 0; krange--)
{
RealType T = tmpLineBuf[pos + krange] - magnitude * krange * krange;
if (doDilate ? (T >= BaseVal) : (T <= BaseVal))
{
BaseVal = T;
newcontact = krange;
}
}
LineBuf[pos] = BaseVal;
koffset = newcontact + 1;
}
}
template <typename TInIter,
typename TOutIter,
typename RealType,
typename TInputPixel,
typename OutputPixelType,
bool doDilate>
void
doOneDimension(TInIter & inputIterator,
TOutIter & outputIterator,
ProgressReporter & progress,
const long LineLength,
const unsigned direction,
const bool m_UseImageSpacing,
const RealType image_scale,
const RealType Sigma)
{
// using LineBufferType = typename std::vector<RealType>;
// message from M.Starring suggested performance gain using Array
// instead of std::vector.
using LineBufferType = typename itk::Array<RealType>;
RealType iscale = 1.0;
if (m_UseImageSpacing)
{
iscale = image_scale;
}
constexpr int magnitudeSign = doDilate ? 1 : -1;
const RealType magnitude = magnitudeSign * 1.0 / (2.0 * Sigma / (iscale * iscale));
LineBufferType LineBuf(LineLength);
LineBufferType tmpLineBuf(LineLength);
inputIterator.SetDirection(direction);
outputIterator.SetDirection(direction);
inputIterator.GoToBegin();
outputIterator.GoToBegin();
while (!inputIterator.IsAtEnd() && !outputIterator.IsAtEnd())
{
// process this direction
// fetch the line into the buffer - this methodology is like
// the gaussian filters
unsigned int i = 0;
while (!inputIterator.IsAtEndOfLine())
{
LineBuf[i++] = static_cast<RealType>(inputIterator.Get());
++inputIterator;
}
DoLine<LineBufferType, RealType, TInputPixel, doDilate>(LineBuf, tmpLineBuf, magnitude);
// copy the line back
unsigned int j = 0;
while (!outputIterator.IsAtEndOfLine())
{
outputIterator.Set(static_cast<OutputPixelType>(LineBuf[j++]));
++outputIterator;
}
// now onto the next line
inputIterator.NextLine();
outputIterator.NextLine();
progress.CompletedPixel();
}
}
} // namespace itk
#endif
|