92 #include <visp3/core/vpImageFilter.h> 93 #include <visp3/core/vpMath.h> 94 #include <visp3/imgproc/vpImgproc.h> 96 #define MAX_RETINEX_SCALES 8 98 std::vector<double> retinexScalesDistribution(
const int scaleDiv,
const int level,
const int scale)
100 std::vector<double> scales(MAX_RETINEX_SCALES);
103 scales[0] = scale / 2.0;
104 }
else if (scaleDiv == 2) {
105 scales[0] = scale / 2.0;
108 double size_step = scale / (double)scaleDiv;
113 for (i = 0; i < scaleDiv; i++) {
114 scales[(size_t)i] = 2.0 + i * size_step;
119 size_step = std::log(scale - 2.0) / (double)scaleDiv;
120 for (i = 0; i < scaleDiv; i++) {
121 scales[(size_t)i] = 2.0 + std::pow(10.0, (i * size_step) / std::log(10.0));
126 size_step = std::log(scale - 2.0) / (double)scaleDiv;
127 for (i = 0; i < scaleDiv; i++) {
128 scales[(size_t)i] = scale - std::pow(10.0, (i * size_step) / std::log(10.0));
142 void MSRCR(
vpImage<vpRGBa> &I,
const int _scale,
const int scaleDiv,
const int level,
const double dynamic,
143 const int _kernelSize)
147 std::vector<double> retinexScales = retinexScalesDistribution(scaleDiv, level, _scale);
152 double weight = 1.0 / (double)scaleDiv;
154 std::vector<vpImage<double> > doubleRGB(3);
155 std::vector<vpImage<double> > doubleResRGB(3);
156 unsigned int size = I.
getSize();
158 int kernelSize = _kernelSize;
159 if (kernelSize == -1) {
162 kernelSize = (kernelSize - kernelSize % 2) + 1;
165 for (
int channel = 0; channel < 3; channel++) {
169 for (
unsigned int cpt = 0; cpt < size; cpt++) {
173 doubleRGB[(size_t)channel].bitmap[cpt] = I.
bitmap[cpt].
R + 1.0;
177 doubleRGB[(
size_t)channel].bitmap[cpt] = I.
bitmap[cpt].
G + 1.0;
181 doubleRGB[(size_t)channel].bitmap[cpt] = I.
bitmap[cpt].
B + 1.0;
189 for (
int sc = 0; sc < scaleDiv; sc++) {
191 double sigma = retinexScales[(size_t)sc];
194 for (
unsigned int cpt = 0; cpt < size; cpt++) {
198 doubleResRGB[(size_t)channel].bitmap[cpt] +=
199 weight * (std::log(doubleRGB[(
size_t)channel].bitmap[cpt]) - std::log(blurImage.
bitmap[cpt]));
204 std::vector<double> dest(size * 3);
205 const double gain = 1.0, alpha = 128.0, offset = 0.0;
207 for (
unsigned int cpt = 0; cpt < size; cpt++) {
210 dest[cpt * 3] = gain * (std::log(alpha * doubleRGB[0].bitmap[cpt]) - logl) * doubleResRGB[0].bitmap[cpt] + offset;
212 gain * (std::log(alpha * doubleRGB[1].bitmap[cpt]) - logl) * doubleResRGB[1].bitmap[cpt] + offset;
214 gain * (std::log(alpha * doubleRGB[2].bitmap[cpt]) - logl) * doubleResRGB[2].bitmap[cpt] + offset;
217 double sum = std::accumulate(dest.begin(), dest.end(), 0.0);
218 double mean = sum / dest.size();
220 std::vector<double> diff(dest.size());
221 std::transform(dest.begin(), dest.end(), diff.begin(), std::bind2nd(std::minus<double>(), mean));
222 double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
223 double stdev = std::sqrt(sq_sum / dest.size());
225 double mini = mean - dynamic * stdev;
226 double maxi = mean + dynamic * stdev;
227 double range = maxi - mini;
233 for (
unsigned int cpt = 0; cpt < size; cpt++) {
234 I.
bitmap[cpt].
R = vpMath::saturate<unsigned char>((255.0 * (dest[cpt * 3 + 0] - mini) / range));
235 I.
bitmap[cpt].
G = vpMath::saturate<unsigned char>((255.0 * (dest[cpt * 3 + 1] - mini) / range));
236 I.
bitmap[cpt].
B = vpMath::saturate<unsigned char>((255.0 * (dest[cpt * 3 + 2] - mini) / range));
259 const int kernelSize)
262 if (scale < 16 || scale > 250) {
263 std::cerr <<
"Scale must be between the interval [16 - 250]" << std::endl;
268 if (scaleDiv < 1 || scaleDiv > 8) {
269 std::cerr <<
"Scale division must be between the interval [1 - 8]" << std::endl;
277 MSRCR(I, scale, scaleDiv, level, dynamic, kernelSize);
301 const double dynamic,
const int kernelSize)
304 vp::retinex(I2, scale, scaleDiv, level, dynamic, kernelSize);
unsigned int getWidth() const
unsigned char B
Blue component.
Type * bitmap
points toward the bitmap
unsigned char G
Green component.
static bool nul(double x, double s=0.001)
unsigned int getSize() const
static void gaussianBlur(const vpImage< unsigned char > &I, vpImage< double > &GI, unsigned int size=7, double sigma=0., bool normalize=true)
unsigned char R
Red component.
unsigned int getHeight() const
VISP_EXPORT void retinex(vpImage< vpRGBa > &I, const int scale=240, const int scaleDiv=3, const int level=RETINEX_UNIFORM, const double dynamic=1.2, const int kernelSize=-1)