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