Skip to content

Commit

Permalink
Add new demosaicing
Browse files Browse the repository at this point in the history
  • Loading branch information
eszdman committed Jul 12, 2024
1 parent a108ede commit 5b3fdaf
Show file tree
Hide file tree
Showing 9 changed files with 754 additions and 6 deletions.
127 changes: 127 additions & 0 deletions app/src/main/assets/shaders/demosaicp12b.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
precision highp float;
precision mediump sampler2D;
uniform sampler2D RawBuffer;
uniform sampler2D GradBuffer;
#define QUAD 0
#define demosw (1.0/10000.0)
#define EPS (0.01)
#define size1 (1.2)
#define MSIZE1 3
#define KSIZE ((MSIZE1-1)/2)
#define GRADSIZE 1.5
#define FUSEMIN 0.0
#define FUSEMAX 1.0
#define FUSESHIFT -0.1
#define FUSEMPY 1.4
#define NOISEO 0.0
#define NOISES 0.0
#define PI 3.1415926535897932384626433832795
out float Output;

// Helper function to get Bayer sample
float getBayerSample(ivec2 pos) {
return texelFetch(RawBuffer, pos, 0).r;
}

float normpdf(in float x, in float sigma){return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;}
void main() {
ivec2 xy = ivec2(gl_FragCoord.xy);
int fact1 = xy.x%2;
int fact2 = xy.y%2;
float outp = 0.0;
if(fact1+fact2 != 1){
float outp = 0.0;
float weight = 0.0;
float green[4];
green[0] = getBayerSample(ivec2(xy+ivec2(0, -1))) + (getBayerSample(xy) - getBayerSample(xy + ivec2(0,-2)))/2.0 + (getBayerSample(xy + ivec2(0,-3)) - 2.0 * getBayerSample(xy + ivec2(0,-1)) + getBayerSample(xy + ivec2(0,1)))/8.0;
green[1] = getBayerSample(ivec2(xy+ivec2(-1, 0))) + (getBayerSample(xy) - getBayerSample(xy + ivec2(-2,0)))/2.0 + (getBayerSample(xy + ivec2(-3,0)) - 2.0 * getBayerSample(xy + ivec2(-1,0)) + getBayerSample(xy + ivec2(1,0)))/8.0;
green[2] = getBayerSample(ivec2(xy+ivec2(1, 0))) + (getBayerSample(xy) - getBayerSample(xy + ivec2(2,0)))/2.0 + (getBayerSample(xy + ivec2(-1,0)) - 2.0 * getBayerSample(xy + ivec2(1,0)) + getBayerSample(xy + ivec2(3,0)))/8.0;
green[3] = getBayerSample(ivec2(xy+ivec2(0, 1))) + (getBayerSample(xy) - getBayerSample(xy + ivec2(0,2)))/2.0 + (getBayerSample(xy + ivec2(0,-1)) - 2.0 * getBayerSample(xy + ivec2(0,1)) + getBayerSample(xy + ivec2(0,3)))/8.0;
float grad[4];
vec2 initialGrad = texelFetch(GradBuffer, ivec2(xy), 0).rg;
grad[0] = initialGrad.g*initialGrad.g;
grad[1] = initialGrad.r*initialGrad.r;
grad[2] = initialGrad.r*initialGrad.r;
grad[3] = initialGrad.g*initialGrad.g;
for (int i =1;i<=2;i++){
if (i == 0) continue;
float t = texelFetch(GradBuffer, ivec2(xy+ivec2(0, -i)), 0).g;
grad[0] += t*t;
t = texelFetch(GradBuffer, ivec2(xy+ivec2(-i, 0)), 0).r;
grad[1] += t*t;
t = texelFetch(GradBuffer, ivec2(xy+ivec2(i, 0)), 0).r;
grad[2] += t*t;
t = texelFetch(GradBuffer, ivec2(xy+ivec2(0, i)), 0).g;
grad[3] += t*t;
}
grad[0] = 1.0/sqrt(grad[0]+demosw);
grad[1] = 1.0/sqrt(grad[1]+demosw);
grad[2] = 1.0/sqrt(grad[2]+demosw);
grad[3] = 1.0/sqrt(grad[3]+demosw);

vec2 HV = vec2(demosw);
float weights = 0.00001;
for (int j =-2;j<=2;j++)
{
float k0 = normpdf(float(j), GRADSIZE);
for (int i =-2;i<=2;i++){
if((i%2) + (j%2) != 1) continue;
float k = normpdf(float(i), GRADSIZE)*k0;
vec2 div = texelFetch(GradBuffer, ivec2(xy+ivec2(i, j)), 0).rg;
HV += div*k;
weights+=k;
}
}
float MIN = min(min(green[0],green[1]),min(green[2],green[3]));
float MAX = max(max(green[0],green[1]),max(green[2],green[3]));
float dmax = 1.0 - MAX;
float W;
if(dmax < MIN){
W = dmax/MAX;
} else {
W = MIN/MAX;
}
float avr = (green[0]+green[1]+green[2]+green[3])/4.0;
//float N = sqrt(avr*NOISES + NOISEO)/5.0;
//W=W*W;
//W=sqrt(W);
//float badGR = (abs(HV.r-HV.g)*5.0)/((HV.r+HV.g));
HV/=weights;
//if(abs(HV.r) > N || abs(HV.g) > N){
//float angle = atan(dxy.y,dxy.x)+PI;
vec2 dxy2 = vec2((HV.x+HV.y)/2.0,(HV.y-HV.x)/2.0);
float avrg = (green[0]*grad[0]+green[1]*grad[1]+green[2]*grad[2]+green[3]*grad[3])/(grad[0]+grad[1]+grad[2]+grad[3]);
grad[0] = 1.0/sqrt(HV.x*HV.x+abs(green[0]-avrg)+demosw);
grad[1] = 1.0/sqrt(HV.y*HV.y+abs(green[1]-avrg)+demosw);
grad[2] = 1.0/sqrt(HV.y*HV.y+abs(green[2]-avrg)+demosw);
grad[3] = 1.0/sqrt(HV.x*HV.x+abs(green[3]-avrg)+demosw);

//Output = (green[0]*grad[0] +green[1]*grad[1] + green[2]*grad[2]+ green[3]*grad[3])/(grad[0]+grad[1]+grad[2]+grad[3]);
float outp2 = 0.0;

if (HV.y > HV.x){
Output = (green[1]*grad[1] + green[2]*grad[2])/(grad[1]+grad[2]);
//Output = (green[1] + green[2])/(2.0);
} else {
Output = (green[0]*grad[0] + green[3]*grad[3])/(grad[0]+grad[3]);
//Output = (green[0] + green[3])/(2.0);
}
//Output = mix(outp2,Output,0.5 - 0.5*abs(HV.y-HV.x));
/*} else {
Output = avr;
}*/


W = mix(FUSEMIN,FUSEMAX,clamp((W+FUSESHIFT)*FUSEMPY,0.0,1.0));
//Output = mix(Output,(green[0]*grad[0] + green[1]*grad[1]+ green[2]*grad[2] + green[3]*grad[3])/(grad[0]+grad[1]+grad[2]+grad[3]),W);


/*} else {
Output = green[0]*grad[0] + green[1]*grad[1]+ green[2]*grad[2] + green[3]*grad[3];
Output/=grad[0]+grad[1]+grad[2]+grad[3];
}*/
}
else {
Output = float(texelFetch(RawBuffer, (xy), 0).x);
}
}
134 changes: 134 additions & 0 deletions app/src/main/assets/shaders/demosaicp12e.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
precision highp float;
precision highp sampler2D;
uniform sampler2D bayerTexture;
#define alpha 3.75
#define THRESHOLD 1.9
#define L 3
out vec3 Output;
uniform int yOffset;

