Handle flat field images with different black levels than raw image

For bayer images handle flat field images with different black levels
than the raw image.
This commit is contained in:
Simone Gotti 2024-03-14 10:50:03 +01:00
parent 7751019b6e
commit 2aea26b5f3
3 changed files with 30 additions and 10 deletions

View File

@ -145,6 +145,7 @@ void ffInfo::updateRawImage()
int H = ri->get_height(); int H = ri->get_height();
int W = ri->get_width(); int W = ri->get_width();
ri->compress_image(0); ri->compress_image(0);
ri->set_prefilters();
int rSize = W * ((ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1) ? 1 : 3); int rSize = W * ((ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1) ? 1 : 3);
acc_t **acc = new acc_t*[H]; acc_t **acc = new acc_t*[H];
@ -165,6 +166,7 @@ void ffInfo::updateRawImage()
if( !temp->loadRaw(true)) { if( !temp->loadRaw(true)) {
temp->compress_image(0); //\ TODO would be better working on original, because is temporary temp->compress_image(0); //\ TODO would be better working on original, because is temporary
temp->set_prefilters();
nFiles++; nFiles++;
if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1 ) { if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1 ) {
@ -204,6 +206,7 @@ void ffInfo::updateRawImage()
ri = nullptr; ri = nullptr;
} else { } else {
ri->compress_image(0); ri->compress_image(0);
ri->set_prefilters();
} }
} }

View File

