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

| vigra/transformimage.hxx |
--- | --- | ---

    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)