//////////////////////////////////////////////////////////////// // // AMaZE demosaic algorithm // (Aliasing Minimization and Zipper Elimination) // // copyright (c) 2008-2010 Emil Martinec // // incorporating ideas of Luis Sanz Rodrigues and Paul Lee // // code dated: May 27, 2010 // // amaze_interpolate_RT.cc is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //////////////////////////////////////////////////////////////// void RawImageSource::amaze_demosaic_RT() { #define SQR(x) ((x)*(x)) //#define MIN(a,b) ((a) < (b) ? (a) : (b)) //#define MAX(a,b) ((a) > (b) ? (a) : (b)) #define LIM(x,min,max) MAX(min,MIN(x,max)) #define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) //#define CLIP(x) LIM(x,0,65535) //allocate outpute arrays int width=W, height=H; red = new unsigned short*[H]; for (int i=0; isetProgressStr ("AMaZE Demosaicing..."); plistener->setProgress (0.0); } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //determine GRBG coset; (ey,ex) is the offset of the R subarray if (FC(0,0)==1) {//first pixel is G if (FC(0,1)==0) {ey=0; ex=1;} else {ey=1; ex=0;} } else {//first pixel is R or B if (FC(0,0)==0) {ey=0; ex=0;} else {ey=1; ex=1;} } // Main algorithm: Tile loop //#pragma omp parallel for shared(ri->data,height,width,red,green,blue) private(top,left) schedule(dynamic) //code is openmp ready; just have to pull local tile variable declarations inside the tile loop for (top=-16; top < height; top += TS-32) for (left=-16; left < width; left += TS-32) { //location of tile bottom edge int bottom = MIN( top+TS,height+16); //location of tile right edge int right = MIN(left+TS, width+16); //tile width (=TS except for right edge of image) int rr1 = bottom - top; //tile height (=TS except for bottom edge of image) int cc1 = right - left; //tile vars //counters for pixel location in the image int row, col; //min and max row/column in the tile int rrmin, rrmax, ccmin, ccmax; //counters for pixel location within the tile int rr, cc; //color index 0=R, 1=G, 2=B int c; //pointer counters within the tile int indx, indx1; //direction counter for nbrs[] int dir; //dummy indices int i, j; // +1 or -1 int sgn; //color ratios in up/down/left/right directions float cru, crd, crl, crr; //adaptive weights for vertical/horizontal/plus/minus directions float vwt, hwt, pwt, mwt; //vertical and horizontal G interpolations float Gintv, Ginth; //G interpolated in vert/hor directions using adaptive ratios float guar, gdar, glar, grar; //G interpolated in vert/hor directions using Hamilton-Adams method float guha, gdha, glha, grha; //interpolated G from fusing left/right or up/down float Ginthar, Ginthha, Gintvar, Gintvha; //color difference (G-R or G-B) variance in up/down/left/right directions float Dgrbvvaru, Dgrbvvard, Dgrbhvarl, Dgrbhvarr; //gradients in various directions float gradp, gradm, gradv, gradh, gradpm, gradhv; //color difference variances in vertical and horizontal directions float vcdvar, hcdvar, vcdvar1, hcdvar1, hcdaltvar, vcdaltvar; //adaptive interpolation weight using variance of color differences float varwt; //adaptive interpolation weight using difference of left-right and up-down G interpolations float diffwt; //alternative adaptive weight for combining horizontal/vertical interpolations float hvwtalt; //temporary variables for combining interpolation weights at R and B sites float vo, ve; //interpolation of G in four directions float gu, gd, gl, gr; //variance of G in vertical/horizontal directions float gvarh, gvarv; //Nyquist texture test float nyqtest; //accumulators for Nyquist texture interpolation float sumh, sumv, sumsqh, sumsqv, areawt; //color ratios in diagonal directions float crse, crnw, crne, crsw; //color differences in diagonal directions float rbse, rbnw, rbne, rbsw; //adaptive weights for combining diagonal interpolations float wtse, wtnw, wtsw, wtne; //alternate weight for combining diagonal interpolations float pmwtalt; //variance of R-B in plus/minus directions float rbvarp, rbvarm; // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /* char *buffer; // TS*TS*168 float (*rgb)[3]; // TS*TS*12 float (*delh); // TS*TS*4 float (*delv); // TS*TS*4 float (*delhsq); // TS*TS*4 float (*delvsq); // TS*TS*4 float (*dirwts)[2]; // TS*TS*8 float (*vcd); // TS*TS*4 float (*hcd); // TS*TS*4 float (*vcdalt); // TS*TS*4 float (*hcdalt); // TS*TS*4 float (*vcdsq); // TS*TS*4 float (*hcdsq); // TS*TS*4 float (*cddiffsq); // TS*TS*4 float (*hvwt); // TS*TS*4 float (*Dgrb)[2]; // TS*TS*8 float (*delp); // TS*TS*4 float (*delm); // TS*TS*4 float (*rbint); // TS*TS*4 float (*Dgrbh2); // TS*TS*4 float (*Dgrbv2); // TS*TS*4 float (*dgintv); // TS*TS*4 float (*dginth); // TS*TS*4 float (*Dgrbp1); // TS*TS*4 float (*Dgrbm1); // TS*TS*4 float (*Dgrbpsq1); // TS*TS*4 float (*Dgrbmsq1); // TS*TS*4 float (*cfa); // TS*TS*4 float (*pmwt); // TS*TS*4 float (*rbp); // TS*TS*4 float (*rbm); // TS*TS*4 int (*nyquist); // TS*TS*4 // assign working space buffer = (char *) malloc(35*sizeof(float)*TS*TS); //merror(buffer,"amaze_interpolate()"); memset(buffer,0,35*sizeof(float)*TS*TS); // rgb array rgb = (float (*)[3]) buffer; //pointers to array delh = (float (*)) (buffer + 3*sizeof(float)*TS*TS); delv = (float (*)) (buffer + 4*sizeof(float)*TS*TS); delhsq = (float (*)) (buffer + 5*sizeof(float)*TS*TS); delvsq = (float (*)) (buffer + 6*sizeof(float)*TS*TS); dirwts = (float (*)[2]) (buffer + 7*sizeof(float)*TS*TS); vcd = (float (*)) (buffer + 9*sizeof(float)*TS*TS); hcd = (float (*)) (buffer + 10*sizeof(float)*TS*TS); vcdalt = (float (*)) (buffer + 11*sizeof(float)*TS*TS); hcdalt = (float (*)) (buffer + 12*sizeof(float)*TS*TS); vcdsq = (float (*)) (buffer + 13*sizeof(float)*TS*TS); hcdsq = (float (*)) (buffer + 14*sizeof(float)*TS*TS); cddiffsq = (float (*)) (buffer + 15*sizeof(float)*TS*TS); hvwt = (float (*)) (buffer + 16*sizeof(float)*TS*TS); Dgrb = (float (*)[2]) (buffer + 17*sizeof(float)*TS*TS); delp = (float (*)) (buffer + 19*sizeof(float)*TS*TS); delm = (float (*)) (buffer + 20*sizeof(float)*TS*TS); rbint = (float (*)) (buffer + 21*sizeof(float)*TS*TS); Dgrbh2 = (float (*)) (buffer + 22*sizeof(float)*TS*TS); Dgrbv2 = (float (*)) (buffer + 23*sizeof(float)*TS*TS); dgintv = (float (*)) (buffer + 24*sizeof(float)*TS*TS); dginth = (float (*)) (buffer + 25*sizeof(float)*TS*TS); Dgrbp1 = (float (*)) (buffer + 26*sizeof(float)*TS*TS); Dgrbm1 = (float (*)) (buffer + 27*sizeof(float)*TS*TS); Dgrbpsq1 = (float (*)) (buffer + 28*sizeof(float)*TS*TS); Dgrbmsq1 = (float (*)) (buffer + 29*sizeof(float)*TS*TS); cfa = (float (*)) (buffer + 30*sizeof(float)*TS*TS); pmwt = (float (*)) (buffer + 31*sizeof(float)*TS*TS); rbp = (float (*)) (buffer + 32*sizeof(float)*TS*TS); rbm = (float (*)) (buffer + 33*sizeof(float)*TS*TS); nyquist = (int (*)) (buffer + 34*sizeof(float)*TS*TS); */ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // rgb from input CFA data // rgb values should be floating point number between 0 and 1 // after white balance multipliers are applied // a 16 pixel border is added to each side of the image // bookkeeping for borders if (top<0) {rrmin=16;} else {rrmin=0;} if (left<0) {ccmin=16;} else {ccmin=0;} if (bottom>height) {rrmax=height-top;} else {rrmax=rr1;} if (right>width) {ccmax=width-left;} else {ccmax=cc1;} for (rr=rrmin; rr < rrmax; rr++) for (row=rr+top, cc=ccmin; cc < ccmax; cc++) { col = cc+left; c = FC(rr,cc); indx=row*width+col; indx1=rr*TS+cc; rgb[indx1][c] = (ri->data[row][col])/65535.0f; //rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation cfa[indx1] = rgb[indx1][c]; } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //fill borders if (rrmin>0) { for (rr=0; rr<16; rr++) for (cc=ccmin; ccdata[(height-rr-2)][left+cc])/65535.0f; //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+left+cc][c])/65535.0f;//for dcraw implementation cfa[(rrmax+rr)*TS+cc] = rgb[(rrmax+rr)*TS+cc][c]; } } if (ccmin>0) { for (rr=rrmin; rrdata[(top+rr)][(width-cc-2)])/65535.0f; //rgb[rr*TS+ccmax+cc][c] = (image[(top+rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation cfa[rr*TS+ccmax+cc] = rgb[rr*TS+ccmax+cc][c]; } } //also, fill the image corners if (rrmin>0 && ccmin>0) { for (rr=0; rr<16; rr++) for (cc=0; cc<16; cc++) { c=FC(rr,cc); rgb[(rr)*TS+cc][c] = (ri->data[32-rr][32-cc])/65535.0f; //rgb[(rr)*TS+cc][c] = (rgb[(32-rr)*TS+(32-cc)][c]);//for dcraw implementation cfa[(rr)*TS+cc] = rgb[(rr)*TS+cc][c]; } } if (rrmaxdata[(height-rr-2)][(width-cc-2)])/65535.0f; //rgb[(rrmax+rr)*TS+ccmax+cc][c] = (image[(height-rr-2)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation cfa[(rrmax+rr)*TS+ccmax+cc] = rgb[(rrmax+rr)*TS+ccmax+cc][c]; } } if (rrmin>0 && ccmaxdata[(32-rr)][(width-cc-2)])/65535.0f; //rgb[(rr)*TS+ccmax+cc][c] = (image[(32-rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation cfa[(rr)*TS+ccmax+cc] = rgb[(rr)*TS+ccmax+cc][c]; } } if (rrmax0) { for (rr=0; rr<16; rr++) for (cc=0; cc<16; cc++) { c=FC(rr,cc); rgb[(rrmax+rr)*TS+cc][c] = (ri->data[(height-rr-2)][(32-cc)])/65535.0f; //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+(32-cc)][c])/65535.0f;//for dcraw implementation cfa[(rrmax+rr)*TS+cc] = rgb[(rrmax+rr)*TS+cc][c]; } } //end of border fill // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% for (rr=1; rr < rr1-1; rr++) for (cc=1, indx=(rr)*TS+cc; cc < cc1-1; cc++, indx++) { delh[indx] = fabs(cfa[indx+1]-cfa[indx-1]); delv[indx] = fabs(cfa[indx+v1]-cfa[indx-v1]); delhsq[indx] = SQR(delh[indx]); delvsq[indx] = SQR(delv[indx]); delp[indx] = fabs(cfa[indx+p1]-cfa[indx-p1]); delm[indx] = fabs(cfa[indx+m1]-cfa[indx-m1]); } for (rr=2; rr < rr1-2; rr++) for (cc=2,indx=(rr)*TS+cc; cc < cc1-2; cc++, indx++) { dirwts[indx][0] = eps+delv[indx+v1]+delv[indx-v1]+delv[indx];//+fabs(cfa[indx+v2]-cfa[indx-v2]); //vert directional averaging weights dirwts[indx][1] = eps+delh[indx+1]+delh[indx-1]+delh[indx];//+fabs(cfa[indx+2]-cfa[indx-2]); //horizontal weights if (FC(rr,cc)&1) { //for later use in diagonal interpolation //Dgrbp1[indx]=2*cfa[indx]-(cfa[indx-p1]+cfa[indx+p1]); //Dgrbm1[indx]=2*cfa[indx]-(cfa[indx-m1]+cfa[indx+m1]); Dgrbpsq1[indx]=(SQR(cfa[indx]-cfa[indx-p1])+SQR(cfa[indx]-cfa[indx+p1])); Dgrbmsq1[indx]=(SQR(cfa[indx]-cfa[indx-m1])+SQR(cfa[indx]-cfa[indx+m1])); } } //t2_init += clock()-t1_init; // end of tile initialization // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //interpolate vertical and horizontal color differences //t1_vcdhcd = clock(); for (rr=4; rr0) { if (3*hcd[indx] > (Ginth+cfa[indx])) { hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx]; } else { hwt = 1-3*hcd[indx]/(eps+Ginth+cfa[indx]); hcd[indx]=hwt*hcd[indx] + (1-hwt)*(-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx]); } } if (vcd[indx]>0) { if (3*vcd[indx] > (Gintv+cfa[indx])) { vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; } else { vwt = 1-3*vcd[indx]/(eps+Gintv+cfa[indx]); vcd[indx]=vwt*vcd[indx] + (1-vwt)*(-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]); } } if (Ginth > 1) hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx];//for RT implementation if (Gintv > 1) vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; //if (Ginth > pre_mul[c]) hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx];//for dcraw implementation //if (Gintv > pre_mul[c]) vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; } else { Ginth = hcd[indx]+cfa[indx];//interpolated G Gintv = vcd[indx]+cfa[indx]; if (hcd[indx]<0) { if (3*hcd[indx] < -(Ginth+cfa[indx])) { hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx]; } else { hwt = 1+3*hcd[indx]/(eps+Ginth+cfa[indx]); hcd[indx]=hwt*hcd[indx] + (1-hwt)*(ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx]); } } if (vcd[indx]<0) { if (3*vcd[indx] < -(Gintv+cfa[indx])) { vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; } else { vwt = 1+3*vcd[indx]/(eps+Gintv+cfa[indx]); vcd[indx]=vwt*vcd[indx] + (1-vwt)*(ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]); } } if (Ginth > 1) hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx];//for RT implementation if (Gintv > 1) vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; //if (Ginth > pre_mul[c]) hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx];//for dcraw implementation //if (Gintv > pre_mul[c]) vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; } vcdsq[indx] = SQR(vcd[indx]); hcdsq[indx] = SQR(hcd[indx]); cddiffsq[indx] = SQR(vcd[indx]-hcd[indx]); } for (rr=6; rr0 && fabs(0.5-diffwt)0) {nyquist[indx]=1;}//nyquist=1 for nyquist region } for (rr=8; rr4) nyquist[indx]=1; //or not if (areawt<4) nyquist[indx]=0; } //t2_nyqtest += clock() - t1_nyqtest; // end of Nyquist test // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // in areas of Nyquist texture, do area interpolation //t1_areainterp = clock(); for (rr=8; rr0.75) hvwt[indx]=1.0; Dgrb[indx][0] = (hcd[indx]*(1-hvwt[indx]) + vcd[indx]*hvwt[indx]);//evaluate color differences rgb[indx][1] = cfa[indx] + Dgrb[indx][0];//evaluate G (finally!) //local curvature in G (preparation for nyquist refinement step) if (nyquist[indx]) { Dgrbh2[indx] = SQR(rgb[indx][1] - 0.5*(rgb[indx-1][1]+rgb[indx+1][1])); Dgrbv2[indx] = SQR(rgb[indx][1] - 0.5*(rgb[indx-v1][1]+rgb[indx+v1][1])); } } //end of standard interpolation // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // refine Nyquist areas using G curvatures for (rr=8; rr 1) rbp[indx]=ULIM(rbp[indx],cfa[indx-p1],cfa[indx+p1]);//for RT implementation if (rbm[indx] > 1) rbm[indx]=ULIM(rbm[indx],cfa[indx-m1],cfa[indx+m1]); //c=FC(rr,cc);//for dcraw implementation //if (rbp[indx] > pre_mul[c]) rbp[indx]=ULIM(rbp[indx],cfa[indx-p1],cfa[indx+p1]); //if (rbm[indx] > pre_mul[c]) rbm[indx]=ULIM(rbm[indx],cfa[indx-m1],cfa[indx+m1]); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //rbint[indx] = 0.5*(cfa[indx] + (rbp*rbvarm+rbm*rbvarp)/(rbvarp+rbvarm));//this is R+B, interpolated } for (rr=10; rr 1) Ginth=ULIM(Ginth,cfa[indx-1],cfa[indx+1]);//for RT implementation if (Gintv > 1) Gintv=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1]); //c=FC(rr,cc);//for dcraw implementation //if (Ginth > pre_mul[c]) Ginth=ULIM(Ginth,cfa[indx-1],cfa[indx+1]); //if (Gintv > pre_mul[c]) Gintv=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1]); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% rgb[indx][1] = Ginth*(1-hvwt[indx]) + Gintv*hvwt[indx]; //rgb[indx][1] = 0.5*(rgb[indx][1]+0.25*(rgb[indx-v1][1]+rgb[indx+v1][1]+rgb[indx-1][1]+rgb[indx+1][1])); Dgrb[indx][0] = rgb[indx][1]-cfa[indx]; //rgb[indx][2-FC(rr,cc)]=2*rbint[indx]-cfa[indx]; } //end of diagonal interpolation correction //t2_diag += clock() - t1_diag; // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //t1_chroma = clock(); //fancy chrominance interpolation //(ey,ex) is location of R site for (rr=13-ey; rrsetProgress(fabs((float)top/height)); } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // clean up free(buffer); // done #undef TS }