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