[ 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.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) |
html generated using doxygen and Python
|