Speedup and reduced memory usage for xtrans dual demosaic

This commit is contained in:
Ingo Weyrich 2020-09-05 13:50:50 +02:00
parent 929a5ce727
commit 498a39a88f
3 changed files with 81 additions and 26 deletions

View File

@ -111,41 +111,34 @@ void RawImageSource::dual_demosaic_RT(bool isBayer, const procparams::RAWParams
buildBlendMask(L, blend, winw, winh, contrastf, autoContrast);
contrast = contrastf * 100.f;
array2D<float>& redTmp = L; // L is not needed anymore => reuse it
array2D<float> greenTmp;
array2D<float> blueTmp;
if (isBayer) {
if (raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEBILINEAR) ||
raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCDBILINEAR) ||
raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBBILINEAR)) {
bayer_bilinear_demosaic(blend, rawData, red, green, blue);
return;
} else {
greenTmp(winw, winh);
blueTmp(winw, winh);
array2D<float>& redTmp = L; // L is not needed anymore => reuse it
array2D<float> greenTmp(winw, winh);
array2D<float> blueTmp(winw, winh);
vng4_demosaic(rawData, redTmp, greenTmp, blueTmp);
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16)
#endif
for(int i = 0; i < winh; ++i) {
// the following is split into 3 loops intentionally to avoid cache conflicts on CPUs with only 4-way cache
for(int j = 0; j < winw; ++j) {
red[i][j] = intp(blend[i][j], red[i][j], redTmp[i][j]);
}
for(int j = 0; j < winw; ++j) {
green[i][j] = intp(blend[i][j], green[i][j], greenTmp[i][j]);
}
for(int j = 0; j < winw; ++j) {
blue[i][j] = intp(blend[i][j], blue[i][j], blueTmp[i][j]);
}
}
}
} else {
greenTmp(winw, winh);
blueTmp(winw, winh);
fast_xtrans_interpolate(rawData, redTmp, greenTmp, blueTmp);
}
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic,16)
#endif
for(int i = 0; i < winh; ++i) {
// the following is split into 3 loops intentionally to avoid cache conflicts on CPUs with only 4-way cache
for(int j = 0; j < winw; ++j) {
red[i][j] = intp(blend[i][j], red[i][j], redTmp[i][j]);
}
for(int j = 0; j < winw; ++j) {
green[i][j] = intp(blend[i][j], green[i][j], greenTmp[i][j]);
}
for(int j = 0; j < winw; ++j) {
blue[i][j] = intp(blend[i][j], blue[i][j], blueTmp[i][j]);
}
fast_xtrans_interpolate_blend(blend, rawData, red, green, blue);
}
}
}

View File

@ -299,6 +299,7 @@ protected:
void xtransborder_interpolate (int border, array2D<float> &red, array2D<float> &green, array2D<float> &blue);
void xtrans_interpolate (const int passes, const bool useCieLab, size_t chunkSize = 1, bool measure = false);
void fast_xtrans_interpolate (const array2D<float> &rawData, array2D<float> &red, array2D<float> &green, array2D<float> &blue);
void fast_xtrans_interpolate_blend (const float* const * blend, const array2D<float> &rawData, array2D<float> &red, array2D<float> &green, array2D<float> &blue);
void pixelshift(int winx, int winy, int winw, int winh, const procparams::RAWParams &rawParams, unsigned int frame, const std::string &make, const std::string &model, float rawWpCorrection);
void bayer_bilinear_demosaic(const float *const * blend, const array2D<float> &rawData, array2D<float> &red, array2D<float> &green, array2D<float> &blue);
void hflip (Imagefloat* im);

View File

@ -1027,6 +1027,67 @@ void RawImageSource::fast_xtrans_interpolate (const array2D<float> &rawData, arr
plistener->setProgress (1.0);
}
}
void RawImageSource::fast_xtrans_interpolate_blend (const float* const * blend, const array2D<float> &rawData, array2D<float> &red, array2D<float> &green, array2D<float> &blue)
{
if (plistener) {
plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_XTRANSFAST")));
plistener->setProgress(0.0);
}
int xtrans[6][6];
ri->getXtransMatrix(xtrans);
const float weight[3][3] = {
{0.25f, 0.5f, 0.25f},
{0.5f, 0.f, 0.5f},
{0.25f, 0.5f, 0.25f}
};
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16)
#endif
for (int row = 8; row < H - 8; ++row) {
for (int col = 8; col < W - 8; ++col) {
float sum[3] = {};
for (int v = -1; v <= 1; v++) {
for (int h = -1; h <= 1; h++) {
sum[fcol(row + v, col + h)] += rawData[row + v][(col + h)] * weight[v + 1][h + 1];
}
}
switch(fcol(row, col)) {
case 0: // red pixel
red[row][col] = intp(blend[row][col], red[row][col], rawData[row][col]);
green[row][col] = intp(blend[row][col], green[row][col], sum[1] * 0.5f);
blue[row][col] = intp(blend[row][col], blue[row][col], sum[2]);
break;
case 1: // green pixel
green[row][col] = intp(blend[row][col], green[row][col], rawData[row][col]);
if (fcol(row, col - 1) == fcol(row, col + 1)) { // Solitary green pixel always has exactly two direct red and blue neighbors in 3x3 grid
red[row][col] = intp(blend[row][col], red[row][col], sum[0]);
blue[row][col] = intp(blend[row][col], blue[row][col], sum[2]);
} else { // Non solitary green pixel always has one direct and one diagonal red and blue neighbor in 3x3 grid
red[row][col] = intp(blend[row][col], red[row][col], sum[0] * 1.3333333f);
blue[row][col] = intp(blend[row][col], blue[row][col], sum[2] * 1.3333333f);
}
break;
case 2: // blue pixel
red[row][col] = intp(blend[row][col], red[row][col], sum[0]);
green[row][col] = intp(blend[row][col], green[row][col], sum[1] * 0.5f);
blue[row][col] = intp(blend[row][col], blue[row][col], rawData[row][col]);
break;
}
}
}
if (plistener) {
plistener->setProgress (1.0);
}
}
#undef fcol
#undef isgreen