From 0da47b0da37610c4728d3835496a788d41475132 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 18 Oct 2018 22:09:35 +0200 Subject: [PATCH] 2-pass dual-demosaic-contrast-threshold detection if 1-pass does not find a flat area, #4866 --- rtengine/dual_demosaic_RT.cc | 20 +----- rtengine/rawimagesource.cc | 4 +- rtengine/rawimagesource.h | 2 +- rtengine/rt_algo.cc | 125 ++++++++++++++++++----------------- 4 files changed, 70 insertions(+), 81 deletions(-) diff --git a/rtengine/dual_demosaic_RT.cc b/rtengine/dual_demosaic_RT.cc index 5425e9d01..862516416 100644 --- a/rtengine/dual_demosaic_RT.cc +++ b/rtengine/dual_demosaic_RT.cc @@ -36,7 +36,7 @@ using namespace std; namespace rtengine { -void RawImageSource::dual_demosaic_RT(bool isBayer, const RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast, int autoX, int autoY) +void RawImageSource::dual_demosaic_RT(bool isBayer, const RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast) { BENCHFUN @@ -91,24 +91,6 @@ void RawImageSource::dual_demosaic_RT(bool isBayer, const RAWParams &raw, int wi { 0.019334, 0.119193, 0.950227 } }; - if (autoContrast && autoX >= 0 && autoY >= 0) { - constexpr int rectSize = 40; - const int autoWidth = min(rectSize, winw - autoX); - const int autoHeight = min(rectSize, winh - autoY); - if (std::min(autoWidth, autoHeight) > 20) { - array2D autoL(autoWidth, autoHeight); - for(int i = 0; i < autoHeight; ++i) { - Color::RGB2L(red[i + autoY] + autoX, green[i + autoY] + autoX, blue[i + autoY] + autoX, autoL[i], xyz_rgb, autoWidth); - } - // calculate contrast based blend factors to use vng4 in regions with low contrast - JaggedArray blend(autoWidth - 2, autoHeight - 2); - int c = calcContrastThreshold(autoL, blend, autoWidth, autoHeight); - if(c < 100) { - contrast = c; // alternative : contrast = c - 1 - } - } - } - #pragma omp parallel { #pragma omp for diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 1f84cad54..3de802232 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2074,7 +2074,7 @@ void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &c double threshold = raw.bayersensor.dualDemosaicContrast; dual_demosaic_RT (true, raw, W, H, rawData, red, green, blue, threshold, false); } else { - dual_demosaic_RT (true, raw, W, H, rawData, red, green, blue, contrastThreshold, true, 0, 0); + dual_demosaic_RT (true, raw, W, H, rawData, red, green, blue, contrastThreshold, true); } } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::PIXELSHIFT) ) { pixelshift(0, 0, W, H, raw, currFrame, ri->get_maker(), ri->get_model(), raw.expos); @@ -2107,7 +2107,7 @@ void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &c double threshold = raw.xtranssensor.dualDemosaicContrast; dual_demosaic_RT (false, raw, W, H, rawData, red, green, blue, threshold, false); } else { - dual_demosaic_RT (false, raw, W, H, rawData, red, green, blue, contrastThreshold, true, 0, 0); + dual_demosaic_RT (false, raw, W, H, rawData, red, green, blue, contrastThreshold, true); } } else if(raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::MONO) ) { nodemosaic(true); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index ad7807a44..1e2a1984d 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -274,7 +274,7 @@ protected: void igv_interpolate(int winw, int winh); void lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations); void amaze_demosaic_RT(int winx, int winy, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue);//Emil's code for AMaZE - void dual_demosaic_RT(bool isBayer, const RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast = false, int autoX = -1, int autoY = -1); + void dual_demosaic_RT(bool isBayer, const RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast = false); void fast_demosaic();//Emil's code for fast demosaicing void dcb_demosaic(int iterations, bool dcb_enhance); void ahd_demosaic(); diff --git a/rtengine/rt_algo.cc b/rtengine/rt_algo.cc index 49c972a47..71fa4fa6f 100644 --- a/rtengine/rt_algo.cc +++ b/rtengine/rt_algo.cc @@ -204,80 +204,87 @@ void buildBlendMask(float** luminance, float **blend, int W, int H, float contra constexpr float scale = 0.0625f / 327.68f; if (autoContrast) { StopWatch StopC("calculate dual demosaic auto contrast threshold"); - constexpr int tilesize = 80; - const int numTilesW = W / tilesize; - const int numTilesH = H / tilesize; - std::vector>> variances(numTilesH, std::vector>(numTilesW)); + for (int pass = 0; pass < 2; ++pass) { + const int tilesize = 80 / (pass + 1); + const int numTilesW = W / tilesize; + const int numTilesH = H / tilesize; + std::vector>> variances(numTilesH, std::vector>(numTilesW)); - #pragma omp parallel for - for (int i = 0; i < numTilesH; ++i) { - int tileY = i * tilesize; - for (int j = 0; j < numTilesW; ++j) { - int tileX = j * tilesize; + #pragma omp parallel for + for (int i = 0; i < numTilesH; ++i) { + int tileY = i * tilesize; + for (int j = 0; j < numTilesW; ++j) { + int tileX = j * tilesize; #ifdef __SSE2__ - vfloat avgv = ZEROV; - for (int y = tileY; y < tileY + tilesize; ++y) { - for (int x = tileX; x < tileX + tilesize; x += 4) { - avgv += LVFU(luminance[y][x]); + vfloat avgv = ZEROV; + for (int y = tileY; y < tileY + tilesize; ++y) { + for (int x = tileX; x < tileX + tilesize; x += 4) { + avgv += LVFU(luminance[y][x]); + } } - } - float avg = vhadd(avgv); + float avg = vhadd(avgv); #else - float avg = 0.; - for (int y = tileY; y < tileY + tilesize; ++y) { - for (int x = tileX; x < tileX + tilesize; ++x) { - avg += luminance[y][x]; + float avg = 0.; + for (int y = tileY; y < tileY + tilesize; ++y) { + for (int x = tileX; x < tileX + tilesize; ++x) { + avg += luminance[y][x]; + } } - } #endif - avg /= SQR(tilesize); + avg /= SQR(tilesize); #ifdef __SSE2__ - vfloat varv = ZEROV; - avgv = F2V(avg); - for (int y = tileY; y < tileY + tilesize; ++y) { - for (int x = tileX; x < tileX + tilesize; x +=4) { - varv += SQRV(LVFU(luminance[y][x]) - avgv); + vfloat varv = ZEROV; + avgv = F2V(avg); + for (int y = tileY; y < tileY + tilesize; ++y) { + for (int x = tileX; x < tileX + tilesize; x +=4) { + varv += SQRV(LVFU(luminance[y][x]) - avgv); + } } - } - float var = vhadd(varv); + float var = vhadd(varv); #else - float var = 0.0; - for (int y = tileY; y < tileY + tilesize; ++y) { - for (int x = tileX; x < tileX + tilesize; ++x) { - var += SQR(luminance[y][x] - avg); + float var = 0.0; + for (int y = tileY; y < tileY + tilesize; ++y) { + for (int x = tileX; x < tileX + tilesize; ++x) { + var += SQR(luminance[y][x] - avg); + } + } + #endif + var /= (SQR(tilesize) * avg); + variances[i][j].first = var; + variances[i][j].second = avg; + } + } + + float minvar = RT_INFINITY_F; + int minI = 0, minJ = 0; + for (int i = 0; i < numTilesH; ++i) { + for (int j = 0; j < numTilesW; ++j) { + if (variances[i][j].first < minvar && variances[i][j].second > 2000.f && variances[i][j].second < 20000.f) { + minvar = variances[i][j].first; + minI = i; + minJ = j; } } -#endif - var /= (SQR(tilesize) * avg); - variances[i][j].first = var; - variances[i][j].second = avg; } - } - float minvar = RT_INFINITY_F; - int minY = 0, minX = 0; - for (int i = 0; i < numTilesH; ++i) { - for (int j = 0; j < numTilesW; ++j) { - if (variances[i][j].first < minvar && variances[i][j].second > 2000.f && variances[i][j].second < 20000.f) { - minvar = variances[i][j].first; - minY = tilesize * i; - minX = tilesize * j; + const int minY = tilesize * minI; + const int minX = tilesize * minJ; + std::cout << "minvar : " << minvar << std::endl; + +// if (minvar <= 1.f || pass == 1) { + // a variance <= 1 means we already found a flat region and can skip second pass + JaggedArray Lum(tilesize, tilesize); + JaggedArray Blend(tilesize, tilesize); + for (int i = 0; i < tilesize; ++i) { + for (int j = 0; j < tilesize; ++j) { + Lum[i][j] = luminance[i + minY][j + minX]; + } } - } - } -// std::cout << "minY : " << minY << std::endl; -// std::cout << "minX : " << minX << std::endl; -// std::cout << "minvar : " << minvar << std::endl; - JaggedArray Lum(tilesize, tilesize); - JaggedArray Blend(tilesize, tilesize); - for (int i = 0; i < tilesize; ++i) { - for (int j = 0; j < tilesize; ++j) { - Lum[i][j] = luminance[i + minY][j + minX]; - } + /*contrastThreshold = */calcContrastThreshold(Lum, Blend, tilesize, tilesize);// / 100.f; +// break; +// } } - - calcContrastThreshold(Lum, Blend, tilesize, tilesize); } #ifdef _OPENMP @@ -368,7 +375,7 @@ int calcContrastThreshold(float** luminance, float **blend, int W, int H) { } } - const float limit = (W - 2) * (H - 2) / 100.f; + const float limit = (W - 4) * (H - 4) / 100.f; int c; for (c = 1; c < 100; ++c) {