// Helper function to get Bayer sample
float getBayerSample(ivec2 pos) {
return texelFetch(bayerTexture, pos, 0).r;
}

// Helper function to determine Bayer pattern at a given position
// 0: R, 1: G (at red row), 2: G (at blue row), 3: B
int getBayerPattern(ivec2 pos) {
int x = (pos.x) % 2;
int y = (pos.y) % 2;
return (y << 1) | x;
}

float dxy(ivec2 pos, int direction) {
int pattern = getBayerPattern(pos);
float useGreen = (pattern == 1 || pattern == 2) ? 1.0 : -1.0;
if (direction == 0) {
return abs((4.0 * getBayerSample(pos) - 3.0 * getBayerSample(pos + ivec2(1,0)) - 3.0 * getBayerSample(pos + ivec2(-1,0)) + getBayerSample(pos + ivec2(-2,0)) + getBayerSample(pos + ivec2(2,0)))/6.0);
//return (2.0 * getBayerSample(pos) - getBayerSample(pos + ivec2(1,0)) - getBayerSample(pos + ivec2(-1,0)))/2.0;
} else {
return abs((4.0 * getBayerSample(pos) - 3.0 * getBayerSample(pos + ivec2(0,1)) - 3.0 * getBayerSample(pos + ivec2(0,-1)) + getBayerSample(pos + ivec2(0,-2)) + getBayerSample(pos + ivec2(0,2)))/6.0);
//return (2.0 * getBayerSample(pos) - getBayerSample(pos + ivec2(0,1)) - getBayerSample(pos + ivec2(0,-1)))/2.0;
}
}

