1 /*#******************************************************************************
2 ** IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
3 **
4 ** By downloading, copying, installing or using the software you agree to this license.
5 ** If you do not agree to this license, do not download, install,
6 ** copy or use the software.
7 **
8 **
9 ** bioinspired : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab.
10 ** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping.
11 **
12 ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications)
13 **
14 **  Creation - enhancement process 2007-2011
15 **      Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France
16 **
17 ** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr).
18 ** Refer to the following research paper for more information:
19 ** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011
20 ** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book:
21 ** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891.
22 **
23 ** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author :
24 ** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper:
25 ** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007
26 ** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions.
27 ** ====> more informations in the above cited Jeanny Heraults's book.
28 **
29 **                          License Agreement
30 **               For Open Source Computer Vision Library
31 **
32 ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
33 ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
34 **
35 **               For Human Visual System tools (bioinspired)
36 ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
37 **
38 ** Third party copyrights are property of their respective owners.
39 **
40 ** Redistribution and use in source and binary forms, with or without modification,
41 ** are permitted provided that the following conditions are met:
42 **
43 ** * Redistributions of source code must retain the above copyright notice,
44 **    this list of conditions and the following disclaimer.
45 **
46 ** * Redistributions in binary form must reproduce the above copyright notice,
47 **    this list of conditions and the following disclaimer in the documentation
48 **    and/or other materials provided with the distribution.
49 **
50 ** * The name of the copyright holders may not be used to endorse or promote products
51 **    derived from this software without specific prior written permission.
52 **
53 ** This software is provided by the copyright holders and contributors "as is" and
54 ** any express or implied warranties, including, but not limited to, the implied
55 ** warranties of merchantability and fitness for a particular purpose are disclaimed.
56 ** In no event shall the Intel Corporation or contributors be liable for any direct,
57 ** indirect, incidental, special, exemplary, or consequential damages
58 ** (including, but not limited to, procurement of substitute goods or services;
59 ** loss of use, data, or profits; or business interruption) however caused
60 ** and on any theory of liability, whether in contract, strict liability,
61 ** or tort (including negligence or otherwise) arising in any way out of
62 ** the use of this software, even if advised of the possibility of such damage.
63 *******************************************************************************/
64 
65 #ifndef __TEMPLATEBUFFER_HPP__
66 #define __TEMPLATEBUFFER_HPP__
67 
68 #include <valarray>
69 #include <cstdlib>
70 #include <iostream>
71 #include <cmath>
72 
73 
74 //#define __TEMPLATEBUFFERDEBUG //define TEMPLATEBUFFERDEBUG in order to display debug information
75 
76 namespace cv
77 {
78 namespace bioinspired
79 {
80 //// If a parallelization method is available then, you should define MAKE_PARALLEL, in the other case, the classical serial code will be used
81 #define MAKE_PARALLEL
82 // ==> then include required includes
83 #ifdef MAKE_PARALLEL
84 
85 // ==> declare usefull generic tools
86 template <class type>
87 class Parallel_clipBufferValues: public cv::ParallelLoopBody
88 {
89 private:
90     type *bufferToClip;
91     type minValue, maxValue;
92 
93 public:
Parallel_clipBufferValues(type * bufferToProcess,const type min,const type max)94     Parallel_clipBufferValues(type* bufferToProcess, const type min, const type max)
95         : bufferToClip(bufferToProcess), minValue(min), maxValue(max) { }
96 
operator ()(const cv::Range & r) const97     virtual void operator()( const cv::Range &r ) const CV_OVERRIDE {
98         type *inputOutputBufferPTR=bufferToClip+r.start;
99         for (int jf = r.start; jf != r.end; ++jf, ++inputOutputBufferPTR)
100         {
101             if (*inputOutputBufferPTR>maxValue)
102                 *inputOutputBufferPTR=maxValue;
103             else if (*inputOutputBufferPTR<minValue)
104                 *inputOutputBufferPTR=minValue;
105         }
106     }
107 };
108 #endif
109 
110     /**
111     * @class TemplateBuffer
112     * @brief this class is a simple template memory buffer which contains basic functions to get information on or normalize the buffer content
113     * note that thanks to the parent STL template class "valarray", it is possible to perform easily operations on the full array such as addition, product etc.
114     * @author Alexandre BENOIT (benoit.alexandre.vision@gmail.com), helped by Gelu IONESCU (gelu.ionescu@lis.inpg.fr)
115     * creation date: september 2007
116     */
117     template <class type> class TemplateBuffer : public std::valarray<type>
118     {
119     public:
120 
121         /**
122         * constructor for monodimensional array
123         * @param dim: the size of the vector
124         */
TemplateBuffer(const size_t dim=0)125         TemplateBuffer(const size_t dim=0)
126             : std::valarray<type>((type)0, dim)
127         {
128             _NBrows=1;
129             _NBcolumns=dim;
130             _NBdepths=1;
131             _NBpixels=dim;
132             _doubleNBpixels=2*dim;
133         }
134 
135         /**
136         * constructor by copy for monodimensional array
137         * @param pVal: the pointer to a buffer to copy
138         * @param dim: the size of the vector
139         */
TemplateBuffer(const type * pVal,const size_t dim)140         TemplateBuffer(const type* pVal, const size_t dim)
141             : std::valarray<type>(pVal, dim)
142         {
143             _NBrows=1;
144             _NBcolumns=dim;
145             _NBdepths=1;
146             _NBpixels=dim;
147             _doubleNBpixels=2*dim;
148         }
149 
150         /**
151         * constructor for bidimensional array
152         * @param dimRows: the size of the vector
153         * @param dimColumns: the size of the vector
154         * @param depth: the number of layers of the buffer in its third dimension (3 of color images, 1 for gray images.
155         */
TemplateBuffer(const size_t dimRows,const size_t dimColumns,const size_t depth=1)156         TemplateBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1)
157             : std::valarray<type>((type)0, dimRows*dimColumns*depth)
158         {
159 #ifdef TEMPLATEBUFFERDEBUG
160             std::cout<<"TemplateBuffer::TemplateBuffer: new buffer, size="<<dimRows<<", "<<dimColumns<<", "<<depth<<"valarraySize="<<this->size()<<std::endl;
161 #endif
162             _NBrows=dimRows;
163             _NBcolumns=dimColumns;
164             _NBdepths=depth;
165             _NBpixels=dimRows*dimColumns;
166             _doubleNBpixels=2*dimRows*dimColumns;
167             //_createTableIndex();
168 #ifdef TEMPLATEBUFFERDEBUG
169             std::cout<<"TemplateBuffer::TemplateBuffer: construction successful"<<std::endl;
170 #endif
171 
172         }
173 
174         /**
175         * copy constructor
176         * @param toCopy
177         * @return thenconstructed instance
178         *emplateBuffer(const TemplateBuffer &toCopy)
179         :_NBrows(toCopy.getNBrows()),_NBcolumns(toCopy.getNBcolumns()),_NBdepths(toCopy.getNBdephs()), _NBpixels(toCopy.getNBpixels()), _doubleNBpixels(toCopy.getNBpixels()*2)
180         //std::valarray<type>(toCopy)
181         {
182         memcpy(Buffer(), toCopy.Buffer(), this->size());
183         }*/
184         /**
185         * destructor
186         */
~TemplateBuffer()187         virtual ~TemplateBuffer()
188         {
189 #ifdef TEMPLATEBUFFERDEBUG
190             std::cout<<"~TemplateBuffer"<<std::endl;
191 #endif
192         }
193 
194         /**
195         * delete the buffer content (set zeros)
196         */
setZero()197         inline void setZero() { std::valarray<type>::operator=(0); } //memset(Buffer(), 0, sizeof(type)*_NBpixels); }
198 
199         /**
200         * @return the numbers of rows (height) of the images used by the object
201         */
getNBrows()202         inline unsigned int getNBrows() { return (unsigned int)_NBrows; }
203 
204         /**
205         * @return the numbers of columns (width) of the images used by the object
206         */
getNBcolumns()207         inline unsigned int getNBcolumns() { return (unsigned int)_NBcolumns; }
208 
209         /**
210         * @return the numbers of pixels (width*height) of the images used by the object
211         */
getNBpixels()212         inline unsigned int getNBpixels() { return (unsigned int)_NBpixels; }
213 
214         /**
215         * @return the numbers of pixels (width*height) of the images used by the object
216         */
getDoubleNBpixels()217         inline unsigned int getDoubleNBpixels() { return (unsigned int)_doubleNBpixels; }
218 
219         /**
220         * @return the numbers of depths (3rd dimension: 1 for gray images, 3 for rgb images) of the images used by the object
221         */
getDepthSize()222         inline unsigned int getDepthSize() { return (unsigned int)_NBdepths; }
223 
224         /**
225         * resize the buffer and recompute table index etc.
226         */
resizeBuffer(const size_t dimRows,const size_t dimColumns,const size_t depth=1)227         void resizeBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1)
228         {
229             this->resize(dimRows*dimColumns*depth);
230             _NBrows=dimRows;
231             _NBcolumns=dimColumns;
232             _NBdepths=depth;
233             _NBpixels=dimRows*dimColumns;
234             _doubleNBpixels=2*dimRows*dimColumns;
235         }
236 
operator =(const std::valarray<type> & b)237         inline TemplateBuffer<type> & operator=(const std::valarray<type> &b)
238         {
239             //std::cout<<"TemplateBuffer<type> & operator= affect vector: "<<std::endl;
240             std::valarray<type>::operator=(b);
241             return *this;
242         }
243 
operator =(const type & b)244         inline TemplateBuffer<type> & operator=(const type &b)
245         {
246             //std::cout<<"TemplateBuffer<type> & operator= affect value: "<<b<<std::endl;
247             std::valarray<type>::operator=(b);
248             return *this;
249         }
250 
251         /*  inline const type  &operator[](const unsigned int &b)
252         {
253         return (*this)[b];
254         }
255         */
256         /**
257         * @return the buffer adress in non const mode
258         */
Buffer()259         inline type*    Buffer()            {    return &(*this)[0];    }
260 
261         ///////////////////////////////////////////////////////
262         // Standard Image manipulation functions
263 
264         /**
265         * standard 0 to 255 image normalization function
266         * @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
267         * @param nbPixels: specifies the number of pixel on which the normalization should be performed, if 0, then all pixels specified in the constructor are processed
268         * @param maxOutputValue: the maximum output value
269         */
270         static void normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t nbPixels, const type maxOutputValue=(type)255.0);
271 
272         /**
273         * standard 0 to 255 image normalization function
274         * @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
275         * @param nbPixels: specifies the number of pixel on which the normalization should be performed, if 0, then all pixels specified in the constructor are processed
276         * @param maxOutputValue: the maximum output value
277         */
normalizeGrayOutput_0_maxOutputValue(const type maxOutputValue=(type)255.0)278         void normalizeGrayOutput_0_maxOutputValue(const type maxOutputValue=(type)255.0) { normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue); }
279 
280         /**
281         * sigmoide image normalization function (saturates min and max values)
282         * @param meanValue: specifies the mean value of th pixels to be processed
283         * @param sensitivity: strength of the sigmoide
284         * @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized
285         * @param outputBuffer: the ouput buffer on which the result is writed, if no parameter, then, the built in buffer reachable by getOutput() function is normalized
286         * @param maxOutputValue: the maximum output value
287         */
288         static void normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputPicture, type *outputBuffer, const unsigned int nbPixels);
289 
290         /**
291         * sigmoide image normalization function on the current buffer (saturates min and max values)
292         * @param meanValue: specifies the mean value of th pixels to be processed
293         * @param sensitivity: strength of the sigmoide
294         * @param maxOutputValue: the maximum output value
295         */
normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0,const type sensitivity=(type)2.0,const type maxOutputValue=(type)255.0)296         inline void normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0, const type sensitivity=(type)2.0, const type maxOutputValue=(type)255.0) {  CV_UNUSED(maxOutputValue); normalizeGrayOutputCentredSigmoide(meanValue, sensitivity, 255.0, this->Buffer(), this->Buffer(), this->getNBpixels()); }
297 
298         /**
299         * sigmoide image normalization function (saturates min and max values), in this function, the sigmoide is centered on low values (high saturation of the medium and high values
300         * @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized
301         * @param outputBuffer: the ouput buffer on which the result is writed, if no parameter, then, the built in buffer reachable by getOutput() function is normalized
302         * @param sensitivity: strength of the sigmoide
303         * @param maxOutputValue: the maximum output value
304         */
305         void normalizeGrayOutputNearZeroCentreredSigmoide(type *inputPicture=(type*)NULL, type *outputBuffer=(type*)NULL, const type sensitivity=(type)40, const type maxOutputValue=(type)255.0);
306 
307         /**
308         * center and reduct the image (image-mean)/std
309         * @param inputOutputBuffer: the image to be normalized if no parameter, the result is rewrited on it
310         */
311         void centerReductImageLuminance(type *inputOutputBuffer=(type*)NULL);
312 
313         /**
314         * @return standard deviation of the buffer
315         */
getStandardDeviation()316         double getStandardDeviation()
317         {
318             double standardDeviation=0;
319             double meanValue=getMean();
320 
321             type *bufferPTR=Buffer();
322             for (unsigned int i=0;i<this->size();++i)
323             {
324                 double diff=(*(bufferPTR++)-meanValue);
325                 standardDeviation+=diff*diff;
326             }
327             return std::sqrt(standardDeviation/this->size());
328         }
329 
330         /**
331         * Clip buffer histogram
332         * @param minRatio: the minimum ratio of the lower pixel values, range=[0,1] and lower than maxRatio
333         * @param maxRatio: the aximum ratio of the higher pixel values, range=[0,1] and higher than minRatio
334         */
clipHistogram(double minRatio,double maxRatio,double maxOutputValue)335         void clipHistogram(double minRatio, double maxRatio, double maxOutputValue)
336         {
337 
338             if (minRatio>=maxRatio)
339             {
340                 std::cerr<<"TemplateBuffer::clipHistogram: minRatio must be inferior to maxRatio, buffer unchanged"<<std::endl;
341                 return;
342             }
343 
344             /*    minRatio=min(max(minRatio, 1.0),0.0);
345             maxRatio=max(max(maxRatio, 0.0),1.0);
346             */
347 
348             // find the pixel value just above the threshold
349             const double maxThreshold=this->max()*maxRatio;
350             const double minThreshold=(this->max()-this->min())*minRatio+this->min();
351 
352             type *bufferPTR=this->Buffer();
353 
354             double deltaH=maxThreshold;
355             double deltaL=maxThreshold;
356 
357             double updatedHighValue=maxThreshold;
358             double updatedLowValue=maxThreshold;
359 
360             for (unsigned int i=0;i<this->size();++i)
361             {
362                 double curentValue=(double)*(bufferPTR++);
363 
364                 // updating "closest to the high threshold" pixel value
365                 double highValueTest=maxThreshold-curentValue;
366                 if (highValueTest>0)
367                 {
368                     if (deltaH>highValueTest)
369                     {
370                         deltaH=highValueTest;
371                         updatedHighValue=curentValue;
372                     }
373                 }
374 
375                 // updating "closest to the low threshold" pixel value
376                 double lowValueTest=curentValue-minThreshold;
377                 if (lowValueTest>0)
378                 {
379                     if (deltaL>lowValueTest)
380                     {
381                         deltaL=lowValueTest;
382                         updatedLowValue=curentValue;
383                     }
384                 }
385             }
386 
387             std::cout<<"Tdebug"<<std::endl;
388             std::cout<<"deltaL="<<deltaL<<", deltaH="<<deltaH<<std::endl;
389             std::cout<<"this->max()"<<this->max()<<"maxThreshold="<<maxThreshold<<"updatedHighValue="<<updatedHighValue<<std::endl;
390             std::cout<<"this->min()"<<this->min()<<"minThreshold="<<minThreshold<<"updatedLowValue="<<updatedLowValue<<std::endl;
391             // clipping values outside than the updated thresholds
392             bufferPTR=this->Buffer();
393 #ifdef MAKE_PARALLEL // call the TemplateBuffer multitreaded clipping method
394             parallel_for_(cv::Range(0,this->size()), Parallel_clipBufferValues<type>(bufferPTR, updatedLowValue, updatedHighValue));
395 #else
396 
397             for (unsigned int i=0;i<this->size();++i, ++bufferPTR)
398             {
399                 if (*bufferPTR<updatedLowValue)
400                     *bufferPTR=updatedLowValue;
401                 else if (*bufferPTR>updatedHighValue)
402                     *bufferPTR=updatedHighValue;
403             }
404 #endif
405             normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue);
406 
407         }
408 
409         /**
410         * @return the mean value of the vector
411         */
getMean()412         inline double getMean() { return this->sum()/this->size(); }
413 
414     protected:
415         size_t _NBrows;
416         size_t _NBcolumns;
417         size_t _NBdepths;
418         size_t _NBpixels;
419         size_t _doubleNBpixels;
420         // utilities
421         static type _abs(const type x);
422 
423     };
424 
425     ///////////////////////////////////////////////////////////////////////
426     /// normalize output between 0 and 255, can be applied on images of different size that the declared size if nbPixels parameters is setted up;
427     template <class type>
normalizeGrayOutput_0_maxOutputValue(type * inputOutputBuffer,const size_t processedPixels,const type maxOutputValue)428     void TemplateBuffer<type>::normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t processedPixels, const type maxOutputValue)
429     {
430         type maxValue=inputOutputBuffer[0], minValue=inputOutputBuffer[0];
431 
432         // get the min and max value
433         type *inputOutputBufferPTR=inputOutputBuffer;
434         for (size_t j = 0; j<processedPixels; ++j)
435         {
436             type pixValue = *(inputOutputBufferPTR++);
437             if (maxValue < pixValue)
438                 maxValue = pixValue;
439             else if (minValue > pixValue)
440                 minValue = pixValue;
441         }
442         // change the range of the data to 0->255
443 
444         type factor = maxOutputValue/(maxValue-minValue);
445         type offset = (type)(-minValue*factor);
446 
447         inputOutputBufferPTR=inputOutputBuffer;
448         for (size_t j = 0; j < processedPixels; ++j, ++inputOutputBufferPTR)
449             *inputOutputBufferPTR=*(inputOutputBufferPTR)*factor+offset;
450 
451     }
452     // normalize data with a sigmoide close to 0 (saturates values for those superior to 0)
453     template <class type>
normalizeGrayOutputNearZeroCentreredSigmoide(type * inputBuffer,type * outputBuffer,const type sensitivity,const type maxOutputValue)454     void TemplateBuffer<type>::normalizeGrayOutputNearZeroCentreredSigmoide(type *inputBuffer, type *outputBuffer, const type sensitivity, const type maxOutputValue)
455     {
456         if (inputBuffer==NULL)
457             inputBuffer=Buffer();
458         if (outputBuffer==NULL)
459             outputBuffer=Buffer();
460 
461         type X0cube=sensitivity*sensitivity*sensitivity;
462 
463         type *inputBufferPTR=inputBuffer;
464         type *outputBufferPTR=outputBuffer;
465 
466         for (size_t j = 0; j < _NBpixels; ++j, ++inputBufferPTR)
467         {
468 
469             type currentCubeLuminance=*inputBufferPTR**inputBufferPTR**inputBufferPTR;
470             *(outputBufferPTR++)=maxOutputValue*currentCubeLuminance/(currentCubeLuminance+X0cube);
471         }
472     }
473 
474     // normalize and adjust luminance with a centered to 128 sigmode
475     template <class type>
normalizeGrayOutputCentredSigmoide(const type meanValue,const type sensitivity,const type maxOutputValue,type * inputBuffer,type * outputBuffer,const unsigned int nbPixels)476     void TemplateBuffer<type>::normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputBuffer, type *outputBuffer, const unsigned int nbPixels)
477     {
478 
479         if (sensitivity==1.0)
480         {
481             std::cerr<<"TemplateBuffer::TemplateBuffer<type>::normalizeGrayOutputCentredSigmoide error: 2nd parameter (sensitivity) must not equal 0, copying original data..."<<std::endl;
482             memcpy(outputBuffer, inputBuffer, sizeof(type)*nbPixels);
483             return;
484         }
485 
486         type X0=maxOutputValue/(sensitivity-(type)1.0);
487 
488         type *inputBufferPTR=inputBuffer;
489         type *outputBufferPTR=outputBuffer;
490 
491         for (size_t j = 0; j < nbPixels; ++j, ++inputBufferPTR)
492             *(outputBufferPTR++)=(meanValue+(meanValue+X0)*(*(inputBufferPTR)-meanValue)/(_abs(*(inputBufferPTR)-meanValue)+X0));
493 
494     }
495 
496     // center and reduct the image (image-mean)/std
497     template <class type>
centerReductImageLuminance(type * inputOutputBuffer)498     void TemplateBuffer<type>::centerReductImageLuminance(type *inputOutputBuffer)
499     {
500         // if outputBuffer unsassigned, the rewrite the buffer
501         if (inputOutputBuffer==NULL)
502             inputOutputBuffer=Buffer();
503         type meanValue=0, stdValue=0;
504 
505         // compute mean value
506         for (size_t j = 0; j < _NBpixels; ++j)
507             meanValue+=inputOutputBuffer[j];
508         meanValue/=((type)_NBpixels);
509 
510         // compute std value
511         type *inputOutputBufferPTR=inputOutputBuffer;
512         for (size_t index=0;index<_NBpixels;++index)
513         {
514             type inputMinusMean=*(inputOutputBufferPTR++)-meanValue;
515             stdValue+=inputMinusMean*inputMinusMean;
516         }
517 
518         stdValue=std::sqrt(stdValue/((type)_NBpixels));
519         // adjust luminance in regard of mean and std value;
520         inputOutputBufferPTR=inputOutputBuffer;
521         for (size_t index=0;index<_NBpixels;++index, ++inputOutputBufferPTR)
522             *inputOutputBufferPTR=(*(inputOutputBufferPTR)-meanValue)/stdValue;
523     }
524 
525 
526     template <class type>
_abs(const type x)527     type TemplateBuffer<type>::_abs(const type x)
528     {
529 
530         if (x>0)
531             return x;
532         else
533             return -x;
534     }
535 
536     template < >
_abs(const int x)537     inline int TemplateBuffer<int>::_abs(const int x)
538     {
539         return std::abs(x);
540     }
541     template < >
_abs(const double x)542     inline double TemplateBuffer<double>::_abs(const double x)
543     {
544         return std::fabs(x);
545     }
546 
547     template < >
_abs(const float x)548     inline float TemplateBuffer<float>::_abs(const float x)
549     {
550         return std::fabs(x);
551     }
552 
553 }// end of namespace bioinspired
554 }// end of namespace cv
555 #endif
556