@ -263,13 +263,21 @@ void cfaboxblur(const float* const * riFlatFile, float* cfablur, int boxH, int b
namespace rtengine namespace rtengine
{ {
void RawImageSource::processFlatField(const procparams::RAWParams &raw, const RawImage *riFlatFile, array2D<float> &rawData, const float black[4]) void RawImageSource::processFlatField(const procparams::RAWParams &raw, RawImage *riFlatFile, array2D<float> &rawData, const float black[4])
{ {
// BENCHFUN // BENCHFUN
std::unique_ptr<float[]> cfablur(new float[H * W]); std::unique_ptr<float[]> cfablur(new float[H * W]);
const int BS = raw.ff_BlurRadius + (raw.ff_BlurRadius & 1); const int BS = raw.ff_BlurRadius + (raw.ff_BlurRadius & 1);
std::array<float, 4> ffblack;
{
const auto tmpfilters = riFlatFile->get_filters();
riFlatFile->set_filters(riFlatFile->prefilters); // we need 4 blacks for bayer processing
riFlatFile->get_colorsCoeff(nullptr, nullptr, ffblack.data(), false);
riFlatFile->set_filters(tmpfilters);
}
if (raw.ff_BlurType == procparams::RAWParams::getFlatFieldBlurTypeString(procparams::RAWParams::FlatFieldBlurType::V)) { if (raw.ff_BlurType == procparams::RAWParams::getFlatFieldBlurTypeString(procparams::RAWParams::FlatFieldBlurType::V)) {
cfaboxblur(riFlatFile->data, cfablur.get(), 2 * BS, 0, H, W); cfaboxblur(riFlatFile->data, cfablur.get(), 2 * BS, 0, H, W);
} else if (raw.ff_BlurType == procparams::RAWParams::getFlatFieldBlurTypeString(procparams::RAWParams::FlatFieldBlurType::H)) { } else if (raw.ff_BlurType == procparams::RAWParams::getFlatFieldBlurTypeString(procparams::RAWParams::FlatFieldBlurType::H)) {
@ -291,7 +299,7 @@ void RawImageSource::processFlatField(const procparams::RAWParams &raw, const Ra
const int col = 2 * (W >> 2) + n; const int col = 2 * (W >> 2) + n;
const int c = ri->get_colors() != 1 ? FC(row, col) : 0; const int c = ri->get_colors() != 1 ? FC(row, col) : 0;
const int c4 = ri->get_colors() != 1 ? ((c == 1 && !(row & 1)) ? 3 : c) : 0; const int c4 = ri->get_colors() != 1 ? ((c == 1 && !(row & 1)) ? 3 : c) : 0;
refcolor[m][n] = std::max(0.0f, cfablur[row * W + col] - black[c4]); refcolor[m][n] = std::max(0.0f, cfablur[row * W + col] - ffblack[c4]);
} }
float limitFactor = 1.f; float limitFactor = 1.f;
@ -314,7 +322,7 @@ void RawImageSource::processFlatField(const procparams::RAWParams &raw, const Ra
clippedBefore = true; clippedBefore = true;
break; break;
} }
const float tempval = (rawVal - black[c4]) * (refcolor[m][n] / std::max(1e-5f, cfablur[(row + m) * W + col + n] - black[c4])); const float tempval = (rawVal - black[c4]) * (refcolor[m][n] / std::max(1e-5f, cfablur[(row + m) * W + col + n] - ffblack[c4]));
maxval = std::max(maxval, tempval); maxval = std::max(maxval, tempval);
} }
} }
@ -363,6 +371,9 @@ void RawImageSource::processFlatField(const procparams::RAWParams &raw, const Ra
const vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]), const vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]),
_mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]]) _mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]])
}; };
const vfloat ffblackv[2] = {_mm_set_ps(ffblack[c4[0][1]], ffblack[c4[0][0]], ffblack[c4[0][1]], ffblack[c4[0][0]]),
_mm_set_ps(ffblack[c4[1][1]], ffblack[c4[1][0]], ffblack[c4[1][1]], ffblack[c4[1][0]])
};
const vfloat onev = F2V(1.f); const vfloat onev = F2V(1.f);
const vfloat minValuev = F2V(minValue); const vfloat minValuev = F2V(minValue);
@ -375,10 +386,11 @@ void RawImageSource::processFlatField(const procparams::RAWParams &raw, const Ra
int col = 0; int col = 0;
#ifdef __SSE2__ #ifdef __SSE2__
const vfloat rowBlackv = blackv[row & 1]; const vfloat rowBlackv = blackv[row & 1];
const vfloat ffrowBlackv = ffblackv[row & 1];
const vfloat rowRefcolorv = refcolorv[row & 1]; const vfloat rowRefcolorv = refcolorv[row & 1];
for (; col < W - 3; col += 4) { for (; col < W - 3; col += 4) {
const vfloat blurv = LVFU(cfablur[row * W + col]) - rowBlackv; const vfloat blurv = LVFU(cfablur[row * W + col]) - ffrowBlackv;
vfloat vignettecorrv = rowRefcolorv / blurv; vfloat vignettecorrv = rowRefcolorv / blurv;
vignettecorrv = vself(vmaskf_le(blurv, minValuev), onev, vignettecorrv); vignettecorrv = vself(vmaskf_le(blurv, minValuev), onev, vignettecorrv);
const vfloat valv = LVFU(rawData[row][col]) - rowBlackv; const vfloat valv = LVFU(rawData[row][col]) - rowBlackv;
@ -388,7 +400,7 @@ void RawImageSource::processFlatField(const procparams::RAWParams &raw, const Ra
#endif #endif
for (; col < W; ++col) { for (; col < W; ++col) {
const float blur = cfablur[row * W + col] - black[c4[row & 1][col & 1]]; const float blur = cfablur[row * W + col] - ffblack[c4[row & 1][col & 1]];
const float vignettecorr = blur <= minValue ? 1.f : refcolor[row & 1][col & 1] / blur; const float vignettecorr = blur <= minValue ? 1.f : refcolor[row & 1][col & 1] / blur;
rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * vignettecorr + black[c4[row & 1][col & 1]]; rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * vignettecorr + black[c4[row & 1][col & 1]];
} }
@ -490,6 +502,10 @@ void RawImageSource::processFlatField(const procparams::RAWParams &raw, const Ra
const vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]), const vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]),
_mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]]) _mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]])
}; };
const vfloat ffblackv[2] = {_mm_set_ps(ffblack[c4[0][1]], ffblack[c4[0][0]], ffblack[c4[0][1]], ffblack[c4[0][0]]),
_mm_set_ps(ffblack[c4[1][1]], ffblack[c4[1][0]], ffblack[c4[1][1]], ffblack[c4[1][0]])
};
const vfloat epsv = F2V(1e-5f); const vfloat epsv = F2V(1e-5f);
#endif #endif
@ -501,10 +517,11 @@ void RawImageSource::processFlatField(const procparams::RAWParams &raw, const Ra
int col = 0; int col = 0;
#ifdef __SSE2__ #ifdef __SSE2__
const vfloat rowBlackv = blackv[row & 1]; const vfloat rowBlackv = blackv[row & 1];
const vfloat ffrowBlackv = ffblackv[row & 1];
for (; col < W - 3; col += 4) { for (; col < W - 3; col += 4) {
const vfloat linecorrv = SQRV(vmaxf(LVFU(cfablur[row * W + col]) - rowBlackv, epsv)) / const vfloat linecorrv = SQRV(vmaxf(LVFU(cfablur[row * W + col]) - ffrowBlackv, epsv)) /
(vmaxf(LVFU(cfablur1[row * W + col]) - rowBlackv, epsv) * vmaxf(LVFU(cfablur2[row * W + col]) - rowBlackv, epsv)); (vmaxf(LVFU(cfablur1[row * W + col]) - ffrowBlackv, epsv) * vmaxf(LVFU(cfablur2[row * W + col]) - ffrowBlackv, epsv));
const vfloat valv = LVFU(rawData[row][col]) - rowBlackv; const vfloat valv = LVFU(rawData[row][col]) - rowBlackv;
STVFU(rawData[row][col], valv * linecorrv + rowBlackv); STVFU(rawData[row][col], valv * linecorrv + rowBlackv);
} }
@ -512,8 +529,8 @@ void RawImageSource::processFlatField(const procparams::RAWParams &raw, const Ra
#endif #endif
for (; col < W; ++col) { for (; col < W; ++col) {
const float linecorr = SQR(std::max(1e-5f, cfablur[row * W + col] - black[c4[row & 1][col & 1]])) / const float linecorr = SQR(std::max(1e-5f, cfablur[row * W + col] - ffblack[c4[row & 1][col & 1]])) /
(std::max(1e-5f, cfablur1[row * W + col] - black[c4[row & 1][col & 1]]) * std::max(1e-5f, cfablur2[row * W + col] - black[c4[row & 1][col & 1]])); (std::max(1e-5f, cfablur1[row * W + col] - ffblack[c4[row & 1][col & 1]]) * std::max(1e-5f, cfablur2[row * W + col] - ffblack[c4[row & 1][col & 1]]));
rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * linecorr + black[c4[row & 1][col & 1]]; rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * linecorr + black[c4[row & 1][col & 1]];
} }
} }