float dt(ivec2 pos, int direction) {
float c = dxy(pos, direction);
if (direction == 0) {
float c2 = dxy(pos + ivec2(2, 0), direction);
float c1 = dxy(pos + ivec2(1, 0), direction);
return (abs(c - c1) + abs(c1 - c2))/2.0;
} else {
float c2 = dxy(pos + ivec2(0, 2), direction);
float c1 = dxy(pos + ivec2(0, 1), direction);
return (abs(c - c1) + abs(c1 - c2))/2.0;
}
}

float dxy2(ivec2 pos, int direction) {
float c = getBayerSample(pos);
float c1;
float c2;
float c3;
if (direction == 0){
c1 = getBayerSample(pos + ivec2(2,0));
c2 = getBayerSample(pos + ivec2(-1,0));
c3 = getBayerSample(pos + ivec2(1,0));
} else {
c1 = getBayerSample(pos + ivec2(0,2));
c2 = getBayerSample(pos + ivec2(0,-1));
c3 = getBayerSample(pos + ivec2(0,1));
}
return (abs(c - c1) + abs(c2 - c3)) / 2.0 + alpha * dt(pos,direction);
}

float IG(ivec2 pos, int direction) {
int pattern = getBayerPattern(pos);
float useGreen = (pattern == 1 || pattern == 2) ? -1.0 : 1.0;
float useInv = 1.0 - useGreen;
if (direction == 0) {
return 2.0 * dxy2(pos,0) + dxy2(pos + ivec2(0,-1),0) + dxy2(pos + ivec2(0,1),0);
} else {
return 2.0 * dxy2(pos,1) + dxy2(pos + ivec2(-1,0),1) + dxy2(pos + ivec2(1,0),1);
}
}


// Green plane interpolation
vec3 interpolateGreen(ivec2 pos) {
int pattern = getBayerPattern(pos);
if (pattern == 1 || pattern == 2) return vec3(getBayerSample(pos),0.0,0.0); // Already green

float igE = IG(pos,1);
float igS = IG(pos,0);
float igW = IG(pos + ivec2(2,0),1);
float igN = IG(pos + ivec2(0,2),0);

float wE = 1.0 / (igE + 0.0001);
float wS = 1.0 / (igS + 0.0001);
float wW = 1.0 / (igW + 0.0001);
float wN = 1.0 / (igN + 0.0001);
// Pass 1
float gE = getBayerSample(pos + ivec2(0,1)) + (getBayerSample(pos) - getBayerSample(pos + ivec2(0,2)))/2.0 + (getBayerSample(pos + ivec2(0,-1)) - 2.0 * getBayerSample(pos + ivec2(0,1)) + getBayerSample(pos + ivec2(0,3)))/8.0;
float gW = getBayerSample(pos + ivec2(0,-1)) + (getBayerSample(pos) - getBayerSample(pos + ivec2(0,-2)))/2.0 + (getBayerSample(pos + ivec2(0,-3)) - 2.0 * getBayerSample(pos + ivec2(0,-1)) + getBayerSample(pos + ivec2(0,1)))/8.0;
float gN = getBayerSample(pos + ivec2(-1,0)) + (getBayerSample(pos) - getBayerSample(pos + ivec2(-2,0)))/2.0 + (getBayerSample(pos + ivec2(-3,0)) - 2.0 * getBayerSample(pos + ivec2(-1,0)) + getBayerSample(pos + ivec2(1,0)))/8.0;
float gS = getBayerSample(pos + ivec2(1,0)) + (getBayerSample(pos) - getBayerSample(pos + ivec2(2,0)))/2.0 + (getBayerSample(pos + ivec2(-1,0)) - 2.0 * getBayerSample(pos + ivec2(1,0)) + getBayerSample(pos + ivec2(3,0)))/8.0;

float gh = (gE * wE + gW * wW)/(wE + wW + 0.0001);
float gv = (gN * wN + gS * wS)/(wN + wS + 0.0001);
float gd = (gE * wE + gW * wW + gN * wN + gS * wS)/(wE + wW + wN + wS + 0.0001);

float dh = igE + igW;
float dv = igN + igS;

float E = max(dh/dv, dv/dh);

if (E < THRESHOLD) {
return vec3(-1.0, gh, gv);
} else {
if (dh > dv) {
return vec3(gv, gh, gv);
} else {
return vec3(gh, gh, gv);
}
}
/*if (dh > dv) {
return vec3(gv, gh, gv);
//return vec3(gv, gh, gv);
} else {
return vec3(gh, gh, gv);
//return vec3(gh, gh, gv);
}*/

return vec3(0.0);
}


void main() {
ivec2 pos = ivec2(gl_FragCoord.xy);
pos+=ivec2(0,yOffset);

// Step 1: Green plane interpolation
vec3 initialGreen = interpolateGreen(pos);
Output = initialGreen;
}
Loading

0 comments on commit 5b3fdaf

Please sign in to comment.