Improve HLreconstruction color propagation - best transitions - code from ART - thanks to Alberto

This commit is contained in:
Desmis 2021-01-07 12:08:10 +01:00
parent e8da58ad24
commit b554f52ab9

View File

@ -34,6 +34,12 @@
#include "rt_math.h"
#define BENCHMARK
#include "StopWatch.h"
#include "guidedfilter.h"
#include "settings.h"
#include "gauss.h"
#include "rescale.h"
#include "iccstore.h"
#include "color.h"
namespace
{
@ -289,6 +295,9 @@ void boxblur_resamp(const float* const* src, float** dst, float** temp, int H, i
namespace rtengine
{
extern const Settings *settings;
using namespace procparams;
const ProcParams params;
void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue)
{
@ -415,10 +424,10 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue
return;
}
if (plistener) {
progress += 0.05;
plistener->setProgress(progress);
}
// if (plistener) {
// progress += 0.05;
// plistener->setProgress(progress);
// }
constexpr int blurBorder = 256;
minx = std::max(0, minx - blurBorder);
@ -436,17 +445,17 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue
boxblur2(red, channelblur[0], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4);
if (plistener) {
progress += 0.07;
plistener->setProgress(progress);
}
// if (plistener) {
// progress += 0.07;
// plistener->setProgress(progress);
// }
boxblur2(green, channelblur[1], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4);
if (plistener) {
progress += 0.07;
plistener->setProgress(progress);
}
// if (plistener) {
// progress += 0.07;
// plistener->setProgress(progress);
// }
boxblur2(blue, channelblur[2], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4);
@ -931,6 +940,38 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// now reconstruct clipped channels using color ratios
//using code from ART - thanks to Alberto Griggio
const int W2 = float(W) / 2.f + 0.5f;
const int H2 = float(H) / 2.f + 0.5f;
array2D<float> mask(W2, H2, ARRAY2D_CLEAR_DATA);
array2D<float> rbuf(W2, H2);
array2D<float> gbuf(W2, H2);
array2D<float> bbuf(W2, H2);
array2D<float> guide(W2, H2);
array2D<float> Y(W2, H2);
using rtengine::TMatrix;
TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(params.icm.workingProfile);
{
array2D<float> rsrc(W, H, red, ARRAY2D_BYREFERENCE);
array2D<float> gsrc(W, H, green, ARRAY2D_BYREFERENCE);
array2D<float> bsrc(W, H, blue, ARRAY2D_BYREFERENCE);
rescaleNearest(rsrc, rbuf, true);
rescaleNearest(gsrc, gbuf, true);
rescaleNearest(bsrc, bbuf, true);
#ifdef _OPENMP
# pragma omp parallel for
#endif
for (int y = 0; y < H2; ++y) {
for (int x = 0; x < W2; ++x) {
Y[y][x] = rtengine::Color::rgbLuminance(static_cast<double>(rbuf[y][x]), static_cast<double>(gbuf[y][x]), static_cast<double>(bbuf[y][x]), ws);
guide[y][x] = Color::igamma_srgb(Y[y][x]);
}
}
}
//end addind code ART
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16)
@ -1080,15 +1121,18 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue
if (UNLIKELY(!totwt)) {
continue;
}
//using code from ART - thanks to Alberto Griggio
float maskval = 1.f;
int yy = i + miny;
int xx = j + minx;
//now correct clipped channels
if (pixel[0] > max_f[0] && pixel[1] > max_f[1] && pixel[2] > max_f[2]) {
//all channels clipped
const float mult = whitept / (0.299f * clipfix[0] + 0.587f * clipfix[1] + 0.114f * clipfix[2]);
red[i + miny][j + minx] = clipfix[0] * mult;
green[i + miny][j + minx] = clipfix[1] * mult;
blue[i + miny][j + minx] = clipfix[2] * mult;
red[yy][xx] = clipfix[0] * mult;
green[yy][xx] = clipfix[1] * mult;
blue[yy][xx] = clipfix[2] * mult;
} else {//some channels clipped
const float notclipped[3] = {
pixel[0] <= max_f[0] ? 1.f : 0.f,
@ -1097,33 +1141,84 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue
};
if (notclipped[0] == 0.f) { //red clipped
red[i + miny][j + minx] = max(pixel[0], clipfix[0] * ((notclipped[1] * pixel[1] + notclipped[2] * pixel[2]) /
red[yy][xx] = max(pixel[0], clipfix[0] * ((notclipped[1] * pixel[1] + notclipped[2] * pixel[2]) /
(notclipped[1] * clipfix[1] + notclipped[2] * clipfix[2] + epsilon)));
}
if (notclipped[1] == 0.f) { //green clipped
green[i + miny][j + minx] = max(pixel[1], clipfix[1] * ((notclipped[2] * pixel[2] + notclipped[0] * pixel[0]) /
green[yy][xx] = max(pixel[1], clipfix[1] * ((notclipped[2] * pixel[2] + notclipped[0] * pixel[0]) /
(notclipped[2] * clipfix[2] + notclipped[0] * clipfix[0] + epsilon)));
}
if (notclipped[2] == 0.f) { //blue clipped
blue[i + miny][j + minx] = max(pixel[2], clipfix[2] * ((notclipped[0] * pixel[0] + notclipped[1] * pixel[1]) /
blue[yy][xx] = max(pixel[2], clipfix[2] * ((notclipped[0] * pixel[0] + notclipped[1] * pixel[1]) /
(notclipped[0] * clipfix[0] + notclipped[1] * clipfix[1] + epsilon)));
}
maskval = 1.f - (notclipped[0] + notclipped[1] + notclipped[2]) / 5.f;
}
Y = 0.299f * red[i + miny][j + minx] + 0.587f * green[i + miny][j + minx] + 0.114f * blue[i + miny][j + minx];
Y = 0.299f * red[yy][xx] + 0.587f * green[yy][xx] + 0.114f * blue[yy][xx];
if (Y > whitept) {
const float mult = whitept / Y;
red[i + miny][j + minx] *= mult;
green[i + miny][j + minx] *= mult;
blue[i + miny][j + minx] *= mult;
red[yy][xx] *= mult;
green[yy][xx] *= mult;
blue[yy][xx] *= mult;
}
int ii = (yy) / 2;
int jj = (xx) / 2;
rbuf[ii][jj] = red[yy][xx];
gbuf[ii][jj] = green[yy][xx];
bbuf[ii][jj] = blue[yy][xx];
mask[ii][jj] = maskval;
}
}
if (plistener) {
progress += 0.05;
plistener->setProgress(progress);
}
// #ifdef _OPENMP
// #pragma omp parallel
// #endif
{
//gaussianBlur(mask, mask, W/2, H/2, 5);
// gaussianBlur(rbuf, rbuf, W/2, H/2, 1);
// gaussianBlur(gbuf, gbuf, W/2, H/2, 1);
// gaussianBlur(bbuf, bbuf, W/2, H/2, 1);
guidedFilter(guide, mask, mask, 2, 0.001f, true, 1);
guidedFilter(guide, rbuf, rbuf, 3, 0.01f * 65535.f, true, 1);
guidedFilter(guide, gbuf, gbuf, 3, 0.01f * 65535.f, true, 1);
guidedFilter(guide, bbuf, bbuf, 3, 0.01f * 65535.f, true, 1);
}
{
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int y = 0; y < H; ++y) {
float fy = y * 0.5f;
int yy = y / 2;
for (int x = 0; x < W; ++x) {
float fx = x * 0.5f;
int xx = x / 2;
float m = mask[yy][xx];
if (m > 0.f) {
red[y][x] = intp(m, getBilinearValue(rbuf, fx, fy), red[y][x]);
green[y][x] = intp(m, getBilinearValue(gbuf, fx, fy), green[y][x]);
blue[y][x] = intp(m, getBilinearValue(bbuf, fx, fy), blue[y][x]);
}
}
}
}
if (plistener) {
plistener->setProgress(1.00);
}