Add OpenCV source code
[platform/upstream/opencv.git] / modules / contrib / src / templatebuffer.hpp
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 ** HVStools : 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 (hvstools)
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 //// If a parallelization method is available then, you should define MAKE_PARALLEL, in the other case, the classical serial code will be used
75 #define MAKE_PARALLEL
76 // ==> then include required includes
77 #ifdef MAKE_PARALLEL
78
79 // ==> declare usefull generic tools
80 template <class type>
81 class Parallel_clipBufferValues: public cv::ParallelLoopBody
82 {
83 private:
84     type *bufferToClip;
85     type minValue, maxValue;
86
87 public:
88     Parallel_clipBufferValues(type* bufferToProcess, const type min, const type max)
89         : bufferToClip(bufferToProcess), minValue(min), maxValue(max){}
90
91     virtual void operator()( const cv::Range &r ) const {
92         register type *inputOutputBufferPTR=bufferToClip+r.start;
93         for (register int jf = r.start; jf != r.end; ++jf, ++inputOutputBufferPTR)
94         {
95             if (*inputOutputBufferPTR>maxValue)
96                 *inputOutputBufferPTR=maxValue;
97             else if (*inputOutputBufferPTR<minValue)
98                 *inputOutputBufferPTR=minValue;
99         }
100     }
101 };
102 #endif
103
104 //#define __TEMPLATEBUFFERDEBUG //define TEMPLATEBUFFERDEBUG in order to display debug information
105
106 namespace cv
107 {
108     /**
109     * @class TemplateBuffer
110     * @brief this class is a simple template memory buffer which contains basic functions to get information on or normalize the buffer content
111     * 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.
112     * @author Alexandre BENOIT (benoit.alexandre.vision@gmail.com), helped by Gelu IONESCU (gelu.ionescu@lis.inpg.fr)
113     * creation date: september 2007
114     */
115     template <class type> class TemplateBuffer : public std::valarray<type>
116     {
117     public:
118
119         /**
120         * constructor for monodimensional array
121         * @param dim: the size of the vector
122         */
123         TemplateBuffer(const size_t dim=0)
124             : std::valarray<type>((type)0, dim)
125         {
126             _NBrows=1;
127             _NBcolumns=dim;
128             _NBdepths=1;
129             _NBpixels=dim;
130             _doubleNBpixels=2*dim;
131         }
132
133         /**
134         * constructor by copy for monodimensional array
135         * @param pVal: the pointer to a buffer to copy
136         * @param dim: the size of the vector
137         */
138         TemplateBuffer(const type* pVal, const size_t dim)
139             : std::valarray<type>(pVal, dim)
140         {
141             _NBrows=1;
142             _NBcolumns=dim;
143             _NBdepths=1;
144             _NBpixels=dim;
145             _doubleNBpixels=2*dim;
146         }
147
148         /**
149         * constructor for bidimensional array
150         * @param dimRows: the size of the vector
151         * @param dimColumns: the size of the vector
152         * @param depth: the number of layers of the buffer in its third dimension (3 of color images, 1 for gray images.
153         */
154         TemplateBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1)
155             : std::valarray<type>((type)0, dimRows*dimColumns*depth)
156         {
157 #ifdef TEMPLATEBUFFERDEBUG
158             std::cout<<"TemplateBuffer::TemplateBuffer: new buffer, size="<<dimRows<<", "<<dimColumns<<", "<<depth<<"valarraySize="<<this->size()<<std::endl;
159 #endif
160             _NBrows=dimRows;
161             _NBcolumns=dimColumns;
162             _NBdepths=depth;
163             _NBpixels=dimRows*dimColumns;
164             _doubleNBpixels=2*dimRows*dimColumns;
165             //_createTableIndex();
166 #ifdef TEMPLATEBUFFERDEBUG
167             std::cout<<"TemplateBuffer::TemplateBuffer: construction successful"<<std::endl;
168 #endif
169
170         }
171
172         /**
173         * copy constructor
174         * @param toCopy
175         * @return thenconstructed instance
176         *emplateBuffer(const TemplateBuffer &toCopy)
177         :_NBrows(toCopy.getNBrows()),_NBcolumns(toCopy.getNBcolumns()),_NBdepths(toCopy.getNBdephs()), _NBpixels(toCopy.getNBpixels()), _doubleNBpixels(toCopy.getNBpixels()*2)
178         //std::valarray<type>(toCopy)
179         {
180         memcpy(Buffer(), toCopy.Buffer(), this->size());
181         }*/
182         /**
183         * destructor
184         */
185         virtual ~TemplateBuffer()
186         {
187 #ifdef TEMPLATEBUFFERDEBUG
188             std::cout<<"~TemplateBuffer"<<std::endl;
189 #endif
190         }
191
192         /**
193         * delete the buffer content (set zeros)
194         */
195         inline void setZero(){std::valarray<type>::operator=(0);};//memset(Buffer(), 0, sizeof(type)*_NBpixels);};
196
197         /**
198         * @return the numbers of rows (height) of the images used by the object
199         */
200         inline unsigned int getNBrows(){return (unsigned int)_NBrows;};
201
202         /**
203         * @return the numbers of columns (width) of the images used by the object
204         */
205         inline unsigned int getNBcolumns(){return (unsigned int)_NBcolumns;};
206
207         /**
208         * @return the numbers of pixels (width*height) of the images used by the object
209         */
210         inline unsigned int getNBpixels(){return (unsigned int)_NBpixels;};
211
212         /**
213         * @return the numbers of pixels (width*height) of the images used by the object
214         */
215         inline unsigned int getDoubleNBpixels(){return (unsigned int)_doubleNBpixels;};
216
217         /**
218         * @return the numbers of depths (3rd dimension: 1 for gray images, 3 for rgb images) of the images used by the object
219         */
220         inline unsigned int getDepthSize(){return (unsigned int)_NBdepths;};
221
222         /**
223         * resize the buffer and recompute table index etc.
224         */
225         void resizeBuffer(const size_t dimRows, const size_t dimColumns, const size_t depth=1)
226         {
227             this->resize(dimRows*dimColumns*depth);
228             _NBrows=dimRows;
229             _NBcolumns=dimColumns;
230             _NBdepths=depth;
231             _NBpixels=dimRows*dimColumns;
232             _doubleNBpixels=2*dimRows*dimColumns;
233         }
234
235         inline TemplateBuffer<type> & operator=(const std::valarray<type> &b)
236         {
237             //std::cout<<"TemplateBuffer<type> & operator= affect vector: "<<std::endl;
238             std::valarray<type>::operator=(b);
239             return *this;
240         }
241
242         inline TemplateBuffer<type> & operator=(const type &b)
243         {
244             //std::cout<<"TemplateBuffer<type> & operator= affect value: "<<b<<std::endl;
245             std::valarray<type>::operator=(b);
246             return *this;
247         }
248
249         /*  inline const type  &operator[](const unsigned int &b)
250         {
251         return (*this)[b];
252         }
253         */
254         /**
255         * @return the buffer adress in non const mode
256         */
257         inline type*    Buffer()            {    return &(*this)[0];    }
258
259         ///////////////////////////////////////////////////////
260         // Standard Image manipulation functions
261
262         /**
263         * standard 0 to 255 image normalization function
264         * @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
265         * @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
266         * @param maxOutputValue: the maximum output value
267         */
268         static void normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t nbPixels, const type maxOutputValue=(type)255.0);
269
270         /**
271         * standard 0 to 255 image normalization function
272         * @param inputOutputBuffer: the image to be normalized (rewrites the input), if no parameter, then, the built in buffer reachable by getOutput() function is normalized
273         * @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
274         * @param maxOutputValue: the maximum output value
275         */
276         void normalizeGrayOutput_0_maxOutputValue(const type maxOutputValue=(type)255.0){normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue);};
277
278         /**
279         * sigmoide image normalization function (saturates min and max values)
280         * @param meanValue: specifies the mean value of th pixels to be processed
281         * @param sensitivity: strenght of the sigmoide
282         * @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized
283         * @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
284         * @param maxOutputValue: the maximum output value
285         */
286         static void normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputPicture, type *outputBuffer, const unsigned int nbPixels);
287
288         /**
289         * sigmoide image normalization function on the current buffer (saturates min and max values)
290         * @param meanValue: specifies the mean value of th pixels to be processed
291         * @param sensitivity: strenght of the sigmoide
292         * @param maxOutputValue: the maximum output value
293         */
294         inline void normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0, const type sensitivity=(type)2.0, const type maxOutputValue=(type)255.0){ (void)maxOutputValue; normalizeGrayOutputCentredSigmoide(meanValue, sensitivity, 255.0, this->Buffer(), this->Buffer(), this->getNBpixels());};
295
296         /**
297         * 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
298         * @param inputPicture: the image to be normalized if no parameter, then, the built in buffer reachable by getOutput() function is normalized
299         * @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
300         * @param sensitivity: strenght of the sigmoide
301         * @param maxOutputValue: the maximum output value
302         */
303         void normalizeGrayOutputNearZeroCentreredSigmoide(type *inputPicture=(type*)NULL, type *outputBuffer=(type*)NULL, const type sensitivity=(type)40, const type maxOutputValue=(type)255.0);
304
305         /**
306         * center and reduct the image (image-mean)/std
307         * @param inputOutputBuffer: the image to be normalized if no parameter, the result is rewrited on it
308         */
309         void centerReductImageLuminance(type *inputOutputBuffer=(type*)NULL);
310
311         /**
312         * @return standard deviation of the buffer
313         */
314         double getStandardDeviation()
315         {
316             double standardDeviation=0;
317             double meanValue=getMean();
318
319             type *bufferPTR=Buffer();
320             for (unsigned int i=0;i<this->size();++i)
321             {
322                 double diff=(*(bufferPTR++)-meanValue);
323                 standardDeviation+=diff*diff;
324             }
325             return sqrt(standardDeviation/this->size());
326         };
327
328         /**
329         * Clip buffer histogram
330         * @param minRatio: the minimum ratio of the lower pixel values, range=[0,1] and lower than maxRatio
331         * @param maxRatio: the aximum ratio of the higher pixel values, range=[0,1] and higher than minRatio
332         */
333         void clipHistogram(double minRatio, double maxRatio, double maxOutputValue)
334         {
335
336             if (minRatio>=maxRatio)
337             {
338                 std::cerr<<"TemplateBuffer::clipHistogram: minRatio must be inferior to maxRatio, buffer unchanged"<<std::endl;
339                 return;
340             }
341
342             /*    minRatio=min(max(minRatio, 1.0),0.0);
343             maxRatio=max(max(maxRatio, 0.0),1.0);
344             */
345
346             // find the pixel value just above the threshold
347             const double maxThreshold=this->max()*maxRatio;
348             const double minThreshold=(this->max()-this->min())*minRatio+this->min();
349
350             type *bufferPTR=this->Buffer();
351
352             double deltaH=maxThreshold;
353             double deltaL=maxThreshold;
354
355             double updatedHighValue=maxThreshold;
356             double updatedLowValue=maxThreshold;
357
358             for (unsigned int i=0;i<this->size();++i)
359             {
360                 double currentValue=(double)*(bufferPTR++);
361
362                 // updating "closest to the high threshold" pixel value
363                 double highValueTest=maxThreshold-currentValue;
364                 if (highValueTest>0)
365                 {
366                     if (deltaH>highValueTest)
367                     {
368                         deltaH=highValueTest;
369                         updatedHighValue=currentValue;
370                     }
371                 }
372
373                 // updating "closest to the low threshold" pixel value
374                 double lowValueTest=currentValue-minThreshold;
375                 if (lowValueTest>0)
376                 {
377                     if (deltaL>lowValueTest)
378                     {
379                         deltaL=lowValueTest;
380                         updatedLowValue=currentValue;
381                     }
382                 }
383             }
384
385             std::cout<<"Tdebug"<<std::endl;
386             std::cout<<"deltaL="<<deltaL<<", deltaH="<<deltaH<<std::endl;
387             std::cout<<"this->max()"<<this->max()<<"maxThreshold="<<maxThreshold<<"updatedHighValue="<<updatedHighValue<<std::endl;
388             std::cout<<"this->min()"<<this->min()<<"minThreshold="<<minThreshold<<"updatedLowValue="<<updatedLowValue<<std::endl;
389             // clipping values outside than the updated thresholds
390             bufferPTR=this->Buffer();
391 #ifdef MAKE_PARALLEL // call the TemplateBuffer multitreaded clipping method
392             parallel_for_(cv::Range(0,this->size()), Parallel_clipBufferValues<type>(bufferPTR, updatedLowValue, updatedHighValue));
393 #else
394
395             for (unsigned int i=0;i<this->size();++i, ++bufferPTR)
396             {
397                 if (*bufferPTR<updatedLowValue)
398                     *bufferPTR=updatedLowValue;
399                 else if (*bufferPTR>updatedHighValue)
400                     *bufferPTR=updatedHighValue;
401             }
402 #endif
403             normalizeGrayOutput_0_maxOutputValue(this->Buffer(), this->size(), maxOutputValue);
404
405         }
406
407         /**
408         * @return the mean value of the vector
409         */
410         inline double getMean(){return this->sum()/this->size();};
411
412     protected:
413         size_t _NBrows;
414         size_t _NBcolumns;
415         size_t _NBdepths;
416         size_t _NBpixels;
417         size_t _doubleNBpixels;
418         // utilities
419         static type _abs(const type x);
420
421     };
422
423     ///////////////////////////////////////////////////////////////////////
424     /// normalize output between 0 and 255, can be applied on images of different size that the declared size if nbPixels parameters is setted up;
425     template <class type>
426     void TemplateBuffer<type>::normalizeGrayOutput_0_maxOutputValue(type *inputOutputBuffer, const size_t processedPixels, const type maxOutputValue)
427     {
428         type maxValue=inputOutputBuffer[0], minValue=inputOutputBuffer[0];
429
430         // get the min and max value
431         register type *inputOutputBufferPTR=inputOutputBuffer;
432         for (register size_t j = 0; j<processedPixels; ++j)
433         {
434             type pixValue = *(inputOutputBufferPTR++);
435             if (maxValue < pixValue)
436                 maxValue = pixValue;
437             else if (minValue > pixValue)
438                 minValue = pixValue;
439         }
440         // change the range of the data to 0->255
441
442         type factor = maxOutputValue/(maxValue-minValue);
443         type offset = (type)(-minValue*factor);
444
445         inputOutputBufferPTR=inputOutputBuffer;
446         for (register size_t j = 0; j < processedPixels; ++j, ++inputOutputBufferPTR)
447             *inputOutputBufferPTR=*(inputOutputBufferPTR)*factor+offset;
448
449     }
450     // normalize data with a sigmoide close to 0 (saturates values for those superior to 0)
451     template <class type>
452     void TemplateBuffer<type>::normalizeGrayOutputNearZeroCentreredSigmoide(type *inputBuffer, type *outputBuffer, const type sensitivity, const type maxOutputValue)
453     {
454         if (inputBuffer==NULL)
455             inputBuffer=Buffer();
456         if (outputBuffer==NULL)
457             outputBuffer=Buffer();
458
459         type X0cube=sensitivity*sensitivity*sensitivity;
460
461         register type *inputBufferPTR=inputBuffer;
462         register type *outputBufferPTR=outputBuffer;
463
464         for (register size_t j = 0; j < _NBpixels; ++j, ++inputBufferPTR)
465         {
466
467             type currentCubeLuminance=*inputBufferPTR**inputBufferPTR**inputBufferPTR;
468             *(outputBufferPTR++)=maxOutputValue*currentCubeLuminance/(currentCubeLuminance+X0cube);
469         }
470     }
471
472     // normalize and adjust luminance with a centered to 128 sigmode
473     template <class type>
474     void TemplateBuffer<type>::normalizeGrayOutputCentredSigmoide(const type meanValue, const type sensitivity, const type maxOutputValue, type *inputBuffer, type *outputBuffer, const unsigned int nbPixels)
475     {
476
477         if (sensitivity==1.0)
478         {
479             std::cerr<<"TemplateBuffer::TemplateBuffer<type>::normalizeGrayOutputCentredSigmoide error: 2nd parameter (sensitivity) must not equal 0, copying original data..."<<std::endl;
480             memcpy(outputBuffer, inputBuffer, sizeof(type)*nbPixels);
481             return;
482         }
483
484         type X0=maxOutputValue/(sensitivity-(type)1.0);
485
486         register type *inputBufferPTR=inputBuffer;
487         register type *outputBufferPTR=outputBuffer;
488
489         for (register size_t j = 0; j < nbPixels; ++j, ++inputBufferPTR)
490             *(outputBufferPTR++)=(meanValue+(meanValue+X0)*(*(inputBufferPTR)-meanValue)/(_abs(*(inputBufferPTR)-meanValue)+X0));
491
492     }
493
494     // center and reduct the image (image-mean)/std
495     template <class type>
496     void TemplateBuffer<type>::centerReductImageLuminance(type *inputOutputBuffer)
497     {
498         // if outputBuffer unsassigned, the rewrite the buffer
499         if (inputOutputBuffer==NULL)
500             inputOutputBuffer=Buffer();
501         type meanValue=0, stdValue=0;
502
503         // compute mean value
504         for (register size_t j = 0; j < _NBpixels; ++j)
505             meanValue+=inputOutputBuffer[j];
506         meanValue/=((type)_NBpixels);
507
508         // compute std value
509         register type *inputOutputBufferPTR=inputOutputBuffer;
510         for (size_t index=0;index<_NBpixels;++index)
511         {
512             type inputMinusMean=*(inputOutputBufferPTR++)-meanValue;
513             stdValue+=inputMinusMean*inputMinusMean;
514         }
515
516         stdValue=sqrt(stdValue/((type)_NBpixels));
517         // adjust luminance in regard of mean and std value;
518         inputOutputBufferPTR=inputOutputBuffer;
519         for (size_t index=0;index<_NBpixels;++index, ++inputOutputBufferPTR)
520             *inputOutputBufferPTR=(*(inputOutputBufferPTR)-meanValue)/stdValue;
521     }
522
523
524     template <class type>
525     type TemplateBuffer<type>::_abs(const type x)
526     {
527
528         if (x>0)
529             return x;
530         else
531             return -x;
532     }
533
534     template < >
535     inline int TemplateBuffer<int>::_abs(const int x)
536     {
537         return std::abs(x);
538     }
539     template < >
540     inline double TemplateBuffer<double>::_abs(const double x)
541     {
542         return std::fabs(x);
543     }
544
545     template < >
546     inline float TemplateBuffer<float>::_abs(const float x)
547     {
548         return std::fabs(x);
549     }
550
551 }
552 #endif