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 BASICRETINAELEMENT_HPP_ 66 #define BASICRETINAELEMENT_HPP_ 67 68 #include <cstring> 69 70 71 /** 72 * @class BasicRetinaFilter 73 * @brief Brief overview, this class provides tools for low level image processing: 74 * --> this class is able to perform: 75 * -> first order Low pass optimized filtering 76 * -> local luminance adaptation (able to correct back light problems and contrast enhancement) 77 * -> progressive low pass filter filtering (higher filtering on the borders than on the center) 78 * -> image data between 0 and 255 resampling with different options, linear rescaling, sigmoide) 79 * 80 * NOTE : initially the retina model was based on double format scalar values but 81 * a good memory/precision compromise is float... 82 * also the double format precision does not make so much sense from a biological point of view (neurons value coding is not so precise) 83 * 84 * TYPICAL USE: 85 * 86 * // create object at a specified picture size 87 * BasicRetinaFilter *_photoreceptorsPrefilter; 88 * _photoreceptorsPrefilter =new BasicRetinaFilter(sizeRows, sizeWindows); 89 * 90 * // init gain, spatial and temporal parameters: 91 * _photoreceptorsPrefilter->setCoefficientsTable(gain,temporalConstant, spatialConstant); 92 * 93 * // during program execution, call the filter for local luminance correction or low pass filtering for an input picture called "FrameBuffer": 94 * _photoreceptorsPrefilter->runFilter_LocalAdapdation(FrameBuffer); 95 * // or (Low pass first order filter) 96 * _photoreceptorsPrefilter->runFilter_LPfilter(FrameBuffer); 97 * // get output frame and its size: 98 * const unsigned int output_nbRows=_photoreceptorsPrefilter->getNBrows(); 99 * const unsigned int output_nbColumns=_photoreceptorsPrefilter->getNBcolumns(); 100 * const double *outputFrame=_photoreceptorsPrefilter->getOutput(); 101 * 102 * // at the end of the program, destroy object: 103 * delete _photoreceptorsPrefilter; 104 105 * @author Alexandre BENOIT, benoit.alexandre.vision@gmail.com, LISTIC : www.listic.univ-savoie.fr, Gipsa-Lab, France: www.gipsa-lab.inpg.fr/ 106 * Creation date 2007 107 * synthesis of the work described in Alexandre BENOIT thesis: "Le systeme visuel humain au secours de la vision par ordinateur" 108 */ 109 110 #include <iostream> 111 #include "templatebuffer.hpp" 112 113 //#define __BASIC_RETINA_ELEMENT_DEBUG 114 115 namespace cv 116 { 117 namespace bioinspired 118 { 119 class BasicRetinaFilter 120 { 121 public: 122 123 /** 124 * constructor of the base bio-inspired toolbox, parameters are only linked to imae input size and number of filtering capabilities of the object 125 * @param NBrows: number of rows of the input image 126 * @param NBcolumns: number of columns of the input image 127 * @param parametersListSize: specifies the number of parameters set (each parameters set represents a specific low pass spatio-temporal filter) 128 * @param useProgressiveFilter: specifies if the filter has irreguar (progressive) filtering capabilities (this can be activated later using setProgressiveFilterConstants_xxx methods) 129 */ 130 BasicRetinaFilter(const unsigned int NBrows, const unsigned int NBcolumns, const unsigned int parametersListSize=1, const bool useProgressiveFilter=false); 131 132 /** 133 * standrad destructore 134 */ 135 ~BasicRetinaFilter(); 136 137 /** 138 * function which clears the output buffer of the object 139 */ clearOutputBuffer()140 inline void clearOutputBuffer() { _filterOutput = 0; } 141 142 /** 143 * function which clears the secondary buffer of the object 144 */ clearSecondaryBuffer()145 inline void clearSecondaryBuffer() { _localBuffer = 0; } 146 147 /** 148 * function which clears the output and the secondary buffer of the object 149 */ clearAllBuffers()150 inline void clearAllBuffers() { clearOutputBuffer(); clearSecondaryBuffer(); } 151 152 /** 153 * resize basic retina filter object (resize all allocated buffers 154 * @param NBrows: the new height size 155 * @param NBcolumns: the new width size 156 */ 157 void resize(const unsigned int NBrows, const unsigned int NBcolumns); 158 159 /** 160 * forbiden method inherited from parent std::valarray 161 * prefer not to use this method since the filter matrix become vectors 162 */ resize(const unsigned int)163 void resize(const unsigned int) { std::cerr<<"error, not accessible method"<<std::endl; } 164 165 /** 166 * low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors) 167 * @param inputFrame: the input image to be processed 168 * @param filterIndex: the offset which specifies the parameter set that should be used for the filtering 169 * @return the processed image, the output is reachable later by using function getOutput() 170 */ 171 const std::valarray<float> &runFilter_LPfilter(const std::valarray<float> &inputFrame, const unsigned int filterIndex=0); // run the LP filter for a new frame input and save result in _filterOutput 172 173 /** 174 * low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors) 175 * @param inputFrame: the input image to be processed 176 * @param outputFrame: the output buffer in which the result is writed 177 * @param filterIndex: the offset which specifies the parameter set that should be used for the filtering 178 */ 179 void runFilter_LPfilter(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame, const unsigned int filterIndex=0); // run LP filter on a specific output adress 180 181 /** 182 * low pass filter call and run (models the homogeneous cells network at the retina level, for example horizontal cells or photoreceptors) 183 * @param inputOutputFrame: the input image to be processed on which the result is rewrited 184 * @param filterIndex: the offset which specifies the parameter set that should be used for the filtering 185 */ 186 void runFilter_LPfilter_Autonomous(std::valarray<float> &inputOutputFrame, const unsigned int filterIndex=0);// run LP filter on the input data and rewrite it 187 188 /** 189 * local luminance adaptation call and run (contrast enhancement property of the photoreceptors) 190 * @param inputOutputFrame: the input image to be processed 191 * @param localLuminance: an image which represents the local luminance of the inputFrame parameter, in general, it is its low pass spatial filtering 192 * @return the processed image, the output is reachable later by using function getOutput() 193 */ 194 const std::valarray<float> &runFilter_LocalAdapdation(const std::valarray<float> &inputOutputFrame, const std::valarray<float> &localLuminance);// run local adaptation filter and save result in _filterOutput 195 196 /** 197 * local luminance adaptation call and run (contrast enhancement property of the photoreceptors) 198 * @param inputFrame: the input image to be processed 199 * @param localLuminance: an image which represents the local luminance of the inputFrame parameter, in general, it is its low pass spatial filtering 200 * @param outputFrame: the output buffer in which the result is writed 201 */ 202 void runFilter_LocalAdapdation(const std::valarray<float> &inputFrame, const std::valarray<float> &localLuminance, std::valarray<float> &outputFrame); // run local adaptation filter on a specific output adress 203 204 /** 205 * local luminance adaptation call and run (contrast enhancement property of the photoreceptors) 206 * @param inputFrame: the input image to be processed 207 * @return the processed image, the output is reachable later by using function getOutput() 208 */ 209 const std::valarray<float> &runFilter_LocalAdapdation_autonomous(const std::valarray<float> &inputFrame);// run local adaptation filter and save result in _filterOutput 210 211 /** 212 * local luminance adaptation call and run (contrast enhancement property of the photoreceptors) 213 * @param inputFrame: the input image to be processed 214 * @param outputFrame: the output buffer in which the result is writen 215 */ 216 void runFilter_LocalAdapdation_autonomous(const std::valarray<float> &inputFrame, std::valarray<float> &outputFrame); // run local adaptation filter on a specific output adress 217 218 /** 219 * run low pass filtering with progressive parameters (models the retina log sampling of the photoreceptors and its low pass filtering effect consequence: more powerfull low pass filtering effect on the corners) 220 * @param inputFrame: the input image to be processed 221 * @param filterIndex: the index which specifies the parameter set that should be used for the filtering 222 * @return the processed image, the output is reachable later by using function getOutput() if outputFrame is NULL 223 */ runProgressiveFilter(std::valarray<float> & inputFrame,const unsigned int filterIndex=0)224 inline void runProgressiveFilter(std::valarray<float> &inputFrame, const unsigned int filterIndex=0) { _spatiotemporalLPfilter_Irregular(&inputFrame[0], filterIndex); } 225 226 /** 227 * run low pass filtering with progressive parameters (models the retina log sampling of the photoreceptors and its low pass filtering effect consequence: more powerfull low pass filtering effect on the corners) 228 * @param inputFrame: the input image to be processed 229 * @param outputFrame: the output buffer in which the result is writen 230 * @param filterIndex: the index which specifies the parameter set that should be used for the filtering 231 */ runProgressiveFilter(const std::valarray<float> & inputFrame,std::valarray<float> & outputFrame,const unsigned int filterIndex=0)232 inline void runProgressiveFilter(const std::valarray<float> &inputFrame, 233 std::valarray<float> &outputFrame, 234 const unsigned int filterIndex=0) 235 {_spatiotemporalLPfilter_Irregular(get_data(inputFrame), &outputFrame[0], filterIndex); } 236 237 /** 238 * first order spatio-temporal low pass filter setup function 239 * @param beta: gain of the filter (generally set to zero) 240 * @param tau: time constant of the filter (unit is frame for video processing) 241 * @param k: spatial constant of the filter (unit is pixels) 242 * @param filterIndex: the index which specifies the parameter set that should be used for the filtering 243 */ 244 void setLPfilterParameters(const float beta, const float tau, const float k, const unsigned int filterIndex=0); // change the parameters of the filter 245 246 /** 247 * first order spatio-temporal low pass filter setup function 248 * @param beta: gain of the filter (generally set to zero) 249 * @param tau: time constant of the filter (unit is frame for video processing) 250 * @param alpha0: spatial constant of the filter (unit is pixels) on the border of the image 251 * @param filterIndex: the index which specifies the parameter set that should be used for the filtering 252 */ 253 void setProgressiveFilterConstants_CentredAccuracy(const float beta, const float tau, const float alpha0, const unsigned int filterIndex=0); 254 255 /** 256 * first order spatio-temporal low pass filter setup function 257 * @param beta: gain of the filter (generally set to zero) 258 * @param tau: time constant of the filter (unit is frame for video processing) 259 * @param alpha0: spatial constant of the filter (unit is pixels) on the border of the image 260 * @param accuracyMap an image (float format) which values range is between 0 and 1, where 0 means, apply no filtering and 1 means apply the filtering as specified in the parameters set, intermediate values allow to smooth variations of the filtering strength 261 * @param filterIndex: the index which specifies the parameter set that should be used for the filtering 262 */ 263 void setProgressiveFilterConstants_CustomAccuracy(const float beta, const float tau, const float alpha0, const std::valarray<float> &accuracyMap, const unsigned int filterIndex=0); 264 265 /** 266 * local luminance adaptation setup, this function should be applied for normal local adaptation (not for tone mapping operation) 267 * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect 268 * @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous) 269 * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) 270 */ setV0CompressionParameter(const float v0,const float maxInputValue,const float)271 void setV0CompressionParameter(const float v0, const float maxInputValue, const float) 272 { 273 _v0=v0*maxInputValue; 274 _localLuminanceFactor=v0; 275 _localLuminanceAddon=maxInputValue*(1.0f-v0); 276 _maxInputValue=maxInputValue; 277 } 278 279 /** 280 * update local luminance adaptation setup, initial maxInputValue is kept. This function should be applied for normal local adaptation (not for tone mapping operation) 281 * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect 282 * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) 283 */ setV0CompressionParameter(const float v0,const float meanLuminance)284 void setV0CompressionParameter(const float v0, const float meanLuminance) { this->setV0CompressionParameter(v0, _maxInputValue, meanLuminance); } 285 286 /** 287 * local luminance adaptation setup, this function should be applied for normal local adaptation (not for tone mapping operation) 288 * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect 289 */ setV0CompressionParameter(const float v0)290 void setV0CompressionParameter(const float v0) 291 { 292 _v0=v0*_maxInputValue; 293 _localLuminanceFactor=v0; 294 _localLuminanceAddon=_maxInputValue*(1.0f-v0); 295 } 296 297 /** 298 * local luminance adaptation setup, this function should be applied for local adaptation applied to tone mapping operation 299 * @param v0: compression effect for the local luminance adaptation processing, set a value between 0.6 and 0.9 for best results, a high value yields to a high compression effect 300 * @param maxInputValue: the maximum amplitude value measured after local adaptation processing (c.f. function runFilter_LocalAdapdation & runFilter_LocalAdapdation_autonomous) 301 * @param meanLuminance: the a priori meann luminance of the input data (should be 128 for 8bits images but can vary greatly in case of High Dynamic Range Images (HDRI) 302 */ setV0CompressionParameterToneMapping(const float v0,const float maxInputValue,const float meanLuminance=128.0f)303 void setV0CompressionParameterToneMapping(const float v0, const float maxInputValue, const float meanLuminance=128.0f) 304 { 305 _v0=v0*maxInputValue; 306 _localLuminanceFactor=1.0f; 307 _localLuminanceAddon=meanLuminance*v0; 308 _maxInputValue=maxInputValue; 309 } 310 311 /** 312 * update compression parameters while keeping v0 parameter value 313 * @param meanLuminance the input frame mean luminance 314 */ updateCompressionParameter(const float meanLuminance)315 inline void updateCompressionParameter(const float meanLuminance) 316 { 317 _localLuminanceFactor=1; 318 _localLuminanceAddon=meanLuminance*_v0; 319 } 320 321 /** 322 * @return the v0 compression parameter used to compute the local adaptation 323 */ getV0CompressionParameter()324 float getV0CompressionParameter() { return _v0/_maxInputValue; } 325 326 /** 327 * @return the output result of the object 328 */ getOutput() const329 inline const std::valarray<float> &getOutput() const { return _filterOutput; } 330 331 /** 332 * @return number of rows of the filter 333 */ getNBrows()334 inline unsigned int getNBrows() { return _filterOutput.getNBrows(); } 335 336 /** 337 * @return number of columns of the filter 338 */ getNBcolumns()339 inline unsigned int getNBcolumns() { return _filterOutput.getNBcolumns(); } 340 341 /** 342 * @return number of pixels of the filter 343 */ getNBpixels()344 inline unsigned int getNBpixels() { return _filterOutput.getNBpixels(); } 345 346 /** 347 * force filter output to be normalized between 0 and maxValue 348 * @param maxValue: the maximum output value that is required 349 */ normalizeGrayOutput_0_maxOutputValue(const float maxValue)350 inline void normalizeGrayOutput_0_maxOutputValue(const float maxValue) { _filterOutput.normalizeGrayOutput_0_maxOutputValue(maxValue); } 351 352 /** 353 * force filter output to be normalized around 0 and rescaled with a sigmoide effect (extrem values saturation) 354 * @param maxValue: the maximum output value that is required 355 */ normalizeGrayOutputCentredSigmoide()356 inline void normalizeGrayOutputCentredSigmoide() { _filterOutput.normalizeGrayOutputCentredSigmoide(); } 357 358 /** 359 * force filter output to be normalized : data centering and std normalisation 360 * @param maxValue: the maximum output value that is required 361 */ centerReductImageLuminance()362 inline void centerReductImageLuminance() { _filterOutput.centerReductImageLuminance(); } 363 364 /** 365 * @return the maximum input buffer value 366 */ getMaxInputValue()367 inline float getMaxInputValue() { return _maxInputValue; } 368 369 /** 370 * @return the maximum input buffer value 371 */ setMaxInputValue(const float newMaxInputValue)372 inline void setMaxInputValue(const float newMaxInputValue) { this->_maxInputValue=newMaxInputValue; } 373 374 protected: 375 376 ///////////////////////// 377 // data buffers 378 TemplateBuffer<float> _filterOutput; // primary buffer (contains processing outputs) 379 std::valarray<float> _localBuffer; // local secondary buffer 380 ///////////////////////// 381 // PARAMETERS 382 unsigned int _halfNBrows; 383 unsigned int _halfNBcolumns; 384 385 // parameters buffers 386 std::valarray <float>_filteringCoeficientsTable; 387 std::valarray <float>_progressiveSpatialConstant;// pointer to a local table containing local spatial constant (allocated with the object) 388 std::valarray <float>_progressiveGain;// pointer to a local table containing local spatial constant (allocated with the object) 389 390 // local adaptation filtering parameters 391 float _v0; //value used for local luminance adaptation function 392 float _maxInputValue; 393 float _meanInputValue; 394 float _localLuminanceFactor; 395 float _localLuminanceAddon; 396 397 // protected data related to standard low pass filters parameters 398 float _a; 399 float _tau; 400 float _gain; 401 402 ///////////////////////// 403 // FILTERS METHODS 404 405 // Basic low pass spation temporal low pass filter used by each retina filters 406 void _spatiotemporalLPfilter(const float *inputFrame, float *LPfilterOutput, const unsigned int coefTableOffset=0); 407 float _squaringSpatiotemporalLPfilter(const float *inputFrame, float *outputFrame, const unsigned int filterIndex=0); 408 409 // LP filter with an irregular spatial filtering 410 411 // -> rewrites the input buffer 412 void _spatiotemporalLPfilter_Irregular(float *inputOutputFrame, const unsigned int filterIndex=0); 413 // writes the output on another buffer 414 void _spatiotemporalLPfilter_Irregular(const float *inputFrame, float *outputFrame, const unsigned int filterIndex=0); 415 // LP filter that squares the input and computes the output ONLY on the areas where the integrationAreas map are TRUE 416 void _localSquaringSpatioTemporalLPfilter(const float *inputFrame, float *LPfilterOutput, const unsigned int *integrationAreas, const unsigned int filterIndex=0); 417 418 // local luminance adaptation of the input in regard of localLuminance buffer 419 void _localLuminanceAdaptation(const float *inputFrame, const float *localLuminance, float *outputFrame, const bool updateLuminanceMean=true); 420 // local luminance adaptation of the input in regard of localLuminance buffer, the input is rewrited and becomes the output 421 void _localLuminanceAdaptation(float *inputOutputFrame, const float *localLuminance); 422 // local adaptation applied on a range of values which can be positive and negative 423 void _localLuminanceAdaptationPosNegValues(const float *inputFrame, const float *localLuminance, float *outputFrame); 424 425 426 ////////////////////////////////////////////////////////////// 427 // 1D directional filters used for the 2D low pass filtering 428 429 // 1D filters with image input 430 void _horizontalCausalFilter_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); 431 // 1D filters with image input that is squared in the function // parallelized with TBB 432 void _squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); 433 // vertical anticausal filter that returns the mean value of its result 434 float _verticalAnticausalFilter_returnMeanValue(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); 435 436 // most simple functions: only perform 1D filtering with output=input (no add on) 437 void _horizontalCausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); 438 void _horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); // parallelized with TBB 439 void _verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // parallelized with TBB 440 void _verticalAnticausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); 441 442 // perform 1D filtering with output with varrying spatial coefficient 443 void _horizontalCausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); 444 void _horizontalCausalFilter_Irregular_addInput(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd); 445 void _horizontalAnticausalFilter_Irregular(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const float *spatialConstantBuffer); // parallelized with TBB 446 void _verticalCausalFilter_Irregular(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const float *spatialConstantBuffer); // parallelized with TBB 447 void _verticalAnticausalFilter_Irregular_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); 448 449 450 // 1D filters in which the output is multiplied by _gain 451 void _verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // this functions affects _gain at the output // parallelized with TBB 452 void _horizontalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd); // this functions affects _gain at the output 453 454 // LP filter on specific parts of the picture instead of all the image 455 // same functions (some of them) but take a binary flag to allow integration, false flag means, 0 at the output... 456 void _local_squaringHorizontalCausalFilter(const float *inputFrame, float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas); 457 void _local_horizontalAnticausalFilter(float *outputFrame, unsigned int IDrowStart, unsigned int IDrowEnd, const unsigned int *integrationAreas); 458 void _local_verticalCausalFilter(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas); 459 void _local_verticalAnticausalFilter_multGain(float *outputFrame, unsigned int IDcolumnStart, unsigned int IDcolumnEnd, const unsigned int *integrationAreas); // this functions affects _gain at the output 460 461 #ifdef MAKE_PARALLEL 462 /****************************************************** 463 ** IF some parallelizing thread methods are available, then, main loops are parallelized using these functors 464 ** ==> main idea paralellise main filters loops, then, only the most used methods are parallelized... TODO : increase the number of parallelised methods as necessary 465 ** ==> functors names = Parallel_$$$ where $$$= the name of the serial method that is parallelised 466 ** ==> functors constructors can differ from the parameters used with their related serial functions 467 */ 468 469 #define _DEBUG_TBB // define DEBUG_TBB in order to display additionnal data on stdout 470 class Parallel_horizontalAnticausalFilter: public cv::ParallelLoopBody 471 { 472 private: 473 float *outputFrame; 474 unsigned int IDrowEnd, nbColumns; 475 float filterParam_a; 476 public: 477 // constructor which takes the input image pointer reference reference and limits Parallel_horizontalAnticausalFilter(float * bufferToProcess,const unsigned int idEnd,const unsigned int nbCols,const float a)478 Parallel_horizontalAnticausalFilter(float *bufferToProcess, const unsigned int idEnd, const unsigned int nbCols, const float a ) 479 :outputFrame(bufferToProcess), IDrowEnd(idEnd), nbColumns(nbCols), filterParam_a(a) 480 { 481 #ifdef DEBUG_TBB 482 std::cout<<"Parallel_horizontalAnticausalFilter::Parallel_horizontalAnticausalFilter :" 483 <<"\n\t idEnd="<<IDrowEnd 484 <<"\n\t nbCols="<<nbColumns 485 <<"\n\t filterParam="<<filterParam_a 486 <<std::endl; 487 #endif 488 } 489 operator ()(const Range & r) const490 virtual void operator()( const Range& r ) const CV_OVERRIDE { 491 492 #ifdef DEBUG_TBB 493 std::cout<<"Parallel_horizontalAnticausalFilter::operator() :" 494 <<"\n\t range size="<<r.size() 495 <<"\n\t first index="<<r.start 496 //<<"\n\t last index="<<filterParam 497 <<std::endl; 498 #endif 499 for (int IDrow=r.start; IDrow!=r.end; ++IDrow) 500 { 501 float* outputPTR=outputFrame+(IDrowEnd-IDrow)*(nbColumns)-1; 502 float result=0; 503 for (unsigned int index=0; index<nbColumns; ++index) 504 { 505 result = *(outputPTR)+ filterParam_a* result; 506 *(outputPTR--) = result; 507 } 508 } 509 } 510 }; 511 512 class Parallel_horizontalCausalFilter_addInput: public cv::ParallelLoopBody 513 { 514 private: 515 const float *inputFrame; 516 float *outputFrame; 517 unsigned int IDrowStart, nbColumns; 518 float filterParam_a, filterParam_tau; 519 public: Parallel_horizontalCausalFilter_addInput(const float * bufferToAddAsInputProcess,float * bufferToProcess,const unsigned int idStart,const unsigned int nbCols,const float a,const float tau)520 Parallel_horizontalCausalFilter_addInput(const float *bufferToAddAsInputProcess, float *bufferToProcess, const unsigned int idStart, const unsigned int nbCols, const float a, const float tau) 521 :inputFrame(bufferToAddAsInputProcess), outputFrame(bufferToProcess), IDrowStart(idStart), nbColumns(nbCols), filterParam_a(a), filterParam_tau(tau){} 522 operator ()(const Range & r) const523 virtual void operator()( const Range& r ) const CV_OVERRIDE { 524 for (int IDrow=r.start; IDrow!=r.end; ++IDrow) 525 { 526 float* outputPTR=outputFrame+(IDrowStart+IDrow)*nbColumns; 527 const float* inputPTR=inputFrame+(IDrowStart+IDrow)*nbColumns; 528 float result=0; 529 for (unsigned int index=0; index<nbColumns; ++index) 530 { 531 result = *(inputPTR++) + filterParam_tau**(outputPTR)+ filterParam_a* result; 532 *(outputPTR++) = result; 533 } 534 } 535 } 536 }; 537 538 class Parallel_verticalCausalFilter: public cv::ParallelLoopBody 539 { 540 private: 541 float *outputFrame; 542 unsigned int nbRows, nbColumns; 543 float filterParam_a; 544 public: Parallel_verticalCausalFilter(float * bufferToProcess,const unsigned int nbRws,const unsigned int nbCols,const float a)545 Parallel_verticalCausalFilter(float *bufferToProcess, const unsigned int nbRws, const unsigned int nbCols, const float a ) 546 :outputFrame(bufferToProcess), nbRows(nbRws), nbColumns(nbCols), filterParam_a(a){} 547 operator ()(const Range & r) const548 virtual void operator()( const Range& r ) const CV_OVERRIDE { 549 for (int IDcolumn=r.start; IDcolumn!=r.end; ++IDcolumn) 550 { 551 float result=0; 552 float *outputPTR=outputFrame+IDcolumn; 553 554 for (unsigned int index=0; index<nbRows; ++index) 555 { 556 result = *(outputPTR) + filterParam_a * result; 557 *(outputPTR) = result; 558 outputPTR+=nbColumns; 559 560 } 561 } 562 } 563 }; 564 565 class Parallel_verticalAnticausalFilter_multGain: public cv::ParallelLoopBody 566 { 567 private: 568 float *outputFrame; 569 unsigned int nbRows, nbColumns; 570 float filterParam_a, filterParam_gain; 571 public: Parallel_verticalAnticausalFilter_multGain(float * bufferToProcess,const unsigned int nbRws,const unsigned int nbCols,const float a,const float gain)572 Parallel_verticalAnticausalFilter_multGain(float *bufferToProcess, const unsigned int nbRws, const unsigned int nbCols, const float a, const float gain) 573 :outputFrame(bufferToProcess), nbRows(nbRws), nbColumns(nbCols), filterParam_a(a), filterParam_gain(gain){} 574 operator ()(const Range & r) const575 virtual void operator()( const Range& r ) const CV_OVERRIDE { 576 float* offset=outputFrame+nbColumns*nbRows-nbColumns; 577 for (int IDcolumn=r.start; IDcolumn!=r.end; ++IDcolumn) 578 { 579 float result=0; 580 float *outputPTR=offset+IDcolumn; 581 582 for (unsigned int index=0; index<nbRows; ++index) 583 { 584 result = *(outputPTR) + filterParam_a * result; 585 *(outputPTR) = filterParam_gain*result; 586 outputPTR-=nbColumns; 587 588 } 589 } 590 } 591 }; 592 593 class Parallel_localAdaptation: public cv::ParallelLoopBody 594 { 595 private: 596 const float *localLuminance, *inputFrame; 597 float *outputFrame; 598 float localLuminanceFactor, localLuminanceAddon, maxInputValue; 599 public: Parallel_localAdaptation(const float * localLum,const float * inputImg,float * bufferToProcess,const float localLuminanceFact,const float localLuminanceAdd,const float maxInputVal)600 Parallel_localAdaptation(const float *localLum, const float *inputImg, float *bufferToProcess, const float localLuminanceFact, const float localLuminanceAdd, const float maxInputVal) 601 :localLuminance(localLum), inputFrame(inputImg),outputFrame(bufferToProcess), localLuminanceFactor(localLuminanceFact), localLuminanceAddon(localLuminanceAdd), maxInputValue(maxInputVal) {} 602 operator ()(const Range & r) const603 virtual void operator()( const Range& r ) const CV_OVERRIDE { 604 const float *localLuminancePTR=localLuminance+r.start; 605 const float *inputFramePTR=inputFrame+r.start; 606 float *outputFramePTR=outputFrame+r.start; 607 for (int IDpixel=r.start ; IDpixel!=r.end ; ++IDpixel, ++inputFramePTR, ++outputFramePTR) 608 { 609 float X0=*(localLuminancePTR++)*localLuminanceFactor+localLuminanceAddon; 610 // TODO : the following line can lead to a divide by zero ! A small offset is added, take care if the offset is too large in case of High Dynamic Range images which can use very small values... 611 *(outputFramePTR) = (maxInputValue+X0)**inputFramePTR/(*inputFramePTR +X0+0.00000000001f); 612 //std::cout<<"BasicRetinaFilter::inputFrame[IDpixel]=%f, X0=%f, outputFrame[IDpixel]=%f\n", inputFrame[IDpixel], X0, outputFrame[IDpixel]); 613 } 614 } 615 }; 616 617 ////////////////////////////////////////// 618 /// Specific filtering methods which manage non const spatial filtering parameter (used By retinacolor and LogProjectors) 619 class Parallel_horizontalAnticausalFilter_Irregular: public cv::ParallelLoopBody 620 { 621 private: 622 float *outputFrame; 623 const float *spatialConstantBuffer; 624 unsigned int IDrowEnd, nbColumns; 625 public: Parallel_horizontalAnticausalFilter_Irregular(float * bufferToProcess,const float * spatialConst,const unsigned int idEnd,const unsigned int nbCols)626 Parallel_horizontalAnticausalFilter_Irregular(float *bufferToProcess, const float *spatialConst, const unsigned int idEnd, const unsigned int nbCols) 627 :outputFrame(bufferToProcess), spatialConstantBuffer(spatialConst), IDrowEnd(idEnd), nbColumns(nbCols){} 628 operator ()(const Range & r) const629 virtual void operator()( const Range& r ) const CV_OVERRIDE { 630 631 for (int IDrow=r.start; IDrow!=r.end; ++IDrow) 632 { 633 float* outputPTR=outputFrame+(IDrowEnd-IDrow)*(nbColumns)-1; 634 const float* spatialConstantPTR=spatialConstantBuffer+(IDrowEnd-IDrow)*(nbColumns)-1; 635 float result=0; 636 for (unsigned int index=0; index<nbColumns; ++index) 637 { 638 result = *(outputPTR)+ *(spatialConstantPTR--)* result; 639 *(outputPTR--) = result; 640 } 641 } 642 } 643 }; 644 645 class Parallel_verticalCausalFilter_Irregular: public cv::ParallelLoopBody 646 { 647 private: 648 float *outputFrame; 649 const float *spatialConstantBuffer; 650 unsigned int nbRows, nbColumns; 651 public: Parallel_verticalCausalFilter_Irregular(float * bufferToProcess,const float * spatialConst,const unsigned int nbRws,const unsigned int nbCols)652 Parallel_verticalCausalFilter_Irregular(float *bufferToProcess, const float *spatialConst, const unsigned int nbRws, const unsigned int nbCols) 653 :outputFrame(bufferToProcess), spatialConstantBuffer(spatialConst), nbRows(nbRws), nbColumns(nbCols){} 654 operator ()(const Range & r) const655 virtual void operator()( const Range& r ) const CV_OVERRIDE { 656 for (int IDcolumn=r.start; IDcolumn!=r.end; ++IDcolumn) 657 { 658 float result=0; 659 float *outputPTR=outputFrame+IDcolumn; 660 const float* spatialConstantPTR=spatialConstantBuffer+IDcolumn; 661 for (unsigned int index=0; index<nbRows; ++index) 662 { 663 result = *(outputPTR) + *(spatialConstantPTR) * result; 664 *(outputPTR) = result; 665 outputPTR+=nbColumns; 666 spatialConstantPTR+=nbColumns; 667 } 668 } 669 } 670 }; 671 672 #endif 673 674 }; 675 676 }// end of namespace bioinspired 677 }// end of namespace cv 678 #endif 679