diff --git a/modules/contrib/src/retinacolor.cpp b/modules/contrib/src/retinacolor.cpp index b452956997..247234ffef 100644 --- a/modules/contrib/src/retinacolor.cpp +++ b/modules/contrib/src/retinacolor.cpp @@ -1,55 +1,55 @@ /*#****************************************************************************** ** IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -** +** ** By downloading, copying, installing or using the software you agree to this license. ** If you do not agree to this license, do not download, install, ** copy or use the software. -** -** +** +** ** 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. ** 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. -** +** ** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications) -** +** ** Creation - enhancement process 2007-2011 ** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France -** +** ** 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). ** Refer to the following research paper for more information: ** 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 ** 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: ** 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. -** +** ** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author : ** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper: ** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007 ** _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. ** ====> more informations in the above cited Jeanny Heraults's book. -** +** ** License Agreement ** For Open Source Computer Vision Library -** +** ** Copyright (C) 2000-2008, Intel Corporation, all rights reserved. ** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. -** +** ** For Human Visual System tools (hvstools) ** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved. -** +** ** Third party copyrights are property of their respective owners. -** +** ** Redistribution and use in source and binary forms, with or without modification, ** are permitted provided that the following conditions are met: -** +** ** * Redistributions of source code must retain the above copyright notice, ** this list of conditions and the following disclaimer. -** +** ** * Redistributions in binary form must reproduce the above copyright notice, ** this list of conditions and the following disclaimer in the documentation ** and/or other materials provided with the distribution. -** +** ** * The name of the copyright holders may not be used to endorse or promote products ** derived from this software without specific prior written permission. -** +** ** This software is provided by the copyright holders and contributors "as is" and ** any express or implied warranties, including, but not limited to, the implied ** warranties of merchantability and fitness for a particular purpose are disclaimed. @@ -91,28 +91,28 @@ RetinaColor::RetinaColor(const unsigned int NBrows, const unsigned int NBcolumns _colorLocalDensity(NBrows*NBcolumns*3), _imageGradient(NBrows*NBcolumns*2) { - // link to parent buffers (let's recycle !) - _luminance=&_filterOutput; - _multiplexedFrame=&_localBuffer; + // link to parent buffers (let's recycle !) + _luminance=&_filterOutput; + _multiplexedFrame=&_localBuffer; - _objectInit=false; - _samplingMethod=samplingMethod; - _saturateColors=false; - _colorSaturationValue=4.0; + _objectInit=false; + _samplingMethod=samplingMethod; + _saturateColors=false; + _colorSaturationValue=4.0; - // set default spatio-temporal filter parameters - setLPfilterParameters(0.0, 0.0, 1.5); - setLPfilterParameters(0.0, 0.0, 10.5, 1);// for the low pass filter dedicated to contours energy extraction (demultiplexing process) - setLPfilterParameters(0.f, 0.f, 0.9f, 2); + // set default spatio-temporal filter parameters + setLPfilterParameters(0.0, 0.0, 1.5); + setLPfilterParameters(0.0, 0.0, 10.5, 1);// for the low pass filter dedicated to contours energy extraction (demultiplexing process) + setLPfilterParameters(0.f, 0.f, 0.9f, 2); - // init default value on image Gradient - _imageGradient=0.57f; + // init default value on image Gradient + _imageGradient=0.57f; - // init color sampling map - _initColorSampling(); + // init color sampling map + _initColorSampling(); - // flush all buffers - clearAllBuffers(); + // flush all buffers + clearAllBuffers(); } RetinaColor::~RetinaColor() @@ -125,13 +125,13 @@ RetinaColor::~RetinaColor() */ void RetinaColor::clearAllBuffers() { - BasicRetinaFilter::clearAllBuffers(); - _tempMultiplexedFrame=0.f; - _demultiplexedTempBuffer=0.f; + BasicRetinaFilter::clearAllBuffers(); + _tempMultiplexedFrame=0.f; + _demultiplexedTempBuffer=0.f; - _demultiplexedColorFrame=0.f; - _chrominance=0.f; - _imageGradient=0.57f; + _demultiplexedColorFrame=0.f; + _chrominance=0.f; + _imageGradient=0.57f; } /** @@ -141,421 +141,421 @@ void RetinaColor::clearAllBuffers() */ void RetinaColor::resize(const unsigned int NBrows, const unsigned int NBcolumns) { - BasicRetinaFilter::clearAllBuffers(); - _colorSampling.resize(NBrows*NBcolumns); - _RGBmosaic.resize(NBrows*NBcolumns*3); - _tempMultiplexedFrame.resize(NBrows*NBcolumns); - _demultiplexedTempBuffer.resize(NBrows*NBcolumns*3); - _demultiplexedColorFrame.resize(NBrows*NBcolumns*3); - _chrominance.resize(NBrows*NBcolumns*3); - _colorLocalDensity.resize(NBrows*NBcolumns*3); - _imageGradient.resize(NBrows*NBcolumns*2); + BasicRetinaFilter::clearAllBuffers(); + _colorSampling.resize(NBrows*NBcolumns); + _RGBmosaic.resize(NBrows*NBcolumns*3); + _tempMultiplexedFrame.resize(NBrows*NBcolumns); + _demultiplexedTempBuffer.resize(NBrows*NBcolumns*3); + _demultiplexedColorFrame.resize(NBrows*NBcolumns*3); + _chrominance.resize(NBrows*NBcolumns*3); + _colorLocalDensity.resize(NBrows*NBcolumns*3); + _imageGradient.resize(NBrows*NBcolumns*2); - // link to parent buffers (let's recycle !) - _luminance=&_filterOutput; - _multiplexedFrame=&_localBuffer; + // link to parent buffers (let's recycle !) + _luminance=&_filterOutput; + _multiplexedFrame=&_localBuffer; - // init color sampling map - _initColorSampling(); + // init color sampling map + _initColorSampling(); - // clean buffers - clearAllBuffers(); + // clean buffers + clearAllBuffers(); } void RetinaColor::_initColorSampling() { - // filling the conversion table for multiplexed <=> demultiplexed frame - srand((unsigned)time(NULL)); + // filling the conversion table for multiplexed <=> demultiplexed frame + srand((unsigned)time(NULL)); - // preInit cones probabilities - _pR=_pB=_pG=0; - switch (_samplingMethod) - { - case RETINA_COLOR_RANDOM: - for (unsigned int index=0 ; indexgetNBpixels(); ++index) - { + // preInit cones probabilities + _pR=_pB=_pG=0; + switch (_samplingMethod) + { + case RETINA_COLOR_RANDOM: + for (unsigned int index=0 ; indexgetNBpixels(); ++index) + { - // random RGB sampling - unsigned int colorIndex=rand()%24; + // random RGB sampling + unsigned int colorIndex=rand()%24; - if (colorIndex<8){ - colorIndex=0; + if (colorIndex<8){ + colorIndex=0; - ++_pR; - }else - { - if (colorIndex<21){ - colorIndex=1; - ++_pG; - }else{ - colorIndex=2; - ++_pB; - } - } - _colorSampling[index] = colorIndex*this->getNBpixels()+index; - } - _pR/=(float)this->getNBpixels(); - _pG/=(float)this->getNBpixels(); - _pB/=(float)this->getNBpixels(); - std::cout<<"Color channels proportions: pR, pG, pB= "<<_pR<<", "<<_pG<<", "<<_pB<<", "<getNBpixels(); ++index) - { - _colorSampling[index] = index+((index%3+(index%_filterOutput.getNBcolumns()))%3)*_filterOutput.getNBpixels(); - } - _pR=_pB=_pG=1.f/3; - break; - case RETINA_COLOR_BAYER: // default sets bayer sampling - for (unsigned int index=0 ; index<_filterOutput.getNBpixels(); ++index) - { - //First line: R G R G - _colorSampling[index] = index+((index/_filterOutput.getNBcolumns())%2)*_filterOutput.getNBpixels()+((index%_filterOutput.getNBcolumns())%2)*_filterOutput.getNBpixels(); - //First line: G R G R - //_colorSampling[index] = 3*index+((index/_filterOutput.getNBcolumns())%2)+((index%_filterOutput.getNBcolumns()+1)%2); - } - _pR=_pB=0.25; - _pG=0.5; - break; - default: + ++_pR; + }else + { + if (colorIndex<21){ + colorIndex=1; + ++_pG; + }else{ + colorIndex=2; + ++_pB; + } + } + _colorSampling[index] = colorIndex*this->getNBpixels()+index; + } + _pR/=(float)this->getNBpixels(); + _pG/=(float)this->getNBpixels(); + _pB/=(float)this->getNBpixels(); + std::cout<<"Color channels proportions: pR, pG, pB= "<<_pR<<", "<<_pG<<", "<<_pB<<", "<getNBpixels(); ++index) + { + _colorSampling[index] = index+((index%3+(index%_filterOutput.getNBcolumns()))%3)*_filterOutput.getNBpixels(); + } + _pR=_pB=_pG=1.f/3; + break; + case RETINA_COLOR_BAYER: // default sets bayer sampling + for (unsigned int index=0 ; index<_filterOutput.getNBpixels(); ++index) + { + //First line: R G R G + _colorSampling[index] = index+((index/_filterOutput.getNBcolumns())%2)*_filterOutput.getNBpixels()+((index%_filterOutput.getNBcolumns())%2)*_filterOutput.getNBpixels(); + //First line: G R G R + //_colorSampling[index] = 3*index+((index/_filterOutput.getNBcolumns())%2)+((index%_filterOutput.getNBcolumns()+1)%2); + } + _pR=_pB=0.25; + _pG=0.5; + break; + default: #ifdef RETINACOLORDEBUG - std::cerr<<"RetinaColor::No or wrong color sampling method, skeeping"< &multiplexedColorFrame, const bool adaptiveFiltering, const float maxInputValue) { - // demultiplex the grey frame to RGB frame - // -> first set demultiplexed frame to 0 - _demultiplexedTempBuffer=0; - // -> demultiplex process - register unsigned int *colorSamplingPRT=&_colorSampling[0]; - register const float *multiplexedColorFramePTR=get_data(multiplexedColorFrame); - for (unsigned int indexa=0; indexa<_filterOutput.getNBpixels() ; ++indexa) - _demultiplexedTempBuffer[*(colorSamplingPRT++)]=*(multiplexedColorFramePTR++); + // demultiplex the grey frame to RGB frame + // -> first set demultiplexed frame to 0 + _demultiplexedTempBuffer=0; + // -> demultiplex process + register unsigned int *colorSamplingPRT=&_colorSampling[0]; + register const float *multiplexedColorFramePtr=get_data(multiplexedColorFrame); + for (unsigned int indexa=0; indexa<_filterOutput.getNBpixels() ; ++indexa) + _demultiplexedTempBuffer[*(colorSamplingPRT++)]=*(multiplexedColorFramePtr++); - // interpolate the demultiplexed frame depending on the color sampling method - if (!adaptiveFiltering) - _interpolateImageDemultiplexedImage(&_demultiplexedTempBuffer[0]); + // interpolate the demultiplexed frame depending on the color sampling method + if (!adaptiveFiltering) + _interpolateImageDemultiplexedImage(&_demultiplexedTempBuffer[0]); - // low pass filtering the demultiplexed frame - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0], &_chrominance[0]); - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels(), &_chrominance[0]+_filterOutput.getNBpixels()); - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels(), &_chrominance[0]+_filterOutput.getDoubleNBpixels()); + // low pass filtering the demultiplexed frame + _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0], &_chrominance[0]); + _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels(), &_chrominance[0]+_filterOutput.getNBpixels()); + _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels(), &_chrominance[0]+_filterOutput.getDoubleNBpixels()); - /*if (_samplingMethod=BAYER) - { - _applyRIFfilter(_chrominance, _chrominance); - _applyRIFfilter(_chrominance+_filterOutput.getNBpixels(), _chrominance+_filterOutput.getNBpixels()); - _applyRIFfilter(_chrominance+_filterOutput.getDoubleNBpixels(), _chrominance+_filterOutput.getDoubleNBpixels()); - }*/ + /*if (_samplingMethod=BAYER) + { + _applyRIFfilter(_chrominance, _chrominance); + _applyRIFfilter(_chrominance+_filterOutput.getNBpixels(), _chrominance+_filterOutput.getNBpixels()); + _applyRIFfilter(_chrominance+_filterOutput.getDoubleNBpixels(), _chrominance+_filterOutput.getDoubleNBpixels()); + }*/ - // normalize by the photoreceptors local density and retrieve the local luminance - register float *chrominancePTR= &_chrominance[0]; - register float *colorLocalDensityPTR= &_colorLocalDensity[0]; - register float *luminance= &(*_luminance)[0]; - if (!adaptiveFiltering)// compute the gradient on the luminance - { - if (_samplingMethod==RETINA_COLOR_RANDOM) - for (unsigned int indexc=0; indexc<_filterOutput.getNBpixels() ; ++indexc, ++chrominancePTR, ++colorLocalDensityPTR, ++luminance) - { - // normalize by photoreceptors density - float Cr=*(chrominancePTR)*_colorLocalDensity[indexc]; - float Cg=*(chrominancePTR+_filterOutput.getNBpixels())*_colorLocalDensity[indexc+_filterOutput.getNBpixels()]; - float Cb=*(chrominancePTR+_filterOutput.getDoubleNBpixels())*_colorLocalDensity[indexc+_filterOutput.getDoubleNBpixels()]; - *luminance=(Cr+Cg+Cb)*_pG; - *(chrominancePTR)=Cr-*luminance; - *(chrominancePTR+_filterOutput.getNBpixels())=Cg-*luminance; - *(chrominancePTR+_filterOutput.getDoubleNBpixels())=Cb-*luminance; - } - else - for (unsigned int indexc=0; indexc<_filterOutput.getNBpixels() ; ++indexc, ++chrominancePTR, ++colorLocalDensityPTR, ++luminance) - { - float Cr=*(chrominancePTR); - float Cg=*(chrominancePTR+_filterOutput.getNBpixels()); - float Cb=*(chrominancePTR+_filterOutput.getDoubleNBpixels()); - *luminance=_pR*Cr+_pG*Cg+_pB*Cb; - *(chrominancePTR)=Cr-*luminance; - *(chrominancePTR+_filterOutput.getNBpixels())=Cg-*luminance; - *(chrominancePTR+_filterOutput.getDoubleNBpixels())=Cb-*luminance; - } + // normalize by the photoreceptors local density and retrieve the local luminance + register float *chrominancePTR= &_chrominance[0]; + register float *colorLocalDensityPTR= &_colorLocalDensity[0]; + register float *luminance= &(*_luminance)[0]; + if (!adaptiveFiltering)// compute the gradient on the luminance + { + if (_samplingMethod==RETINA_COLOR_RANDOM) + for (unsigned int indexc=0; indexc<_filterOutput.getNBpixels() ; ++indexc, ++chrominancePTR, ++colorLocalDensityPTR, ++luminance) + { + // normalize by photoreceptors density + float Cr=*(chrominancePTR)*_colorLocalDensity[indexc]; + float Cg=*(chrominancePTR+_filterOutput.getNBpixels())*_colorLocalDensity[indexc+_filterOutput.getNBpixels()]; + float Cb=*(chrominancePTR+_filterOutput.getDoubleNBpixels())*_colorLocalDensity[indexc+_filterOutput.getDoubleNBpixels()]; + *luminance=(Cr+Cg+Cb)*_pG; + *(chrominancePTR)=Cr-*luminance; + *(chrominancePTR+_filterOutput.getNBpixels())=Cg-*luminance; + *(chrominancePTR+_filterOutput.getDoubleNBpixels())=Cb-*luminance; + } + else + for (unsigned int indexc=0; indexc<_filterOutput.getNBpixels() ; ++indexc, ++chrominancePTR, ++colorLocalDensityPTR, ++luminance) + { + float Cr=*(chrominancePTR); + float Cg=*(chrominancePTR+_filterOutput.getNBpixels()); + float Cb=*(chrominancePTR+_filterOutput.getDoubleNBpixels()); + *luminance=_pR*Cr+_pG*Cg+_pB*Cb; + *(chrominancePTR)=Cr-*luminance; + *(chrominancePTR+_filterOutput.getNBpixels())=Cg-*luminance; + *(chrominancePTR+_filterOutput.getDoubleNBpixels())=Cb-*luminance; + } - // in order to get the color image, each colored map needs to be added the luminance - // -> to do so, compute: multiplexedColorFrame - remultiplexed chrominances - runColorMultiplexing(_chrominance, _tempMultiplexedFrame); - //lum = 1/3((f*(ImR))/(f*mR) + (f*(ImG))/(f*mG) + (f*(ImB))/(f*mB)); - float *luminancePTR= &(*_luminance)[0]; - chrominancePTR= &_chrominance[0]; - float *demultiplexedColorFramePTR= &_demultiplexedColorFrame[0]; - for (unsigned int indexp=0; indexp<_filterOutput.getNBpixels() ; ++indexp, ++luminancePTR, ++chrominancePTR, ++demultiplexedColorFramePTR) - { - *luminancePTR=(multiplexedColorFrame[indexp]-_tempMultiplexedFrame[indexp]); - *(demultiplexedColorFramePTR)=*(chrominancePTR)+*luminancePTR; - *(demultiplexedColorFramePTR+_filterOutput.getNBpixels())=*(chrominancePTR+_filterOutput.getNBpixels())+*luminancePTR; - *(demultiplexedColorFramePTR+_filterOutput.getDoubleNBpixels())=*(chrominancePTR+_filterOutput.getDoubleNBpixels())+*luminancePTR; - } + // in order to get the color image, each colored map needs to be added the luminance + // -> to do so, compute: multiplexedColorFrame - remultiplexed chrominances + runColorMultiplexing(_chrominance, _tempMultiplexedFrame); + //lum = 1/3((f*(ImR))/(f*mR) + (f*(ImG))/(f*mG) + (f*(ImB))/(f*mB)); + float *luminancePTR= &(*_luminance)[0]; + chrominancePTR= &_chrominance[0]; + float *demultiplexedColorFramePTR= &_demultiplexedColorFrame[0]; + for (unsigned int indexp=0; indexp<_filterOutput.getNBpixels() ; ++indexp, ++luminancePTR, ++chrominancePTR, ++demultiplexedColorFramePTR) + { + *luminancePTR=(multiplexedColorFrame[indexp]-_tempMultiplexedFrame[indexp]); + *(demultiplexedColorFramePTR)=*(chrominancePTR)+*luminancePTR; + *(demultiplexedColorFramePTR+_filterOutput.getNBpixels())=*(chrominancePTR+_filterOutput.getNBpixels())+*luminancePTR; + *(demultiplexedColorFramePTR+_filterOutput.getDoubleNBpixels())=*(chrominancePTR+_filterOutput.getDoubleNBpixels())+*luminancePTR; + } - }else - { - register const float *multiplexedColorFramePTR= get_data(multiplexedColorFrame); - for (unsigned int indexc=0; indexc<_filterOutput.getNBpixels() ; ++indexc, ++chrominancePTR, ++colorLocalDensityPTR, ++luminance, ++multiplexedColorFramePTR) - { - // normalize by photoreceptors density - float Cr=*(chrominancePTR)*_colorLocalDensity[indexc]; - float Cg=*(chrominancePTR+_filterOutput.getNBpixels())*_colorLocalDensity[indexc+_filterOutput.getNBpixels()]; - float Cb=*(chrominancePTR+_filterOutput.getDoubleNBpixels())*_colorLocalDensity[indexc+_filterOutput.getDoubleNBpixels()]; - *luminance=(Cr+Cg+Cb)*_pG; - _demultiplexedTempBuffer[_colorSampling[indexc]] = *multiplexedColorFramePTR - *luminance; + }else + { + register const float *multiplexedColorFramePTR= get_data(multiplexedColorFrame); + for (unsigned int indexc=0; indexc<_filterOutput.getNBpixels() ; ++indexc, ++chrominancePTR, ++colorLocalDensityPTR, ++luminance, ++multiplexedColorFramePTR) + { + // normalize by photoreceptors density + float Cr=*(chrominancePTR)*_colorLocalDensity[indexc]; + float Cg=*(chrominancePTR+_filterOutput.getNBpixels())*_colorLocalDensity[indexc+_filterOutput.getNBpixels()]; + float Cb=*(chrominancePTR+_filterOutput.getDoubleNBpixels())*_colorLocalDensity[indexc+_filterOutput.getDoubleNBpixels()]; + *luminance=(Cr+Cg+Cb)*_pG; + _demultiplexedTempBuffer[_colorSampling[indexc]] = *multiplexedColorFramePTR - *luminance; - } + } - // compute the gradient of the luminance - _computeGradient(&(*_luminance)[0]); + // compute the gradient of the luminance + _computeGradient(&(*_luminance)[0]); - // adaptively filter the submosaics to get the adaptive densities, here the buffer _chrominance is used as a temp buffer - _adaptiveSpatialLPfilter(&_RGBmosaic[0], &_chrominance[0]); - _adaptiveSpatialLPfilter(&_RGBmosaic[0]+_filterOutput.getNBpixels(), &_chrominance[0]+_filterOutput.getNBpixels()); - _adaptiveSpatialLPfilter(&_RGBmosaic[0]+_filterOutput.getDoubleNBpixels(), &_chrominance[0]+_filterOutput.getDoubleNBpixels()); + // adaptively filter the submosaics to get the adaptive densities, here the buffer _chrominance is used as a temp buffer + _adaptiveSpatialLPfilter(&_RGBmosaic[0], &_chrominance[0]); + _adaptiveSpatialLPfilter(&_RGBmosaic[0]+_filterOutput.getNBpixels(), &_chrominance[0]+_filterOutput.getNBpixels()); + _adaptiveSpatialLPfilter(&_RGBmosaic[0]+_filterOutput.getDoubleNBpixels(), &_chrominance[0]+_filterOutput.getDoubleNBpixels()); - _adaptiveSpatialLPfilter(&_demultiplexedTempBuffer[0], &_demultiplexedColorFrame[0]); - _adaptiveSpatialLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels(), &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels()); - _adaptiveSpatialLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels(), &_demultiplexedColorFrame[0]+_filterOutput.getDoubleNBpixels()); + _adaptiveSpatialLPfilter(&_demultiplexedTempBuffer[0], &_demultiplexedColorFrame[0]); + _adaptiveSpatialLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels(), &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels()); + _adaptiveSpatialLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels(), &_demultiplexedColorFrame[0]+_filterOutput.getDoubleNBpixels()); -/* for (unsigned int index=0; index<_filterOutput.getNBpixels()*3 ; ++index) // cette boucle pourrait �tre supprimee en passant la densit� � la fonction de filtrage - _demultiplexedColorFrame[index] /= _chrominance[index];*/ - _demultiplexedColorFrame/=_chrominance; // more optimal ;o) +/* for (unsigned int index=0; index<_filterOutput.getNBpixels()*3 ; ++index) // cette boucle pourrait �tre supprimee en passant la densit� � la fonction de filtrage + _demultiplexedColorFrame[index] /= _chrominance[index];*/ + _demultiplexedColorFrame/=_chrominance; // more optimal ;o) - // compute and substract the residual luminance - for (unsigned int index=0; index<_filterOutput.getNBpixels() ; ++index) - { - float residu = _pR*_demultiplexedColorFrame[index] + _pG*_demultiplexedColorFrame[index+_filterOutput.getNBpixels()] + _pB*_demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()]; - _demultiplexedColorFrame[index] = _demultiplexedColorFrame[index] - residu; - _demultiplexedColorFrame[index+_filterOutput.getNBpixels()] = _demultiplexedColorFrame[index+_filterOutput.getNBpixels()] - residu; - _demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()] = _demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()] - residu; - } + // compute and substract the residual luminance + for (unsigned int index=0; index<_filterOutput.getNBpixels() ; ++index) + { + float residu = _pR*_demultiplexedColorFrame[index] + _pG*_demultiplexedColorFrame[index+_filterOutput.getNBpixels()] + _pB*_demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()]; + _demultiplexedColorFrame[index] = _demultiplexedColorFrame[index] - residu; + _demultiplexedColorFrame[index+_filterOutput.getNBpixels()] = _demultiplexedColorFrame[index+_filterOutput.getNBpixels()] - residu; + _demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()] = _demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()] - residu; + } - // multiplex the obtained chrominance - runColorMultiplexing(_demultiplexedColorFrame, _tempMultiplexedFrame); - _demultiplexedTempBuffer=0; + // multiplex the obtained chrominance + runColorMultiplexing(_demultiplexedColorFrame, _tempMultiplexedFrame); + _demultiplexedTempBuffer=0; - // get the luminance, et and add it to each chrominance - for (unsigned int index=0; index<_filterOutput.getNBpixels() ; ++index) - { - (*_luminance)[index]=multiplexedColorFrame[index]-_tempMultiplexedFrame[index]; - _demultiplexedTempBuffer[_colorSampling[index]] = _demultiplexedColorFrame[_colorSampling[index]];//multiplexedColorFrame[index] - (*_luminance)[index]; - } + // get the luminance, et and add it to each chrominance + for (unsigned int index=0; index<_filterOutput.getNBpixels() ; ++index) + { + (*_luminance)[index]=multiplexedColorFrame[index]-_tempMultiplexedFrame[index]; + _demultiplexedTempBuffer[_colorSampling[index]] = _demultiplexedColorFrame[_colorSampling[index]];//multiplexedColorFrame[index] - (*_luminance)[index]; + } - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0], &_demultiplexedTempBuffer[0]); - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels(), &_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels()); - _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels(), &_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels()); + _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0], &_demultiplexedTempBuffer[0]); + _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels(), &_demultiplexedTempBuffer[0]+_filterOutput.getNBpixels()); + _spatiotemporalLPfilter(&_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels(), &_demultiplexedTempBuffer[0]+_filterOutput.getDoubleNBpixels()); - // get the luminance and add it to each chrominance - for (unsigned int index=0; index<_filterOutput.getNBpixels() ; ++index) - { - _demultiplexedColorFrame[index] = _demultiplexedTempBuffer[index]*_colorLocalDensity[index]+ (*_luminance)[index]; - _demultiplexedColorFrame[index+_filterOutput.getNBpixels()] = _demultiplexedTempBuffer[index+_filterOutput.getNBpixels()]*_colorLocalDensity[index+_filterOutput.getNBpixels()]+ (*_luminance)[index]; - _demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()] = _demultiplexedTempBuffer[index+_filterOutput.getDoubleNBpixels()]*_colorLocalDensity[index+_filterOutput.getDoubleNBpixels()]+ (*_luminance)[index]; - } - } + // get the luminance and add it to each chrominance + for (unsigned int index=0; index<_filterOutput.getNBpixels() ; ++index) + { + _demultiplexedColorFrame[index] = _demultiplexedTempBuffer[index]*_colorLocalDensity[index]+ (*_luminance)[index]; + _demultiplexedColorFrame[index+_filterOutput.getNBpixels()] = _demultiplexedTempBuffer[index+_filterOutput.getNBpixels()]*_colorLocalDensity[index+_filterOutput.getNBpixels()]+ (*_luminance)[index]; + _demultiplexedColorFrame[index+_filterOutput.getDoubleNBpixels()] = _demultiplexedTempBuffer[index+_filterOutput.getDoubleNBpixels()]*_colorLocalDensity[index+_filterOutput.getDoubleNBpixels()]+ (*_luminance)[index]; + } + } - // eliminate saturated colors by simple clipping values to the input range - clipRGBOutput_0_maxInputValue(NULL, maxInputValue); + // eliminate saturated colors by simple clipping values to the input range + clipRGBOutput_0_maxInputValue(NULL, maxInputValue); - /* transfert image gradient in order to check validity + /* transfert image gradient in order to check validity memcpy((*_luminance), _imageGradient, sizeof(float)*_filterOutput.getNBpixels()); memcpy(_demultiplexedColorFrame, _imageGradient+_filterOutput.getNBpixels(), sizeof(float)*_filterOutput.getNBpixels()); memcpy(_demultiplexedColorFrame+_filterOutput.getNBpixels(), _imageGradient+_filterOutput.getNBpixels(), sizeof(float)*_filterOutput.getNBpixels()); memcpy(_demultiplexedColorFrame+2*_filterOutput.getNBpixels(), _imageGradient+_filterOutput.getNBpixels(), sizeof(float)*_filterOutput.getNBpixels()); - */ + */ - if (_saturateColors) - { - TemplateBuffer::normalizeGrayOutputCentredSigmoide(128, _colorSaturationValue, maxInputValue, &_demultiplexedColorFrame[0], &_demultiplexedColorFrame[0], _filterOutput.getNBpixels()); - TemplateBuffer::normalizeGrayOutputCentredSigmoide(128, _colorSaturationValue, maxInputValue, &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels(), &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels(), _filterOutput.getNBpixels()); - TemplateBuffer::normalizeGrayOutputCentredSigmoide(128, _colorSaturationValue, maxInputValue, &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels()*2, &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels()*2, _filterOutput.getNBpixels()); - } + if (_saturateColors) + { + TemplateBuffer::normalizeGrayOutputCentredSigmoide(128, _colorSaturationValue, maxInputValue, &_demultiplexedColorFrame[0], &_demultiplexedColorFrame[0], _filterOutput.getNBpixels()); + TemplateBuffer::normalizeGrayOutputCentredSigmoide(128, _colorSaturationValue, maxInputValue, &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels(), &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels(), _filterOutput.getNBpixels()); + TemplateBuffer::normalizeGrayOutputCentredSigmoide(128, _colorSaturationValue, maxInputValue, &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels()*2, &_demultiplexedColorFrame[0]+_filterOutput.getNBpixels()*2, _filterOutput.getNBpixels()); + } } // color multiplexing: input frame size=_NBrows*_filterOutput.getNBcolumns()*3, multiplexedFrame output size=_NBrows*_filterOutput.getNBcolumns() void RetinaColor::runColorMultiplexing(const std::valarray &demultiplexedInputFrame, std::valarray &multiplexedFrame) { - // multiply each color layer by its bayer mask - register unsigned int *colorSamplingPTR= &_colorSampling[0]; - register float *multiplexedFramePTR= &multiplexedFrame[0]; - for (unsigned int indexp=0; indexp<_filterOutput.getNBpixels(); ++indexp) - *(multiplexedFramePTR++)=demultiplexedInputFrame[*(colorSamplingPTR++)]; + // multiply each color layer by its bayer mask + register unsigned int *colorSamplingPTR= &_colorSampling[0]; + register float *multiplexedFramePTR= &multiplexedFrame[0]; + for (unsigned int indexp=0; indexp<_filterOutput.getNBpixels(); ++indexp) + *(multiplexedFramePTR++)=demultiplexedInputFrame[*(colorSamplingPTR++)]; } void RetinaColor::normalizeRGBOutput_0_maxOutputValue(const float maxOutputValue) { - //normalizeGrayOutputCentredSigmoide(0.0, 2, _chrominance); - TemplateBuffer::normalizeGrayOutput_0_maxOutputValue(&_demultiplexedColorFrame[0], 3*_filterOutput.getNBpixels(), maxOutputValue); - //normalizeGrayOutputCentredSigmoide(0.0, 2, _chrominance+_filterOutput.getNBpixels()); - //normalizeGrayOutput_0_maxOutputValue(_demultiplexedColorFrame+_filterOutput.getNBpixels(), _filterOutput.getNBpixels(), maxOutputValue); - //normalizeGrayOutputCentredSigmoide(0.0, 2, _chrominance+2*_filterOutput.getNBpixels()); - //normalizeGrayOutput_0_maxOutputValue(_demultiplexedColorFrame+_filterOutput.getDoubleNBpixels(), _filterOutput.getNBpixels(), maxOutputValue); - TemplateBuffer::normalizeGrayOutput_0_maxOutputValue(&(*_luminance)[0], _filterOutput.getNBpixels(), maxOutputValue); + //normalizeGrayOutputCentredSigmoide(0.0, 2, _chrominance); + TemplateBuffer::normalizeGrayOutput_0_maxOutputValue(&_demultiplexedColorFrame[0], 3*_filterOutput.getNBpixels(), maxOutputValue); + //normalizeGrayOutputCentredSigmoide(0.0, 2, _chrominance+_filterOutput.getNBpixels()); + //normalizeGrayOutput_0_maxOutputValue(_demultiplexedColorFrame+_filterOutput.getNBpixels(), _filterOutput.getNBpixels(), maxOutputValue); + //normalizeGrayOutputCentredSigmoide(0.0, 2, _chrominance+2*_filterOutput.getNBpixels()); + //normalizeGrayOutput_0_maxOutputValue(_demultiplexedColorFrame+_filterOutput.getDoubleNBpixels(), _filterOutput.getNBpixels(), maxOutputValue); + TemplateBuffer::normalizeGrayOutput_0_maxOutputValue(&(*_luminance)[0], _filterOutput.getNBpixels(), maxOutputValue); } /// normalize output between 0 and maxOutputValue; void RetinaColor::clipRGBOutput_0_maxInputValue(float *inputOutputBuffer, const float maxInputValue) { - //std::cout<<"RetinaColor::normalizing RGB frame..."<(0,_filterOutput.getNBpixels()*3), Parallel_clipBufferValues(inputOutputBuffer, 0, maxInputValue), tbb::auto_partitioner()); #else - register float *inputOutputBufferPTR=inputOutputBuffer; - for (register unsigned int jf = 0; jf < _filterOutput.getNBpixels()*3; ++jf, ++inputOutputBufferPTR) - { - if (*inputOutputBufferPTR>maxInputValue) - *inputOutputBufferPTR=maxInputValue; - else if (*inputOutputBufferPTR<0) - *inputOutputBufferPTR=0; - } + register float *inputOutputBufferPTR=inputOutputBuffer; + for (register unsigned int jf = 0; jf < _filterOutput.getNBpixels()*3; ++jf, ++inputOutputBufferPTR) + { + if (*inputOutputBufferPTR>maxInputValue) + *inputOutputBufferPTR=maxInputValue; + else if (*inputOutputBufferPTR<0) + *inputOutputBufferPTR=0; + } #endif - //std::cout<<"RetinaColor::...normalizing RGB frame OK"<maxValue) - maxValue=outputFrame[index]; - } - } - normalisationFactor=1.f/maxValue; - // normalisation [0, 1] + float maxValue=0.f; + float normalisationFactor=1.f/3.f; + for (unsigned int indexr=1 ; indexr<_filterOutput.getNBrows()-1; ++indexr) + { + for (unsigned int indexc=1 ; indexc<_filterOutput.getNBcolumns()-1; ++indexc) + { + unsigned int index=indexc+indexr*_filterOutput.getNBcolumns(); + outputFrame[index]=normalisationFactor*fabs(8.f*inputFrame[index]-inputFrame[index-1]-inputFrame[index+1]-inputFrame[index-_filterOutput.getNBcolumns()]-inputFrame[index+_filterOutput.getNBcolumns()]-inputFrame[index-1-_filterOutput.getNBcolumns()]-inputFrame[index-1+_filterOutput.getNBcolumns()]-inputFrame[index+1-_filterOutput.getNBcolumns()]-inputFrame[index+1+_filterOutput.getNBcolumns()]); + if (outputFrame[index]>maxValue) + maxValue=outputFrame[index]; + } + } + normalisationFactor=1.f/maxValue; + // normalisation [0, 1] for (unsigned int indexp=1 ; indexp<_filterOutput.getNBrows()-1; ++indexp) - outputFrame[indexp]=outputFrame[indexp]*normalisationFactor; + outputFrame[indexp]=outputFrame[indexp]*normalisationFactor; } ////////////////////////////////////////////////////////// @@ -565,16 +565,16 @@ void RetinaColor::_getNormalizedContoursImage(const float *inputFrame, float *ou void RetinaColor::_adaptiveSpatialLPfilter(const float *inputFrame, float *outputFrame) { - /**********/ - _gain = (1-0.57f)*(1-0.57f)*(1-0.06f)*(1-0.06f); + /**********/ + _gain = (1-0.57f)*(1-0.57f)*(1-0.06f)*(1-0.06f); - // launch the serie of 1D directional filters in order to compute the 2D low pass filter - // -> horizontal filters work with the first layer of imageGradient - _adaptiveHorizontalCausalFilter_addInput(inputFrame, outputFrame, 0, _filterOutput.getNBrows()); - _horizontalAnticausalFilter_Irregular(outputFrame, 0, _filterOutput.getNBrows(), &_imageGradient[0]); - // -> horizontal filters work with the second layer of imageGradient - _verticalCausalFilter_Irregular(outputFrame, 0, _filterOutput.getNBcolumns(), &_imageGradient[0]+_filterOutput.getNBpixels()); - _adaptiveVerticalAnticausalFilter_multGain(outputFrame, 0, _filterOutput.getNBcolumns()); + // launch the serie of 1D directional filters in order to compute the 2D low pass filter + // -> horizontal filters work with the first layer of imageGradient + _adaptiveHorizontalCausalFilter_addInput(inputFrame, outputFrame, 0, _filterOutput.getNBrows()); + _horizontalAnticausalFilter_Irregular(outputFrame, 0, _filterOutput.getNBrows(), &_imageGradient[0]); + // -> horizontal filters work with the second layer of imageGradient + _verticalCausalFilter_Irregular(outputFrame, 0, _filterOutput.getNBcolumns(), &_imageGradient[0]+_filterOutput.getNBpixels()); + _adaptiveVerticalAnticausalFilter_multGain(outputFrame, 0, _filterOutput.getNBcolumns()); } // horizontal causal filter which adds the input inside... replaces the parent _horizontalCausalFilter_Irregular_addInput by avoiding a product for each pixel @@ -583,21 +583,21 @@ void RetinaColor::_adaptiveHorizontalCausalFilter_addInput(const float *inputFra #ifdef HAVE_TBB tbb::parallel_for(tbb::blocked_range(IDrowStart,IDrowEnd), Parallel_adaptiveHorizontalCausalFilter_addInput(inputFrame, outputFrame, &_imageGradient[0], _filterOutput.getNBcolumns()), tbb::auto_partitioner()); #else - register float* outputPTR=outputFrame+IDrowStart*_filterOutput.getNBcolumns(); - register const float* inputPTR=inputFrame+IDrowStart*_filterOutput.getNBcolumns(); - register const float *imageGradientPTR= &_imageGradient[0]+IDrowStart*_filterOutput.getNBcolumns(); - for (unsigned int IDrow=IDrowStart; IDrow(IDcolumnStart,IDcolumnEnd), Parallel_adaptiveVerticalAnticausalFilter_multGain(outputFrame, &_imageGradient[0]+_filterOutput.getNBpixels(), _filterOutput.getNBrows(), _filterOutput.getNBcolumns(), _gain), tbb::auto_partitioner()); #else - float* outputOffset=outputFrame+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns(); - float* gradOffset= &_imageGradient[0]+_filterOutput.getNBpixels()*2-_filterOutput.getNBcolumns(); + float* outputOffset=outputFrame+_filterOutput.getNBpixels()-_filterOutput.getNBcolumns(); + float* gradOffset= &_imageGradient[0]+_filterOutput.getNBpixels()*2-_filterOutput.getNBcolumns(); - for (unsigned int IDcolumn=IDcolumnStart; IDcolumn &result) { - bool processSuccess=true; - // basic preliminary error check - if (result.size()!=_demultiplexedColorFrame.size()) - { - std::cerr<<"RetinaColor::applyKrauskopfLMS2Acr1cr2Transform: input buffer does not match retina buffer size, conversion aborted"< &result) { - bool processSuccess=true; - // basic preliminary error check - if (result.size()!=_demultiplexedColorFrame.size()) - { - std::cerr<<"RetinaColor::applyKrauskopfLMS2Acr1cr2Transform: input buffer does not match retina buffer size, conversion aborted"< &inputFrameBuffer, std::valarray &outputFrameBuffer, const float *transformTable) { - // two step methods in order to allow inputFrame and outputFrame to be the same - unsigned int nbPixels=(unsigned int)(inputFrameBuffer.size()/3), dbpixels=(unsigned int)(2*inputFrameBuffer.size()/3); + // two step methods in order to allow inputFrame and outputFrame to be the same + unsigned int nbPixels=(unsigned int)(inputFrameBuffer.size()/3), dbpixels=(unsigned int)(2*inputFrameBuffer.size()/3); - const float *inputFrame=get_data(inputFrameBuffer); - float *outputFrame= &outputFrameBuffer[0]; + const float *inputFrame=get_data(inputFrameBuffer); + float *outputFrame= &outputFrameBuffer[0]; - for (unsigned int dataIndex=0; dataIndex