diff --git a/rtengine/green_equil_RT.cc b/rtengine/green_equil_RT.cc index 90c412871..5fdf052b7 100644 --- a/rtengine/green_equil_RT.cc +++ b/rtengine/green_equil_RT.cc @@ -89,7 +89,7 @@ void RawImageSource::green_equilibrate_global(array2D &rawData) } //void green_equilibrate()//for dcraw implementation -void RawImageSource::green_equilibrate(float thresh, array2D &rawData) +void RawImageSource::green_equilibrate(const GreenEqulibrateThreshold &thresh, array2D &rawData) { // thresh = threshold for performing green equilibration; max percentage difference of G1 vs G2 // G1-G2 differences larger than this will be assumed to be Nyquist texture, and left untouched @@ -119,7 +119,7 @@ void RawImageSource::green_equilibrate(float thresh, array2D &rawData) } constexpr float eps = 1.f; //tolerance to avoid dividing by zero - const float thresh6 = 6 * thresh; + // const float thresh6 = 6 * thresh; // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Fill G interpolated values with border interpolation and input values @@ -136,8 +136,8 @@ void RawImageSource::green_equilibrate(float thresh, array2D &rawData) #ifdef __SSE2__ vfloat zd5v = F2V(0.5f); vfloat onev = F2V(1.f); - vfloat threshv = F2V(thresh); - vfloat thresh6v = F2V(thresh6); + // vfloat threshv = F2V(thresh); + // vfloat thresh6v = F2V(thresh6); vfloat epsv = F2V(eps); #endif #ifdef _OPENMP @@ -165,7 +165,14 @@ void RawImageSource::green_equilibrate(float thresh, array2D &rawData) vfloat c1 = (vabsf(o1_1 - o1_2) + vabsf(o1_1 - o1_3) + vabsf(o1_1 - o1_4) + vabsf(o1_2 - o1_3) + vabsf(o1_3 - o1_4) + vabsf(o1_2 - o1_4)); vfloat c2 = (vabsf(o2_1 - o2_2) + vabsf(o2_1 - o2_3) + vabsf(o2_1 - o2_4) + vabsf(o2_2 - o2_3) + vabsf(o2_3 - o2_4) + vabsf(o2_2 - o2_4)); - vmask mask1 = vmaskf_lt(c1 + c2, thresh6v * vabsf(d1 - d2)); + vfloat tfv; + vfloat tf6v; + for (int k = 0; k < 4; ++k) { + tfv[k] = thresh(rr, cc+k); + tf6v[k] = 6 * tfv[k]; + } + + vmask mask1 = vmaskf_lt(c1 + c2, tf6v * vabsf(d1 - d2)); if (_mm_movemask_ps((vfloat)mask1)) { // if for any of the 4 pixels the condition is true, do the maths for all 4 pixels and mask the unused out at the end //pixel interpolation @@ -188,7 +195,7 @@ void RawImageSource::green_equilibrate(float thresh, array2D &rawData) vfloat ginterp = (gse * wtse + gnw * wtnw + gne * wtne + gsw * wtsw) / (wtse + wtnw + wtne + wtsw); - vfloat val = vself(vmaskf_lt(ginterp - gin, threshv * (ginterp + gin)), zd5v * (ginterp + gin), gin); + vfloat val = vself(vmaskf_lt(ginterp - gin, tfv * (ginterp + gin)), zd5v * (ginterp + gin), gin); val = vself(mask1, val, gin); STC2VFU(rawData[rr][cc], val); } @@ -213,7 +220,9 @@ void RawImageSource::green_equilibrate(float thresh, array2D &rawData) float c1 = (fabs(o1_1 - o1_2) + fabs(o1_1 - o1_3) + fabs(o1_1 - o1_4) + fabs(o1_2 - o1_3) + fabs(o1_3 - o1_4) + fabs(o1_2 - o1_4)); float c2 = (fabs(o2_1 - o2_2) + fabs(o2_1 - o2_3) + fabs(o2_1 - o2_4) + fabs(o2_2 - o2_3) + fabs(o2_3 - o2_4) + fabs(o2_2 - o2_4)); - if (c1 + c2 < thresh6 * fabs(d1 - d2)) { + float tf = thresh(rr, cc); + + if (c1 + c2 < 6 * tf * fabs(d1 - d2)) { //pixel interpolation float gin = cfa[rr][cc >> 1]; @@ -234,7 +243,7 @@ void RawImageSource::green_equilibrate(float thresh, array2D &rawData) float ginterp = (gse * wtse + gnw * wtnw + gne * wtne + gsw * wtsw) / (wtse + wtnw + wtne + wtsw); - if (ginterp - gin < thresh * (ginterp + gin)) { + if (ginterp - gin < tf * (ginterp + gin)) { rawData[rr][cc] = 0.5f * (ginterp + gin); } } diff --git a/rtengine/pdaflinesfilter.cc b/rtengine/pdaflinesfilter.cc index de1273ba3..482dbeb3e 100644 --- a/rtengine/pdaflinesfilter.cc +++ b/rtengine/pdaflinesfilter.cc @@ -27,11 +27,92 @@ namespace rtengine { extern const Settings *settings; +namespace { + +class PDAFGreenEqulibrateThreshold: public RawImageSource::GreenEqulibrateThreshold { + static constexpr float base_threshold = 0.5f; +public: + PDAFGreenEqulibrateThreshold(int w, int h, int ntiles=20): + RawImageSource::GreenEqulibrateThreshold(base_threshold), + w_(w), + h_(h) + { + tw_ = (w_ + 1) / ntiles; + th_ = (h_ + 1) / ntiles; + area_ = tw_ * th_; + tiles_.resize(ntiles+1, std::vector(ntiles+1)); + } + + void increment(int row, int col) + { + auto &r = tiles_[row / th_]; + ++r[col / tw_]; + } + + float operator()(int row, int col) const + { + int y = row / th_; + int x = col / tw_; + + float f = tile_factor(y, x); + int cy = y * th_ + th_/2; + int cx = x * tw_ + tw_/2; + + if (std::abs(y - cy) > std::abs(x - cx)) { + int y1 = y > cy ? y+1 : y-1; + if (y1 >= 0 && size_t(y1) < tiles_.size()) { + float f2 = tile_factor(y1, x); + int d = std::abs(cy - row); + f = f * float(th_ - d)/float(th_) + f2 * float(d)/float(th_); + } + } else { + int x1 = x > cx ? x+1 : x-1; + if (x1 >= 0 && size_t(x1) < tiles_[y].size()) { + float f2 = tile_factor(y, x1); + int d = std::abs(cx - col); + f = f * float(tw_ - d)/float(tw_) + f2 * float(d)/float(tw_); + } + } + return thresh_ * f; + } + + void print() const + { + std::cout << "PDAFGreenEqulibrateThreshold:\n"; + for (size_t row = 0; row < tiles_.size(); ++row) { + for (size_t col = 0; col < tiles_.size(); ++col) { + std::cout << " " << tile_factor(row, col); + } + std::cout << std::endl; + } + } + +private: + float tile_factor(int y, int x) const + { + return float(tiles_[y][x] * 12) / area_; + } + + int w_; + int h_; + int ntiles_; + int tw_; + int th_; + float area_; + std::vector> tiles_; +}; + +} // namespace + + + PDAFLinesFilter::PDAFLinesFilter(RawImage *ri): ri_(ri), W_(ri->get_width()), H_(ri->get_height()) { + gthresh_ = new PDAFGreenEqulibrateThreshold(W_, H_); + if (ri_->get_maker() == "Sony") { if (ri_->get_model() == "ILCE-7M3") { // A7III, from https://www.dpreview.com/forums/post/60843139 @@ -64,6 +145,18 @@ PDAFLinesFilter::PDAFLinesFilter(RawImage *ri): } +PDAFLinesFilter::~PDAFLinesFilter() +{ + delete gthresh_; +} + + +RawImageSource::GreenEqulibrateThreshold &PDAFLinesFilter::greenEqThreshold() +{ + return *gthresh_; +} + + int PDAFLinesFilter::markLine(array2D &rawData, PixelsMap &bpMap, int y) { rowmap_.clear(); @@ -91,13 +184,18 @@ int PDAFLinesFilter::markLine(array2D &rawData, PixelsMap &bpMap, int y) } } + PDAFGreenEqulibrateThreshold *m = static_cast(gthresh_); + for (int x = 2; x < W_-2; ++x) { if (ri_->FC(y, x) == 1) { const int i = x/2; if (rowmap_[i-1] && rowmap_[i] && rowmap_[i+1]) { for (int xx = x-2; xx <= x+2; ++xx) { - bpMap.set(xx, y); - ++marked; + if (!bpMap.get(xx, y)) { + bpMap.set(xx, y); + m->increment(y, xx); + ++marked; + } } } } @@ -138,6 +236,11 @@ int PDAFLinesFilter::mark(array2D &rawData, PixelsMap &bpMap) } } } + + if (settings->verbose) { + static_cast(gthresh_)->print(); + } + return found; } diff --git a/rtengine/pdaflinesfilter.h b/rtengine/pdaflinesfilter.h index 13b97812f..312367be7 100644 --- a/rtengine/pdaflinesfilter.h +++ b/rtengine/pdaflinesfilter.h @@ -28,17 +28,21 @@ namespace rtengine { class PDAFLinesFilter { public: PDAFLinesFilter(RawImage *ri); + ~PDAFLinesFilter(); + int mark(array2D &rawData, PixelsMap &bpMap); + RawImageSource::GreenEqulibrateThreshold &greenEqThreshold(); private: int markLine(array2D &rawData, PixelsMap &bpMap, int y); - + RawImage *ri_; int W_; int H_; std::vector pattern_; int offset_; std::vector rowmap_; + RawImageSource::GreenEqulibrateThreshold *gthresh_; }; } // namespace rtengine diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 893a4a30d..bd9af122e 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1933,6 +1933,15 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le if (settings->verbose && n > 0) { printf("Marked %d hot pixels from PDAF lines\n", n); } + + auto &thresh = f.greenEqThreshold(); + if (numFrames == 4) { + for (int i = 0; i < 4; ++i) { + green_equilibrate(thresh, *rawDataFrames[i]); + } + } else { + green_equilibrate(thresh, rawData); + } } // check if it is an olympus E camera or green equilibration is enabled. If yes, compute G channel pre-compensation factors @@ -1953,12 +1962,14 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le plistener->setProgress (0.0); } + GreenEqulibrateThreshold thresh(0.01 * raw.bayersensor.greenthresh); + if(numFrames == 4) { for(int i = 0; i < 4; ++i) { - green_equilibrate(0.01 * raw.bayersensor.greenthresh, *rawDataFrames[i]); + green_equilibrate(thresh, *rawDataFrames[i]); } } else { - green_equilibrate(0.01 * raw.bayersensor.greenthresh, rawData); + green_equilibrate(thresh, rawData); } } diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index b9ab7a154..ae0d38dc1 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -213,6 +213,15 @@ public: } int getFrameCount() {return numFrames;} + class GreenEqulibrateThreshold { + public: + explicit GreenEqulibrateThreshold(float thresh): thresh_(thresh) {} + virtual ~GreenEqulibrateThreshold() {} + virtual float operator()(int row, int column) const { return thresh_; } + protected: + const float thresh_; + }; + protected: typedef unsigned short ushort; void processFalseColorCorrection (Imagefloat* i, const int steps); @@ -237,7 +246,7 @@ protected: void cfa_linedn (float linenoiselevel, bool horizontal, bool vertical);//Emil's line denoise void green_equilibrate_global (array2D &rawData); - void green_equilibrate (float greenthresh, array2D &rawData);//Emil's green equilibration + void green_equilibrate (const GreenEqulibrateThreshold &greenthresh, array2D &rawData);//Emil's green equilibration void nodemosaic(bool bw); void eahd_demosaic();