View File

@ -138,7 +138,7 @@ public:
return rgbSourceModified; // tracks whether cached rgb output of demosaic has been modified return rgbSourceModified; // tracks whether cached rgb output of demosaic has been modified
} }
void processFlatField(const procparams::RAWParams &raw, const RawImage *riFlatFile, array2D<float> &rawData, const float black[4]); void processFlatField(const procparams::RAWParams &raw, RawImage *riFlatFile, array2D<float> &rawData, const float black[4]);
void copyOriginalPixels(const procparams::RAWParams &raw, RawImage *ri, const RawImage *riDark, RawImage *riFlatFile, array2D<float> &rawData ); void copyOriginalPixels(const procparams::RAWParams &raw, RawImage *ri, const RawImage *riDark, RawImage *riFlatFile, array2D<float> &rawData );
void scaleColors (int winx, int winy, int winw, int winh, const procparams::RAWParams &raw, array2D<float> &rawData); // raw for cblack void scaleColors (int winx, int winy, int winw, int winh, const procparams::RAWParams &raw, array2D<float> &rawData); // raw for cblack
void WBauto(bool extra, double &tempref, double &greenref, array2D<float> &redloc, array2D<float> &greenloc, array2D<float> &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &temp0, float &delta, int &bia, int &dread, int &kcam, int &nocam, float &studgood, float &minchrom, int &kmin, float &minhist, float &maxhist, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override; void WBauto(bool extra, double &tempref, double &greenref, array2D<float> &redloc, array2D<float> &greenloc, array2D<float> &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &temp0, float &delta, int &bia, int &dread, int &kcam, int &nocam, float &studgood, float &minchrom, int &kmin, float &minhist, float &maxhist, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override;