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