Improve HLreconstruction color propagation - best transitions - code from ART - thanks to Alberto
This commit is contained in:
parent
e8da58ad24
commit
b554f52ab9
@ -34,6 +34,12 @@
|
|||||||
#include "rt_math.h"
|
#include "rt_math.h"
|
||||||
#define BENCHMARK
|
#define BENCHMARK
|
||||||
#include "StopWatch.h"
|
#include "StopWatch.h"
|
||||||
|
#include "guidedfilter.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "gauss.h"
|
||||||
|
#include "rescale.h"
|
||||||
|
#include "iccstore.h"
|
||||||
|
#include "color.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -289,6 +295,9 @@ void boxblur_resamp(const float* const* src, float** dst, float** temp, int H, i
|
|||||||
|
|
||||||
namespace rtengine
|
namespace rtengine
|
||||||
{
|
{
|
||||||
|
extern const Settings *settings;
|
||||||
|
using namespace procparams;
|
||||||
|
const ProcParams params;
|
||||||
|
|
||||||
void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plistener) {
|
// if (plistener) {
|
||||||
progress += 0.05;
|
// progress += 0.05;
|
||||||
plistener->setProgress(progress);
|
// plistener->setProgress(progress);
|
||||||
}
|
// }
|
||||||
|
|
||||||
constexpr int blurBorder = 256;
|
constexpr int blurBorder = 256;
|
||||||
minx = std::max(0, minx - blurBorder);
|
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);
|
boxblur2(red, channelblur[0], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4);
|
||||||
|
|
||||||
if (plistener) {
|
// if (plistener) {
|
||||||
progress += 0.07;
|
// progress += 0.07;
|
||||||
plistener->setProgress(progress);
|
// plistener->setProgress(progress);
|
||||||
}
|
// }
|
||||||
|
|
||||||
boxblur2(green, channelblur[1], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4);
|
boxblur2(green, channelblur[1], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4);
|
||||||
|
|
||||||
if (plistener) {
|
// if (plistener) {
|
||||||
progress += 0.07;
|
// progress += 0.07;
|
||||||
plistener->setProgress(progress);
|
// plistener->setProgress(progress);
|
||||||
}
|
// }
|
||||||
|
|
||||||
boxblur2(blue, channelblur[2], temp, miny, minx, blurHeight, blurWidth, bufferWidth, 4);
|
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
|
// 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
|
#ifdef _OPENMP
|
||||||
#pragma omp parallel for schedule(dynamic,16)
|
#pragma omp parallel for schedule(dynamic,16)
|
||||||
@ -1080,15 +1121,18 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue
|
|||||||
if (UNLIKELY(!totwt)) {
|
if (UNLIKELY(!totwt)) {
|
||||||
continue;
|
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
|
//now correct clipped channels
|
||||||
if (pixel[0] > max_f[0] && pixel[1] > max_f[1] && pixel[2] > max_f[2]) {
|
if (pixel[0] > max_f[0] && pixel[1] > max_f[1] && pixel[2] > max_f[2]) {
|
||||||
//all channels clipped
|
//all channels clipped
|
||||||
|
|
||||||
const float mult = whitept / (0.299f * clipfix[0] + 0.587f * clipfix[1] + 0.114f * clipfix[2]);
|
const float mult = whitept / (0.299f * clipfix[0] + 0.587f * clipfix[1] + 0.114f * clipfix[2]);
|
||||||
red[i + miny][j + minx] = clipfix[0] * mult;
|
red[yy][xx] = clipfix[0] * mult;
|
||||||
green[i + miny][j + minx] = clipfix[1] * mult;
|
green[yy][xx] = clipfix[1] * mult;
|
||||||
blue[i + miny][j + minx] = clipfix[2] * mult;
|
blue[yy][xx] = clipfix[2] * mult;
|
||||||
} else {//some channels clipped
|
} else {//some channels clipped
|
||||||
const float notclipped[3] = {
|
const float notclipped[3] = {
|
||||||
pixel[0] <= max_f[0] ? 1.f : 0.f,
|
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
|
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)));
|
(notclipped[1] * clipfix[1] + notclipped[2] * clipfix[2] + epsilon)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notclipped[1] == 0.f) { //green clipped
|
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)));
|
(notclipped[2] * clipfix[2] + notclipped[0] * clipfix[0] + epsilon)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notclipped[2] == 0.f) { //blue clipped
|
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)));
|
(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) {
|
if (Y > whitept) {
|
||||||
const float mult = whitept / Y;
|
const float mult = whitept / Y;
|
||||||
|
|
||||||
red[i + miny][j + minx] *= mult;
|
red[yy][xx] *= mult;
|
||||||
green[i + miny][j + minx] *= mult;
|
green[yy][xx] *= mult;
|
||||||
blue[i + miny][j + minx] *= 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) {
|
if (plistener) {
|
||||||
plistener->setProgress(1.00);
|
plistener->setProgress(1.00);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user