added automatic adaptive green equilibration to the PDAF lines filter
This commit is contained in:
@@ -89,7 +89,7 @@ void RawImageSource::green_equilibrate_global(array2D<float> &rawData)
|
||||
}
|
||||
|
||||
//void green_equilibrate()//for dcraw implementation
|
||||
void RawImageSource::green_equilibrate(float thresh, array2D<float> &rawData)
|
||||
void RawImageSource::green_equilibrate(const GreenEqulibrateThreshold &thresh, array2D<float> &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<float> &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<float> &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<float> &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<float> &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<float> &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<float> &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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<int>(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<std::vector<int>> 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<float> &rawData, PixelsMap &bpMap, int y)
|
||||
{
|
||||
rowmap_.clear();
|
||||
@@ -91,13 +184,18 @@ int PDAFLinesFilter::markLine(array2D<float> &rawData, PixelsMap &bpMap, int y)
|
||||
}
|
||||
}
|
||||
|
||||
PDAFGreenEqulibrateThreshold *m = static_cast<PDAFGreenEqulibrateThreshold *>(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<float> &rawData, PixelsMap &bpMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (settings->verbose) {
|
||||
static_cast<PDAFGreenEqulibrateThreshold *>(gthresh_)->print();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,17 +28,21 @@ namespace rtengine {
|
||||
class PDAFLinesFilter {
|
||||
public:
|
||||
PDAFLinesFilter(RawImage *ri);
|
||||
~PDAFLinesFilter();
|
||||
|
||||
int mark(array2D<float> &rawData, PixelsMap &bpMap);
|
||||
RawImageSource::GreenEqulibrateThreshold &greenEqThreshold();
|
||||
|
||||
private:
|
||||
int markLine(array2D<float> &rawData, PixelsMap &bpMap, int y);
|
||||
|
||||
|
||||
RawImage *ri_;
|
||||
int W_;
|
||||
int H_;
|
||||
std::vector<int> pattern_;
|
||||
int offset_;
|
||||
std::vector<bool> rowmap_;
|
||||
RawImageSource::GreenEqulibrateThreshold *gthresh_;
|
||||
};
|
||||
|
||||
} // namespace rtengine
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<float> &rawData);
|
||||
void green_equilibrate (float greenthresh, array2D<float> &rawData);//Emil's green equilibration
|
||||
void green_equilibrate (const GreenEqulibrateThreshold &greenthresh, array2D<float> &rawData);//Emil's green equilibration
|
||||
|
||||
void nodemosaic(bool bw);
|
||||
void eahd_demosaic();
|
||||
|
||||
Reference in New Issue
Block a user