//get the image by homography for a destination pixel x, y float destination_pixel(float inv[9], float *im, int w, int h, int x, int y) { float p[3] = {x, y, 1}; float p1[3]; p1[0] = p[0]*inv[0] + p[1]*inv[1] + p[2]*inv[2]; p1[1] = p[0]*inv[3] + p[1]*inv[4] + p[2]*inv[5]; p1[2] = p[0]*inv[6] + p[1]*inv[7] + p[2]*inv[8]; return bicubic_interpolation(im, w, h, p1[0]/p1[2], p1[1]/p1[2]); }
void apply_transformation(float *im, float *Tx, float *Ty, int w, int h, float *out) { for(int i = 0 ; i < w ; i++) for(int j = 0 ; j < h ; j++) { float dx = Tx[j*w+i]; float dy = Ty[j*w+i]; out[j*w+i] = bicubic_interpolation(im, w, h, dx, dy); } }
void mnehs_affine_warp(float *warp, float *h, int wh, int hh, int pd, float *a, int wa, int ha, float *b, int wb, int hb, double PA[8], double PB[8]) { for (int j = 0; j < hh; j++) for (int i = 0; i < wh; i++) { float vh = getsample_nan(h, wh, hh, 1, i, j, 0); double ijh[3] = {i, j, vh}; double paijh[3], pbijh[3]; apply_projection(paijh, PA, ijh); apply_projection(pbijh, PB, ijh); float va[pd], vb[pd]; bicubic_interpolation(va, a, wa, ha, pd, paijh[0], paijh[1]); bicubic_interpolation(vb, b, wb, hb, pd, pbijh[0], pbijh[1]); for (int l = 0; l < pd; l++) warp[pd*(j*wh+i)+l] = va[l] - vb[l]; } }
// y := pull back of image x by vector field f static void field_pull_back(float *y, float *f, float *x, int w, int h, int pd) { float (*flow)[w][2] = (void*)f; float (*out)[w][pd] = (void*)y; for (int j = 0; j < h; j++) for (int i = 0; i < w; i++) { float p[2] = {i + flow[j][i][0], j + flow[j][i][1]}; bicubic_interpolation(out[j][i], x, w, h, pd, p[0], p[1]); } }
// v(x) := -u(x+v(x)) static void inversion_iteration(float *v, float *u, int w, int h) { float (*V)[w][2] = (void*)v; for (int j = 0; j < h; j++) for (int i = 0; i < w; i++) { float p[2]; float qx = i + V[j][i][0]; float qy = j + V[j][i][1]; bicubic_interpolation(p, u, w, h, 2, qx, qy); V[j][i][0] = -p[0]; V[j][i][1] = -p[1]; } }
// interpolate an image at a given sub-pixelic point static void general_interpolate(float *result, float *x, int w, int h, int pd, float p, float q, int m) // method { if (m == 3) { bicubic_interpolation(result, x, w, h, pd, p, q); } else { int ip = floor(p); int iq = floor(q); for (int l = 0; l < pd; l++) { float a = getsample_0(x, w, h, pd, ip , iq , l); float b = getsample_0(x, w, h, pd, ip , iq+1, l); float c = getsample_0(x, w, h, pd, ip+1, iq , l); float d = getsample_0(x, w, h, pd, ip+1, iq+1, l); float v = interpolate_cell(a, b, c, d, p-ip, q-iq, m); result[l] = v; } } }
void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, int components, float u, float v) { bicubic_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); }
void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, int components, float u, float v) { bicubic_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); }
/* only supports RGBA nodes now */ static void node_composit_exec_rotate(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { if(out[0]->hasoutput==0) return; if(in[0]->data) { CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* note, this returns zero'd image */ float rad, u, v, s, c, centx, centy, miny, maxy, minx, maxx; int x, y, yo, xo; ImBuf *ibuf, *obuf; rad= (M_PI*in[1]->vec[0])/180.0f; s= sin(rad); c= cos(rad); centx= cbuf->x/2; centy= cbuf->y/2; minx= -centx; maxx= -centx + (float)cbuf->x; miny= -centy; maxy= -centy + (float)cbuf->y; ibuf=IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); obuf=IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0); if(ibuf && obuf){ ibuf->rect_float=cbuf->rect; obuf->rect_float=stackbuf->rect; for(y=miny; y<maxy; y++) { yo= y+(int)centy; for(x=minx; x<maxx;x++) { u=c*x + y*s + centx; v=-s*x + c*y + centy; xo= x+(int)centx; switch(node->custom1) { case 0: neareast_interpolation(ibuf, obuf, u, v, xo, yo); break ; case 1: bilinear_interpolation(ibuf, obuf, u, v, xo, yo); break; case 2: bicubic_interpolation(ibuf, obuf, u, v, xo, yo); break; } } } /* rotate offset vector too, but why negative rad, ehh?? Has to be replaced with [3][3] matrix once (ton) */ s= sin(-rad); c= cos(-rad); centx= (float)cbuf->xof; centy= (float)cbuf->yof; stackbuf->xof= (int)( c*centx + s*centy); stackbuf->yof= (int)(-s*centx + c*centy); IMB_freeImBuf(ibuf); IMB_freeImBuf(obuf); } /* pass on output and free */ out[0]->data= stackbuf; if(cbuf!=in[0]->data) { free_compbuf(cbuf); } } }
CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type) { CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); ImBuf *ibuf, *obuf; float mat[4][4], lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4]; float svec[3]= {scale, scale, scale}, loc[2]= {x, y}; unit_m4(rmat); unit_m4(lmat); unit_m4(smat); unit_m4(cmat); /* image center as rotation center */ cmat[3][0]= (float)cbuf->x/2.0f; cmat[3][1]= (float)cbuf->y/2.0f; invert_m4_m4(icmat, cmat); size_to_mat4(smat, svec); /* scale matrix */ add_v2_v2(lmat[3], loc); /* tranlation matrix */ rotate_m4(rmat, 'Z', angle); /* rotation matrix */ /* compose transformation matrix */ mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL); invert_m4(mat); ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); obuf= IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0); if (ibuf && obuf) { int i, j; ibuf->rect_float= cbuf->rect; obuf->rect_float= stackbuf->rect; for (j=0; j<cbuf->y; j++) { for (i=0; i<cbuf->x;i++) { float vec[3]= {i, j, 0}; mul_v3_m4v3(vec, mat, vec); switch(filter_type) { case 0: neareast_interpolation(ibuf, obuf, vec[0], vec[1], i, j); break; case 1: bilinear_interpolation(ibuf, obuf, vec[0], vec[1], i, j); break; case 2: bicubic_interpolation(ibuf, obuf, vec[0], vec[1], i, j); break; } } } IMB_freeImBuf(ibuf); IMB_freeImBuf(obuf); } /* pass on output and free */ return stackbuf; }
void rhf_multiscale(int iDWin, // Half size of patch int iDBloc, // Half size of research window float fDistance, // Max-Distance parameter int knn, // Minimum Number of Neighbors int iNscales, // Number of Scales float **fhI, // Histogram float **fpI, // Input float **fpO, // Output int iChannels, // Number of channels int iWidth, // Image width int iHeight, // Image height int iBins) // Number of bins Histogram image { //0 Scales: 1x1 //1 Scales: 1x1, 2x2 //2 Scales: 1x1, 2x2, 4x4 //3 Scales: 1x1, 2x2, 4x4, 16x16 //Need a buffer.... float **fpOs_old = (float**) malloc(sizeof(float*)*iChannels); int nxSold,nySold; nxSold=nySold=-1; for (int ii=0; ii< iChannels;ii++) fpOs_old[ii] = (float*) malloc(sizeof(float)*iWidth * iHeight); double sigma_scale = SIGMASCALE; //Total number of samples in the whole image double dtotal = 0.0f; for(int ii=0;ii < iWidth*iHeight; ii++) { dtotal += fhI[iBins-1][ii]; } for(int s=iNscales-1; s>=0; s--) { // Generate Image and Histogram at desired scale float **fpIs;// = (float**) malloc(sizeof(float*)*iChannels); float **fpOs = (float**) malloc(sizeof(float*)*iChannels); float **fhIs;// = (float**) malloc(sizeof(float*)*iBins); int nxS, nyS, nyM, nxM, nxSS, nySS; double scale = pow(0.5f,s); if(s>0) //If it is not the last scale... { fhIs = gaussian_sampler(fhI, iWidth, iHeight, iBins, &nxS, &nyS, scale, sigma_scale); //Renormalize weights to keep total number of samples double dtotalS = 0; for(int ii=0;ii < nxS*nyS; ii++) { dtotalS += fhIs[iBins-1][ii]; } float samples_factor = (dtotal/dtotalS); for(int ii=0; ii < nxS*nyS; ii++) { for(int jj=0; jj< iBins; jj++) fhIs[jj][ii] = samples_factor*fhIs[jj][ii]; } fpIs = gaussian_sampler(fpI, iWidth, iHeight, iChannels, &nxS, &nyS, scale, sigma_scale); } else { fpIs = fpI; fhIs = fhI; nxS = iWidth; nyS = iHeight; } for (int ii=0; ii < iChannels; ii++) { fpOs[ii] = (float*) malloc(sizeof(float)*nxS*nyS); } //Filter Scale printf("-->Filtering Scale %d BEGIN\n",s); //In the scale 0 force a minimum number of neighbors int knnS = (s>0)?0:knn; if(knnS>0) { rhf_knn(iDWin, // Half size of patch iDBloc, // Half size of research window fDistance, // Max-Distance parameter knn, // Minimum number of neighbors fhIs, // Histogram fpIs, // Input fpOs, // Output iChannels, nxS, nyS, iBins); } else { rhf(iDWin, // Half size of patch iDBloc, // Half size of research window fDistance, // Max-Distance parameter fhIs, // Histogram fpIs, // Input fpOs, // Output iChannels, nxS, nyS, iBins); } printf("-->Filtering Scale %d END\n",s); if(s < iNscales - 1) //This is not the last Scale { float **fpOs_PosTerm; //= (float**) malloc(sizeof(float*)*iChannels); fpOs_PosTerm = bicubic_interpolation(fpOs_old, nxSold, nySold, iChannels, nxS, nyS); nxM = nxS; nyM = nyS; float **fpOs_NegTermD; //= (float**) malloc(sizeof(float*)*iChannels); float **fpOs_NegTerm; //= (float**) malloc(sizeof(float*)*iChannels); fpOs_NegTermD = gaussian_sampler(fpOs, nxS, nyS, iChannels, &nxM, &nyM, 0.5f, sigma_scale); fpOs_NegTerm = bicubic_interpolation(fpOs_NegTermD, nxM, nyM, iChannels, nxS, nyS); nxSS = nxS; nySS = nyS; nxS = MIN(nxS, nxSS); nyS = MIN(nyS, nySS); for(int ii=0; ii < iChannels; ii++) for(int x=0;x<nxS*nyS;x++) { fpOs[ii][x] += fpOs_PosTerm[ii][x] - fpOs_NegTerm[ii][x]; } //Cleaning for (int ii=0; ii < iChannels; ii++) { free(fpOs_NegTermD[ii]); free(fpOs_NegTerm[ii]); free(fpOs_PosTerm[ii]); } free(fpOs_NegTermD); free(fpOs_NegTerm); free(fpOs_PosTerm); } //Clean last fpOs_old and create the new one nxSold = nxS; nySold = nyS; for (int ii=0; ii < iChannels; ii++) { for(int x=0;x<nxS*nyS;x++) fpOs_old[ii][x] = fpOs[ii][x]; } //If scale==0 copy output if(s==0) { for(int ii=0; ii < iChannels; ii++) for(int x=0;x<iWidth*iHeight;x++) fpO[ii][x] = fpOs[ii][x]; /*Clean*/ for (int ii=0; ii < iChannels; ii++) { free(fpOs_old[ii]); } free(fpOs_old); } //Clean the Step if(s>0) { for (int ii=0; ii < iBins; ii++) { free(fhIs[ii]); } for (int ii=0; ii < iChannels; ii++) { free(fpIs[ii]); } free(fpIs); free(fhIs); } for (int ii=0; ii < iChannels; ii++) { free(fpOs[ii]); } free(fpOs); } //for Scales }
// Modèle Numérique d'Élévation Horn Schunck (cas affine) void mnehs_affine(float *out_h, float *init_h, int ow, int oh, float *a, int wa, int ha, float *b, int wb, int hb, double PA[8], double PB[8], float alpha2, int niter) { // allocate temporary images float *h = xmalloc(ow * oh * sizeof*h); // h-increment float *Q = xmalloc(ow * oh * sizeof*Q); // Q float *amb = xmalloc(ow * oh * sizeof*amb); // A-B (warped) float *ga = xmalloc(2 * wa * ha * sizeof*ga); // grad(A) float *gb = xmalloc(2 * wb * hb * sizeof*gb); // grad(B) // gradient of A and B fill_gradient(ga, a, wa, ha); fill_gradient(gb, b, wb, hb); // fill images q and amb (a minus b) for (int j = 0; j < oh; j++) for (int i = 0; i < ow; i++) { float h0 = getsample_nan(init_h, ow, oh, 1, i, j, 0); double ijh[3] = {i, j, h0}, paijh[3], pbijh[3]; apply_projection(paijh, PA, ijh); apply_projection(pbijh, PB, ijh); float va, vb, vga[2], vgb[2]; bicubic_interpolation_nans(&va, a, wa, ha, 1, paijh[0], paijh[1]); bicubic_interpolation_nans(&vb, b, wb, hb, 1, pbijh[0], pbijh[1]); bicubic_interpolation(vga, ga, wa, ha, 2, paijh[0], paijh[1]); bicubic_interpolation(vgb, gb, wb, hb, 2, pbijh[0], pbijh[1]); float gapa = vga[0] * PA[2] + vga[1] * PA[6]; float gbpb = vgb[0] * PB[2] + vgb[1] * PB[6]; Q [j*ow+i] = gapa - gbpb; amb[j*ow+i] = va - vb; } nusavec("Q_%d.tiff", global_scale, Q, ow, oh, 1); nusavec("amb_%d.tiff", global_scale, amb, ow, oh, 1); // initialize h for (int i = 0; i < ow * oh; i++) h[i] = 0; // run the iterations (without warps) for (int iter = 0; iter < niter; iter++) { for (int j = 0; j < oh; j++) for (int i = 0; i < ow; i++) { int ij = j * ow + i; if (!isfinite(amb[ij])) continue; float ax = laplacian_at(h, ow, oh, i, j); ax -= Q[ij] * (Q[ij] * h[ij] + amb[ij]) / alpha2; h[ij] += TAU() * ax; } } nusavec("h_%d.tiff", global_scale, h, ow, oh, 1); // update result for (int i = 0; i < ow * oh; i++) out_h[i] = init_h[i] + h[i]; // cleanup and exit free(h); free(Q); free(amb); free(ga); free(gb); }