[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]

details vigra/transformimage.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    ( Version 1.3.2, Jan 27 2005 )                                    */
00008 /*    You may use, modify, and distribute this software according       */
00009 /*    to the terms stated in the LICENSE file included in               */
00010 /*    the VIGRA distribution.                                           */
00011 /*                                                                      */
00012 /*    The VIGRA Website is                                              */
00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00014 /*    Please direct questions, bug reports, and contributions to        */
00015 /*        koethe@informatik.uni-hamburg.de                              */
00016 /*                                                                      */
00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
00020 /*                                                                      */
00021 /************************************************************************/
00022 
00023 
00024 #ifndef VIGRA_TRANSFORMIMAGE_HXX
00025 #define VIGRA_TRANSFORMIMAGE_HXX
00026 
00027 #include "vigra/utilities.hxx"
00028 #include "vigra/numerictraits.hxx"
00029 #include "vigra/iteratortraits.hxx"
00030 #include "vigra/rgbvalue.hxx"
00031 #include "vigra/functortraits.hxx"
00032 
00033 namespace vigra {
00034 
00035 /** \addtogroup TransformAlgo Algorithms to Transform Images
00036     Apply functor to calculate a pixelwise transformation of one image
00037 
00038     @{
00039 */
00040 
00041 /********************************************************/
00042 /*                                                      */
00043 /*                      transformLine                   */
00044 /*                                                      */
00045 /********************************************************/
00046 
00047 template <class SrcIterator, class SrcAccessor,
00048           class DestIterator, class DestAccessor, class Functor>
00049 void
00050 transformLine(SrcIterator s,
00051               SrcIterator send, SrcAccessor src,
00052               DestIterator d, DestAccessor dest,
00053               Functor const & f)
00054 {
00055     for(; s != send; ++s, ++d)
00056         dest.set(f(src(s)), d);
00057 }
00058 
00059 template <class SrcIterator, class SrcAccessor,
00060           class MaskIterator, class MaskAccessor,
00061           class DestIterator, class DestAccessor,
00062           class Functor>
00063 void
00064 transformLineIf(SrcIterator s,
00065                 SrcIterator send, SrcAccessor src,
00066                 MaskIterator m, MaskAccessor mask,
00067                 DestIterator d, DestAccessor dest,
00068                 Functor const & f)
00069 {
00070     for(; s != send; ++s, ++d, ++m)
00071         if(mask(m))
00072             dest.set(f(src(s)), d);
00073 }
00074 
00075 /********************************************************/
00076 /*                                                      */
00077 /*                      transformImage                  */
00078 /*                                                      */
00079 /********************************************************/
00080 
00081 /** \brief Apply unary point transformation to each pixel.
00082 
00083     The transformation given by the functor is applied to every source
00084     pixel and the result written into the corresponding destination pixel.
00085     The function uses accessors to access the pixel data.
00086     Note that the unary functors of the STL can be used in addition to
00087     the functors specifically defined in \ref TransformFunctor.
00088     Creation of new functors is easiest by using \ref FunctorExpressions.
00089 
00090     <b> Declarations:</b>
00091 
00092     pass arguments explicitly:
00093     \code
00094     namespace vigra {
00095         template <class SrcImageIterator, class SrcAccessor,
00096               class DestImageIterator, class DestAccessor, class Functor>
00097         void
00098         transformImage(SrcImageIterator src_upperleft,
00099                SrcImageIterator src_lowerright, SrcAccessor sa,
00100                DestImageIterator dest_upperleft, DestAccessor da,
00101                Functor const & f)
00102     }
00103     \endcode
00104 
00105 
00106     use argument objects in conjunction with \ref ArgumentObjectFactories:
00107     \code
00108     namespace vigra {
00109         template <class SrcImageIterator, class SrcAccessor,
00110               class DestImageIterator, class DestAccessor, class Functor>
00111         void
00112         transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00113                pair<DestImageIterator, DestAccessor> dest,
00114                Functor const & f)
00115     }
00116     \endcode
00117 
00118     <b> Usage:</b>
00119 
00120     <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00121     Namespace: vigra
00122 
00123     \code
00124 
00125     #include <cmath>         // for sqrt()
00126 
00127     vigra::transformImage(srcImageRange(src),
00128                           destImage(dest),
00129                           &std::sqrt );
00130 
00131     \endcode
00132 
00133     <b> Required Interface:</b>
00134 
00135     \code
00136     SrcImageIterator src_upperleft, src_lowerright;
00137     DestImageIterator      dest_upperleft;
00138     SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
00139     DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
00140 
00141     SrcAccessor src_accessor;
00142     DestAccessor dest_accessor;
00143 
00144     Functor functor;
00145 
00146     dest_accessor.set(functor(src_accessor(sx)), dx);
00147 
00148     \endcode
00149 
00150 */
00151 template <class SrcImageIterator, class SrcAccessor,
00152           class DestImageIterator, class DestAccessor, class Functor>
00153 void
00154 transformImage(SrcImageIterator src_upperleft,
00155                SrcImageIterator src_lowerright, SrcAccessor sa,
00156                DestImageIterator dest_upperleft, DestAccessor da,
00157                Functor const & f)
00158 {
00159     int w = src_lowerright.x - src_upperleft.x;
00160 
00161     for(; src_upperleft.y < src_lowerright.y; ++src_upperleft.y, ++dest_upperleft.y)
00162     {
00163         transformLine(src_upperleft.rowIterator(),
00164                       src_upperleft.rowIterator() + w, sa,
00165                       dest_upperleft.rowIterator(), da, f);
00166     }
00167 }
00168 
00169 template <class SrcImageIterator, class SrcAccessor,
00170       class DestImageIterator, class DestAccessor, class Functor>
00171 inline
00172 void
00173 transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00174                pair<DestImageIterator, DestAccessor> dest,
00175                Functor const & f)
00176 {
00177     transformImage(src.first, src.second, src.third,
00178                    dest.first, dest.second, f);
00179 }
00180 
00181 /********************************************************/
00182 /*                                                      */
00183 /*                   transformImageIf                   */
00184 /*                                                      */
00185 /********************************************************/
00186 
00187 /** \brief Apply unary point transformation to each pixel within the ROI
00188     (i.e., where the mask is non-zero).
00189 
00190     The transformation given by the functor is applied to every source
00191     pixel in the ROI (i.e. when the return vlaue of the mask's accessor
00192     is not zero)
00193     and the result is written into the corresponding destination pixel.
00194     The function uses accessors to access the pixel data.
00195     Note that the unary functors of the STL can be used in addition to
00196     the functors specifically defined in \ref TransformFunctor.
00197     Creation of new functors is easiest by using \ref FunctorExpressions.
00198 
00199     <b> Declarations:</b>
00200 
00201     pass arguments explicitly:
00202     \code
00203     namespace vigra {
00204         template <class SrcImageIterator, class SrcAccessor,
00205               class MaskImageIterator, class MaskAccessor,
00206               class DestImageIterator, clas DestAccessor,
00207               class Functor>
00208         void
00209         transformImageIf(SrcImageIterator src_upperleft,
00210             SrcImageIterator src_lowerright, SrcAccessor sa,
00211             MaskImageIterator mask_upperleft, MaskAccessor ma,
00212             DestImageIterator dest_upperleft, DestAccessor da,
00213             Functor const & f)
00214     }
00215     \endcode
00216 
00217 
00218     use argument objects in conjunction with \ref ArgumentObjectFactories:
00219     \code
00220     namespace vigra {
00221         template <class SrcImageIterator, class SrcAccessor,
00222               class MaskImageIterator, class MaskAccessor,
00223               class DestImageIterator, clas DestAccessor,
00224               class Functor>
00225         void
00226         transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00227                  pair<MaskImageIterator, MaskAccessor> mask,
00228                  pair<DestImageIterator, DestAccessor> dest,
00229                  Functor const & f)
00230     }
00231     \endcode
00232 
00233     <b> Usage:</b>
00234 
00235         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00236         Namespace: vigra
00237 
00238     \code
00239     #include <math.h>         // for sqrt()
00240 
00241     vigra::transformImageIf(srcImageRange(src),
00242                             maskImage(mask),
00243                             destImage(dest),
00244                             &::sqrt );
00245 
00246     \endcode
00247 
00248     <b> Required Interface:</b>
00249 
00250     \code
00251     SrcImageIterator src_upperleft, src_lowerright;
00252     DestImageIterator  dest_upperleft;
00253     MaskImageIterator mask_upperleft;
00254     SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
00255     MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
00256     DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
00257 
00258     SrcAccessor src_accessor;
00259     DestAccessor dest_accessor;
00260     MaskAccessor mask_accessor;
00261     Functor functor;
00262 
00263     if(mask_accessor(mx))
00264        dest_accessor.set(functor(src_accessor(sx)), dx);
00265 
00266     \endcode
00267 
00268 */
00269 template <class SrcImageIterator, class SrcAccessor,
00270           class MaskImageIterator, class MaskAccessor,
00271           class DestImageIterator, class DestAccessor,
00272           class Functor>
00273 void
00274 transformImageIf(SrcImageIterator src_upperleft,
00275                  SrcImageIterator src_lowerright, SrcAccessor sa,
00276                  MaskImageIterator mask_upperleft, MaskAccessor ma,
00277                  DestImageIterator dest_upperleft, DestAccessor da,
00278                  Functor const & f)
00279 {
00280     int w = src_lowerright.x - src_upperleft.x;
00281 
00282     for(; src_upperleft.y < src_lowerright.y;
00283              ++src_upperleft.y, ++mask_upperleft.y, ++dest_upperleft.y)
00284     {
00285         transformLineIf(src_upperleft.rowIterator(),
00286                         src_upperleft.rowIterator() + w, sa,
00287                         mask_upperleft.rowIterator(), ma,
00288                         dest_upperleft.rowIterator(), da, f);
00289     }
00290 }
00291 
00292 template <class SrcImageIterator, class SrcAccessor,
00293           class MaskImageIterator, class MaskAccessor,
00294           class DestImageIterator, class DestAccessor,
00295           class Functor>
00296 inline
00297 void
00298 transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00299                  pair<MaskImageIterator, MaskAccessor> mask,
00300                  pair<DestImageIterator, DestAccessor> dest,
00301                  Functor const & f)
00302 {
00303     transformImageIf(src.first, src.second, src.third,
00304                      mask.first, mask.second,
00305                      dest.first, dest.second, f);
00306 }
00307 
00308 /********************************************************/
00309 /*                                                      */
00310 /*               gradientBasedTransform                 */
00311 /*                                                      */
00312 /********************************************************/
00313 
00314 /** \brief Calculate a function of the image gradient.
00315 
00316     The gradient and the function represented by <TT>Functor f</TT>
00317     are calculated in one go: for each location, the symmetric
00318     difference in x- and y-directions (asymmetric difference at the
00319     image borders) are passed to the given functor, and the result is
00320     written the destination image. Functors to be used with this
00321     function include \ref MagnitudeFunctor and \ref
00322     RGBGradientMagnitudeFunctor.
00323 
00324     <b> Declarations:</b>
00325 
00326     pass arguments explicitly:
00327     \code
00328     namespace vigra {
00329         template <class SrcImageIterator, class SrcAccessor,
00330                   class DestImageIterator, class DestAccessor, class Functor>
00331         void
00332         gradientBasedTransform(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor sa,
00333                       DestImageIterator destul, DestAccessor da, Functor const & f)
00334     }
00335     \endcode
00336 
00337 
00338     use argument objects in conjunction with \ref ArgumentObjectFactories:
00339     \code
00340     namespace vigra {
00341         template <class SrcImageIterator, class SrcAccessor,
00342                   class DestImageIterator, class DestAccessor, class Functor>
00343         void
00344         gradientBasedTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00345                        pair<DestImageIterator, DestAccessor> dest, Functor const & const & f)
00346     }
00347     \endcode
00348 
00349     <b> Usage:</b>
00350 
00351     <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"
00352 
00353 
00354     \code
00355     vigra::FImage src(w,h), magnitude(w,h);
00356     ...
00357 
00358     gradientBasedTransform(srcImageRange(src), destImage(magnitude),
00359                                 vigra::MagnitudeFunctor<float>());
00360     \endcode
00361 
00362     <b> Required Interface:</b>
00363 
00364     \code
00365     SrcImageIterator is, isend;
00366     DestImageIterator id;
00367 
00368     SrcAccessor src_accessor;
00369     DestAccessor dest_accessor;
00370 
00371     typename NumericTraits<typename SrcAccessor::value_type>::RealPromote
00372         diffx, diffy;
00373 
00374     diffx = src_accessor(is, Diff2D(-1,0)) - src_accessor(is, Diff2D(1,0));
00375     diffy = src_accessor(is, Diff2D(0,-1)) - src_accessor(is, Diff2D(0,1));
00376 
00377     Functor f;
00378 
00379     dest_accessor.set(f(diffx, diffy), id);
00380 
00381     \endcode
00382 
00383 */
00384 
00385 template <class SrcImageIterator, class SrcAccessor,
00386           class DestImageIterator, class DestAccessor, class Functor>
00387 void
00388 gradientBasedTransform(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor sa,
00389                        DestImageIterator destul, DestAccessor da, Functor const & grad)
00390 {
00391     int w = srclr.x - srcul.x;
00392     int h = srclr.y - srcul.y;
00393     int x,y;
00394 
00395     SrcImageIterator sy = srcul;
00396     DestImageIterator dy = destul;
00397 
00398     static const Diff2D left(-1,0);
00399     static const Diff2D right(1,0);
00400     static const Diff2D top(0,-1);
00401     static const Diff2D bottom(0,1);
00402 
00403     typename NumericTraits<typename SrcAccessor::value_type>::RealPromote
00404              diffx, diffy;
00405 
00406     SrcImageIterator sx = sy;
00407     DestImageIterator dx = dy;
00408 
00409     diffx = sa(sx) - sa(sx, right);
00410     diffy = sa(sx) - sa(sx, bottom);
00411     da.set(grad(diffx, diffy), dx);
00412 
00413     for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
00414     {
00415         diffx = (sa(sx, left) - sa(sx, right)) / 2.0;
00416         diffy = sa(sx) - sa(sx, bottom);
00417         da.set(grad(diffx, diffy), dx);
00418     }
00419 
00420     diffx = sa(sx, left) - sa(sx);
00421     diffy = sa(sx) - sa(sx, bottom);
00422     da.set(grad(diffx, diffy), dx);
00423 
00424     ++sy.y;
00425     ++dy.y;
00426 
00427     for(y=2; y<h; ++y, ++sy.y, ++dy.y)
00428     {
00429         sx = sy;
00430         dx = dy;
00431 
00432         diffx = sa(sx) - sa(sx, right);
00433         diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0;
00434         da.set(grad(diffx, diffy), dx);
00435 
00436         for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
00437         {
00438             diffx = (sa(sx, left) - sa(sx, right)) / 2.0;
00439             diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0;
00440             da.set(grad(diffx, diffy), dx);
00441         }
00442 
00443         diffx = sa(sx, left) - sa(sx);
00444         diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0;
00445         da.set(grad(diffx, diffy), dx);
00446     }
00447 
00448     sx = sy;
00449     dx = dy;
00450 
00451     diffx = sa(sx) - sa(sx, right);
00452     diffy = sa(sx, top) - sa(sx);
00453     da.set(grad(diffx, diffy), dx);
00454 
00455     for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
00456     {
00457         diffx = (sa(sx, left) - sa(sx, right)) / 2.0;
00458         diffy = sa(sx, top) - sa(sx);
00459         da.set(grad(diffx, diffy), dx);
00460     }
00461 
00462     diffx = sa(sx, left) - sa(sx);
00463     diffy = sa(sx, top) - sa(sx);
00464     da.set(grad(diffx, diffy), dx);
00465 }
00466 
00467 template <class SrcImageIterator, class SrcAccessor,
00468           class DestImageIterator, class DestAccessor, class Functor>
00469 inline
00470 void
00471 gradientBasedTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00472                        pair<DestImageIterator, DestAccessor> dest, Functor const & grad)
00473 {
00474     gradientBasedTransform(src.first, src.second, src.third,
00475                            dest.first, dest.second, grad);
00476 }
00477 
00478 /** @} */
00479 /** \addtogroup TransformFunctor Functors to Transform Images
00480 
00481     Note that the unary functors of the STL can also be used in
00482     connection with \ref transformImage().
00483 */
00484 //@{
00485 
00486 template <class DestValueType, class Multiplier = double>
00487 class LinearIntensityTransform
00488 {
00489   public:
00490         /* the functors argument type (actually, since
00491            <tt>operator()</tt> is a template, much more types are possible)
00492         */
00493     typedef DestValueType argument_type;
00494 
00495         /* the functors result type
00496         */
00497     typedef DestValueType result_type;
00498 
00499         /* \deprecated use argument_type and result_type
00500         */
00501     typedef DestValueType value_type;
00502 
00503         /* type of the offset (used in internal calculations to prevent
00504             overflows and minimize round-off errors).
00505         */
00506     typedef typename
00507             NumericTraits<DestValueType>::RealPromote argument_promote;
00508 
00509         /* type of the scale factor
00510         */
00511     typedef Multiplier scalar_multiplier_type;
00512 
00513         /* init scale and offset
00514         */
00515     LinearIntensityTransform(scalar_multiplier_type scale, argument_promote offset)
00516     : scale_(scale), offset_(offset)
00517     {}
00518 
00519         /* calculate transform
00520         */
00521     template <class SrcValueType>
00522     result_type operator()(SrcValueType const & s) const
00523     {
00524         return NumericTraits<result_type>::fromRealPromote(scale_ * (s + offset_));
00525     }
00526 
00527   private:
00528 
00529     scalar_multiplier_type scale_;
00530     argument_promote offset_;
00531 };
00532 
00533 template <class DestValueType, class Multiplier>
00534 class FunctorTraits<LinearIntensityTransform<DestValueType, Multiplier> >
00535 : public FunctorTraitsBase<LinearIntensityTransform<DestValueType, Multiplier> >
00536 {
00537   public:
00538     typedef VigraTrueType isUnaryFunctor;
00539 };
00540 
00541 template <class DestValueType, class Multiplier = double>
00542 class ScalarIntensityTransform
00543 {
00544   public:
00545         /* the functors argument type (actually, since
00546            <tt>operator()</tt> is a template, much more types are possible)
00547         */
00548     typedef DestValueType argument_type;
00549 
00550         /* the functors result type
00551         */
00552     typedef DestValueType result_type;
00553 
00554         /* \deprecated use argument_type and result_type
00555         */
00556     typedef DestValueType value_type;
00557 
00558         /* type of the scale factor
00559         */
00560     typedef Multiplier scalar_multiplier_type;
00561 
00562         /* init scale
00563         */
00564     ScalarIntensityTransform(scalar_multiplier_type scale)
00565     : scale_(scale)
00566     {}
00567 
00568         /* calculate transform
00569         */
00570     template <class SrcValueType>
00571     result_type operator()(SrcValueType const & s) const
00572     {
00573         return NumericTraits<result_type>::fromRealPromote(scale_ * s);
00574     }
00575 
00576   private:
00577     scalar_multiplier_type scale_;
00578 };
00579 
00580 template <class DestValueType, class Multiplier>
00581 class FunctorTraits<ScalarIntensityTransform<DestValueType, Multiplier> >
00582 : public FunctorTraitsBase<ScalarIntensityTransform<DestValueType, Multiplier> >
00583 {
00584   public:
00585     typedef VigraTrueType isUnaryFunctor;
00586 };
00587 
00588 /********************************************************/
00589 /*                                                      */
00590 /*              linearIntensityTransform                */
00591 /*                                                      */
00592 /********************************************************/
00593 
00594 /** \brief Apply a linear transform to the source pixel values
00595 
00596     Factory function for a functor that linearly transforms the
00597     source pixel values. The functor applies the transform
00598     '<TT>destvalue = scale * (srcvalue + offset)</TT>' to every pixel.
00599     This can, for example, be used to transform images into the visible
00600     range 0...255 or to invert an image.
00601 
00602     If you leave out the second parameter / offset, you will get an
00603     optimized version of the functor which only scales by the given
00604     factor, however you have to make the template parameter (pixel
00605     type) explicit then.
00606 
00607     <b> Traits defined:</b>
00608 
00609     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType<tt>)
00610 
00611     <b> Declaration:</b>
00612 
00613     \code
00614     namespace vigra {
00615         template <class Multiplier, class DestValueType>
00616         LinearIntensityTransform<DestValueType, Multiplier>
00617         linearIntensityTransform(Multiplier scale, DestValueType offset);
00618 
00619         template <class DestValueType, class Multiplier>
00620         ScalarIntensityTransform<DestValueType, Multiplier>
00621         linearIntensityTransform(Multiplier scale);
00622     }
00623     \endcode
00624 
00625     <b> Usage:</b>
00626 
00627         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00628         Namespace: vigra
00629 
00630     \code
00631     vigra::IImage src(width, height);
00632     vigra::BImage dest(width, height);
00633     ...
00634     vigra::FindMinMax<IImage::PixelType> minmax;   // functor to find range
00635 
00636     vigra::inspectImage(srcImageRange(src), minmax); // find original range
00637 
00638     // transform to range 0...255
00639     vigra::transformImage(srcImageRange(src), destImage(dest),
00640                           linearIntensityTransform(
00641                             255.0 / (minmax.max - minmax.min), // scaling
00642                           - minmax.min));                    // offset
00643     \endcode
00644 
00645     The one-parameter version can be used like this:
00646 
00647     \code
00648     // scale from 0..255 to 0..1.0
00649     FImage dest(src.size());
00650 
00651     vigra::transformImage(srcImageRange(src), destImage(dest),
00652                           linearIntensityTransform<float>(1.0 / 255));
00653     \endcode
00654 
00655     <b> Required Interface:</b>
00656 
00657     The source and destination value types must be models of \ref LinearSpace in both cases.
00658 
00659 */
00660 template <class Multiplier, class DestValueType>
00661 LinearIntensityTransform<DestValueType, Multiplier>
00662 linearIntensityTransform(Multiplier scale, DestValueType offset)
00663 {
00664     return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
00665 }
00666 
00667 template <class DestValueType, class Multiplier>
00668 ScalarIntensityTransform<DestValueType, Multiplier>
00669 linearIntensityTransform(Multiplier scale)
00670 {
00671     return ScalarIntensityTransform<DestValueType, Multiplier>(scale);
00672 }
00673 
00674 /********************************************************/
00675 /*                                                      */
00676 /*                   linearRangeMapping                 */
00677 /*                                                      */
00678 /********************************************************/
00679 
00680 /** \brief Map a source intensity range linearly to a destination range.
00681 
00682     Factory function for a functor that linearly transforms the
00683     source pixel values. The functor applies the transform
00684     '<TT>destvalue = scale * (srcvalue + offset)</TT>' to every pixel,
00685     where <tt>scale = (dest_max - dest_min) / (src_max - src_min)</tt>
00686     and <tt>offset = dest_min / scale - src_min</tt>. As a result,
00687     the pixel values <tt>src_max</tt>, <tt>src_min</tt> in the source image
00688     are mapped onto <tt>dest_max</tt>, <tt>dest_min</tt> respectively.
00689     This works for scalar as well as vector pixel types.
00690 
00691     <b> Declaration:</b>
00692 
00693     \code
00694     namespace vigra {
00695         template <class SrcValueType, class DestValueType>
00696         LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00697         linearRangeMapping(SrcValueType src_min, SrcValueType src_max,
00698                            DestValueType dest_min, DestValueType dest_max );
00699     }
00700     \endcode
00701 
00702     <b> Usage:</b>
00703 
00704         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00705         Namespace: vigra
00706 
00707     \code
00708     vigra::IImage src(width, height);
00709     vigra::BImage dest(width, height);
00710     ...
00711     vigra::FindMinMax<IImage::PixelType> minmax;   // functor to find range
00712 
00713     vigra::inspectImage(srcImageRange(src), minmax); // find original range
00714 
00715     // transform to range 0...255
00716     vigra::transformImage(srcImageRange(src), destImage(dest),
00717                           linearRangeTransform(
00718                             minmax.min, minmax.max,               // src range
00719                             (unsigned char)0, (unsigned char)255) // dest range
00720                           );
00721     \endcode
00722 
00723     <b> Required Interface:</b>
00724 
00725     The source and destination value types must be models of \ref LinearSpace in both cases.
00726 
00727 */
00728 template <class SrcValueType, class DestValueType>
00729 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00730 linearRangeMapping(SrcValueType src_min, SrcValueType src_max,
00731                    DestValueType dest_min, DestValueType dest_max )
00732 {
00733     return linearRangeMapping(src_min, src_max, dest_min, dest_max,
00734             typename NumericTraits<DestValueType>::isScalar());
00735 }
00736 
00737 template <class SrcValueType, class DestValueType>
00738 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00739 linearRangeMapping(
00740     SrcValueType src_min, SrcValueType src_max,
00741     DestValueType dest_min, DestValueType dest_max,
00742     VigraTrueType /* isScalar */ )
00743 {
00744     typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
00745     Multiplier diff = src_max - src_min;
00746     Multiplier scale = diff == NumericTraits<Multiplier>::zero()
00747                      ? NumericTraits<Multiplier>::one()
00748                      : (dest_max - dest_min) / diff;
00749     return LinearIntensityTransform<DestValueType, Multiplier>(
00750                                    scale, dest_min / scale - src_min );
00751 }
00752 
00753 template <class SrcValueType, class DestValueType>
00754 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00755 linearRangeMapping(
00756     SrcValueType src_min, SrcValueType src_max,
00757     DestValueType dest_min, DestValueType dest_max,
00758     VigraFalseType /* isScalar */ )
00759 {
00760     typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
00761     typedef typename Multiplier::value_type MComponent;
00762     Multiplier scale(dest_max), offset(dest_max);
00763     for(unsigned int i=0; i<src_min.size(); ++i)
00764     {
00765         MComponent diff = src_max[i] - src_min[i];
00766         scale[i] = diff == NumericTraits<MComponent>::zero()
00767                      ? NumericTraits<MComponent>::one()
00768                      : (dest_max[i] - dest_min[i]) / diff;
00769         offset[i] = dest_min[i] / scale[i] - src_min[i];
00770     }
00771     return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
00772 }
00773 
00774 /********************************************************/
00775 /*                                                      */
00776 /*                      Threshold                       */
00777 /*                                                      */
00778 /********************************************************/
00779 
00780 /** \brief Threshold an image.
00781 
00782     If a source pixel is above or equal the lower and below
00783     or equal the higher threshold (i.e. within the closed interval
00784     [lower, heigher]) the destination pixel is set to 'yesresult',
00785     otherwise to 'noresult'.
00786 
00787     <b> Traits defined:</b>
00788 
00789     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType<tt>)
00790 
00791     <b> Usage:</b>
00792 
00793         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00794         Namespace: vigra
00795 
00796     \code
00797     vigra::BImage src(width, height), dest(width, height);
00798     ...
00799     vigra::transformImage(src.upperLeft(), src.lowerRight(), src.accessor(),
00800        dest.upperLeft(), dest.accessor(),
00801        vigra::Threshold<
00802           vigra::BImage::PixelType, vigra::BImage::PixelType>(10, 100, 0, 255));
00803 
00804     \endcode
00805 
00806     <b> Required Interface:</b>
00807 
00808     \code
00809 
00810     SrcValueType   src;
00811     DestValueType  dest, yesresult, noresult;
00812 
00813     dest = ((src < lower) || (higher < src)) ? noresult : yesresult;
00814 
00815     \endcode
00816 
00817 */
00818 template <class SrcValueType, class DestValueType>
00819 class Threshold
00820 {
00821    public:
00822 
00823         /** the functor's argument type
00824         */
00825     typedef SrcValueType argument_type;
00826 
00827         /** the functor's result type
00828         */
00829     typedef DestValueType result_type;
00830 
00831         /** init thresholds and return values
00832         */
00833     Threshold(argument_type lower, argument_type higher,
00834               result_type noresult, result_type yesresult)
00835     : lower_(lower), higher_(higher),
00836       yesresult_(yesresult), noresult_(noresult)
00837     {}
00838 
00839         /** calculate transform
00840         */
00841     result_type operator()(argument_type s) const
00842     {
00843         return ((s < lower_) || (higher_ < s)) ? noresult_ : yesresult_;
00844     }
00845 
00846   private:
00847 
00848     argument_type lower_, higher_;
00849     result_type yesresult_, noresult_;
00850 };
00851 
00852 template <class SrcValueType, class DestValueType>
00853 class FunctorTraits<Threshold<SrcValueType, DestValueType> >
00854 : public FunctorTraitsBase<Threshold<SrcValueType, DestValueType> >
00855 {
00856   public:
00857     typedef VigraTrueType isUnaryFunctor;
00858 };
00859 
00860 /********************************************************/
00861 /*                                                      */
00862 /*                BrightnessContrastFunctor             */
00863 /*                                                      */
00864 /********************************************************/
00865 
00866 /** \brief Adjust brightness and contrast of an image.
00867 
00868     This functor applies a gamma correction to each pixel in order to
00869     modify the brightness of the image. To the result of the gamma correction,
00870     another transform is applied that modifies the contrast. The brightness and
00871     contrast parameters must be positive. Values greater than 1 will increase image
00872     brightness and contrast, values smaller than 1 decrease them. A value = 1 will
00873     have no effect.
00874     For \ref RGBValue "RGBValue's", the transforms are applied component-wise. The pixel
00875     values are assumed to lie between the given minimum and maximum
00876     values. In case of RGB, this is again understood component-wise. In case
00877     of <TT>unsigned char</TT>, min and max default to 0 and 255 respectively.
00878     Precisely, the following transform is applied to each <em> PixelValue</em>:
00879 
00880     \f[
00881     \begin{array}{rcl}
00882     V_1 & = & \frac{PixelValue - min}{max - min} \\
00883     V_2 & = & V_1^\frac{1}{brightness} \\
00884     V_3 & = & 2 V_2 - 1 \\
00885     V_4 & = & \left\lbrace
00886         \begin{array}{l}
00887          V_3^\frac{1}{contrast} \mbox{\rm \quad if  } V_3 \ge 0 \\
00888          - (-V_3)^\frac{1}{contrast} \mbox{\rm \quad otherwise}
00889         \end{array} \right. \\
00890     Result & = & \frac{V_4 + 1}{2} (max - min) + min
00891     \end{array}
00892     \f]
00893 
00894     If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a look-up-table is used
00895     for faster computation.
00896 
00897     <b> Traits defined:</b>
00898 
00899     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType<tt>)
00900 
00901     <b> Usage:</b>
00902 
00903         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00904         Namespace: vigra
00905 
00906     \code
00907     vigra::BImage bimage(width, height);
00908     double brightness, contrast;
00909     ...
00910     vigra::transformImage(srcImageRange(bimage), destImage(bimage),
00911        vigra::BrightnessContrastFunctor<unsigned char>(brightness, contrast));
00912 
00913 
00914 
00915     vigra::FImage fimage(width, height);
00916     ...
00917 
00918     vigra::FindMinmax<float> minmax;
00919     vigra::inspectImage(srcImageRange(fimage), minmax);
00920 
00921     vigra::transformImage(srcImageRange(fimage), destImage(fimage),
00922        vigra::BrightnessContrastFunctor<float>(brightness, contrast, minmax.min, minmax.max));
00923 
00924 
00925     \endcode
00926 
00927     <b> Required Interface:</b>
00928 
00929     Scalar types: must be a linear algebra (+, - *, NumericTraits),
00930     strict weakly ordered (<), and <TT>pow()</TT> must be defined.
00931 
00932     RGB values: the component type must meet the above requirements.
00933 */
00934 template <class PixelType>
00935 class BrightnessContrastFunctor
00936 {
00937     typedef typename
00938         NumericTraits<PixelType>::RealPromote promote_type;
00939 
00940  public:
00941 
00942         /** the functor's argument type
00943         */
00944     typedef PixelType argument_type;
00945 
00946         /** the functor's result type
00947         */
00948     typedef PixelType result_type;
00949 
00950         /** \deprecated use argument_type and result_type
00951         */
00952     typedef PixelType value_type;
00953 
00954         /** Init functor for argument range <TT>[min, max]</TT>.
00955             <TT>brightness</TT> and <TT>contrast</TT> values > 1 will
00956             increase brightness and contrast, < 1 will decrease them, and == 1 means
00957             no change.
00958         */
00959     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
00960                               argument_type const & min, argument_type const & max)
00961     : b_(1.0/brightness),
00962       c_(1.0/contrast),
00963       min_(min),
00964       diff_(max - min),
00965       zero_(NumericTraits<promote_type>::zero()),
00966       one_(NumericTraits<promote_type>::one())
00967     {}
00968 
00969         /** Calculate modified gray or color value
00970         */
00971     result_type operator()(argument_type const & v) const
00972     {
00973         promote_type v1 = (v - min_) / diff_;
00974         promote_type brighter = pow(v1, b_);
00975         promote_type v2 = 2.0 * brighter - one_;
00976         promote_type contrasted = (v2 < zero_) ?
00977                                      -pow(-v2, c_) :
00978                                       pow(v2, c_);
00979         return result_type(0.5 * diff_ * (contrasted + one_) + min_);
00980     }
00981 
00982   private:
00983     promote_type b_, c_;
00984     argument_type min_;
00985     promote_type diff_, zero_, one_;
00986 };
00987 
00988 template <>
00989 class BrightnessContrastFunctor<unsigned char>
00990 {
00991     typedef NumericTraits<unsigned char>::RealPromote promote_type;
00992      unsigned char lut[256];
00993 
00994  public:
00995 
00996     typedef unsigned char value_type;
00997 
00998     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
00999                               value_type const & min = 0, value_type const & max = 255)
01000     {
01001         BrightnessContrastFunctor<promote_type> f(brightness, contrast, min, max);
01002 
01003         for(int i = min; i <= max; ++i)
01004         {
01005             lut[i] = static_cast<unsigned char>(f(i)+0.5);
01006         }
01007     }
01008 
01009     value_type operator()(value_type const & v) const
01010     {
01011 
01012         return lut[v];
01013     }
01014 };
01015 
01016 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
01017 
01018 template <class ComponentType>
01019 class BrightnessContrastFunctor<RGBValue<ComponentType> >
01020 {
01021     typedef typename
01022         NumericTraits<ComponentType>::RealPromote promote_type;
01023     BrightnessContrastFunctor<ComponentType> red, green, blue;
01024 
01025  public:
01026 
01027     typedef RGBValue<ComponentType> value_type;
01028 
01029     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01030                               value_type const & min, value_type const & max)
01031     : red(brightness, contrast, min.red(), max.red()),
01032       green(brightness, contrast, min.green(), max.green()),
01033       blue(brightness, contrast, min.blue(), max.blue())
01034     {}
01035 
01036     value_type operator()(value_type const & v) const
01037     {
01038 
01039         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01040     }
01041 };
01042 
01043 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01044 
01045 template <>
01046 class BrightnessContrastFunctor<RGBValue<int> >
01047 {
01048     typedef NumericTraits<int>::RealPromote promote_type;
01049     BrightnessContrastFunctor<int> red, green, blue;
01050 
01051  public:
01052 
01053     typedef RGBValue<int> value_type;
01054 
01055     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01056                               value_type const & min, value_type const & max)
01057     : red(brightness, contrast, min.red(), max.red()),
01058       green(brightness, contrast, min.green(), max.green()),
01059       blue(brightness, contrast, min.blue(), max.blue())
01060     {}
01061 
01062     value_type operator()(value_type const & v) const
01063     {
01064 
01065         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01066     }
01067 };
01068 
01069 template <>
01070 class BrightnessContrastFunctor<RGBValue<float> >
01071 {
01072     typedef NumericTraits<float>::RealPromote promote_type;
01073     BrightnessContrastFunctor<float> red, green, blue;
01074 
01075  public:
01076 
01077     typedef RGBValue<float> value_type;
01078 
01079     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01080                               value_type const & min, value_type const & max)
01081     : red(brightness, contrast, min.red(), max.red()),
01082       green(brightness, contrast, min.green(), max.green()),
01083       blue(brightness, contrast, min.blue(), max.blue())
01084     {}
01085 
01086     value_type operator()(value_type const & v) const
01087     {
01088 
01089         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01090     }
01091 };
01092 
01093 template <class PixelType>
01094 class FunctorTraits<BrightnessContrastFunctor<PixelType> >
01095 : public FunctorTraitsBase<BrightnessContrastFunctor<PixelType> >
01096 {
01097   public:
01098     typedef VigraTrueType isUnaryFunctor;
01099 };
01100 
01101 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01102 
01103 template <>
01104 class BrightnessContrastFunctor<RGBValue<unsigned char> >
01105 {
01106     typedef NumericTraits<unsigned char>::RealPromote promote_type;
01107     BrightnessContrastFunctor<unsigned char> red, green, blue;
01108 
01109  public:
01110 
01111     typedef RGBValue<unsigned char> value_type;
01112 
01113     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01114        value_type const & min = value_type(0,0,0),
01115        value_type const & max = value_type(255, 255, 255))
01116     : red(brightness, contrast, min.red(), max.red()),
01117       green(brightness, contrast, min.green(), max.green()),
01118       blue(brightness, contrast, min.blue(), max.blue())
01119     {}
01120 
01121     value_type operator()(value_type const & v) const
01122     {
01123 
01124         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01125     }
01126 };
01127 
01128 
01129 
01130 /********************************************************/
01131 /*                                                      */
01132 /*                     VectorNormFunctor                */
01133 /*                                                      */
01134 /********************************************************/
01135 
01136 /** \brief A functor for computing the vector norm
01137 
01138     Calculate the magnitude or norm from a given vector-valued
01139     entity. The vector type will typically be some sort of
01140     ref vigra::TinyVector. If the vector is represented by a pair of
01141     scalar-valued images, use \ref vigra::MagnitudeFunctor instead.
01142 
01143     At least, the vector type is required to have a function
01144     '<em>result</em><TT> = dot(v,v)</TT>'.
01145 
01146     <b> Traits defined:</b>
01147 
01148     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType<tt>)
01149 
01150     <b> Usage:</b>
01151 
01152         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
01153         Namespace: vigra
01154 
01155     \code
01156     typedef vigra::TinyVector<float, 2> Vector;
01157     vigra::BasicImage<Vector> grad(width, height);
01158     vigra::FImage magn(width,height);
01159     ...
01160     vigra::transformImage(srcImageRange(grad), destImage(magn),
01161                           VectorNormFunctor<float>()
01162                           );
01163     \endcode
01164 
01165     \see vigra::TinyVector, dot(), vigra::MagnitudeFunctor
01166 */
01167 template <class ValueType>
01168 class VectorNormFunctor
01169 {
01170 public:
01171   /** the functor's argument type
01172    */
01173   typedef ValueType argument_type;
01174 
01175   /** the functor's result type
01176    */
01177   typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
01178 
01179   /** calculate transform '<TT>sqrt(v1*v1 + v2*v2 + ...)</TT>'.
01180    */
01181   result_type operator()( const argument_type &a ) const
01182   {
01183     return VIGRA_CSTD::sqrt( dot(a,a) );
01184   }
01185 };    //-- class VectorNormFunctor
01186 
01187 template <class ValueType>
01188 class FunctorTraits<VectorNormFunctor<ValueType> >
01189 : public FunctorTraitsBase<VectorNormFunctor<ValueType> >
01190 {
01191   public:
01192     typedef VigraTrueType isUnaryFunctor;
01193 };
01194 
01195 /** \brief A functor for computing the squared vector norm
01196 
01197     Calculate the squared magnitude or norm from a given
01198     vector-valued entity. The vector type will typically be some
01199     sort of TinyVector.
01200 
01201     At least, the vector type is required to have a function
01202     '<em>result</em><TT> = dot(v,v)</TT>'.
01203 
01204     For an example of its usage see VectorNormFunctor
01205 
01206     <b> Traits defined:</b>
01207 
01208     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType<tt>)
01209 
01210     \see TinyVector, dot()
01211 */
01212 template <class ValueType>
01213 class VectorNormSqFunctor
01214 {
01215 public:
01216   /** the functor's argument type
01217    */
01218   typedef ValueType argument_type;
01219 
01220   /** the functor's result type
01221    */
01222   typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
01223 
01224   /** calculate transform '<TT>v1*v1 + v2*v2 + ...</TT>'.
01225    */
01226   result_type operator()( const argument_type &a ) const
01227   {
01228     return dot(a,a);
01229   }
01230 };    //-- class VectorNormSqFunctor
01231 
01232 template <class ValueType>
01233 class FunctorTraits<VectorNormSqFunctor<ValueType> >
01234 : public FunctorTraitsBase<VectorNormSqFunctor<ValueType> >
01235 {
01236   public:
01237     typedef VigraTrueType isUnaryFunctor;
01238 };
01239 
01240 //@}
01241 
01242 } // namespace vigra
01243 
01244 #endif // VIGRA_TRANSFORMIMAGE_HXX

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.3.2 (27 Jan 2005)