virtual void onDraw(SkCanvas* canvas) { if (!fInitialized) { make_checkerboard(4, 4); fInitialized = true; } SkScalar sk32 = SkIntToScalar(32); canvas->clear(0x00000000); SkPaint bilinearPaint, bicubicPaint; SkSize scale = SkSize::Make(sk32, sk32); canvas->save(); canvas->scale(sk32, sk32); bilinearPaint.setFilterLevel(SkPaint::kLow_FilterLevel); canvas->drawBitmap(fCheckerboard, 0, 0, &bilinearPaint); canvas->restore(); SkAutoTUnref<SkImageFilter> bicubic(SkBicubicImageFilter::CreateMitchell(scale)); bicubicPaint.setImageFilter(bicubic); SkRect srcBounds; fCheckerboard.getBounds(&srcBounds); canvas->translate(SkIntToScalar(140), 0); canvas->saveLayer(&srcBounds, &bicubicPaint); canvas->drawBitmap(fCheckerboard, 0, 0); canvas->restore(); }
/** * @brief PSF Estimation (Main Function) */ float * psf_estim (float *img, int nx, int ny, float *pattern, int pat_nx, int pat_ny, int s, int psf_nrow, int psf_ncol, int solver, char *detected_ppm) { ImageFloat in, imgW, imgN, imgT, imgEq, xGrid, yGrid, imgC, imgP, imgPf; int i, j; int ncs, nrs; float *psharp, *pblur; float xmin, xmax, ymin, ymax; float fcx, fcy; float *cblur, *csharp; float ps; float *A, *b, *x; int ncol, nrow; ImageFloat imgMask; ThinPlate tp, tpI; /* convert input image to ImageFloat */ in = new_imageFloat (nx, ny); memcpy (in->val, img, nx * ny * sizeof (float)); /* Convert the input random pattern image to a sharp pattern image of UP_RES x UP_RES larger size by replacing each pixel by a block of UP_RES x UP_RES pixels with the same gray value. Also normalize the sharp pattern image to be a FloatImage in [0,1]*/ imgP = pattern_to_pattern_image(pattern, pat_nx, pat_ny); /*---------Detecting the pattern---------*/ printf ("Detecting the pattern...\n"); pblur = detect_pattern (in); /*Check if the detected pattern is required by the user*/ if(detected_ppm) { ImageFloat inR_detected, inG_detected, inB_detected; inR_detected = draw_detected_corners_image_maxval(in, pblur); inG_detected = draw_detected_corners_image_minval(in, pblur); inB_detected = draw_detected_corners_image_minval(in, pblur); write_ppm_normalize_float(detected_ppm, inR_detected->val, inG_detected->val, inB_detected->val, inR_detected->ncol, inR_detected->nrow); free_imageFloat(inR_detected); free_imageFloat(inG_detected); free_imageFloat(inB_detected); } /*---Extract a sub image with the target * and update the checkpoints locations relative to the extracted image */ printf ("Extracting the pattern...\n"); imgT = extract_pattern_region (in, pblur, 12); #ifdef SAVE_INTERMEDIATE_IMGS write_pgm_normalize_float("pattern_region_image.pgm", imgT->val,imgT->ncol, imgT->nrow); #endif /*----Geometric Distortion - Thin Plates----*/ printf ("Calculating thin-plates distortion...\n"); /* Compute checkerboard X points positions in the analytic pattern */ psharp = pattern_Xpoints (); tp = calculate_thinPlate (pblur, psharp, 12, 10);/*lambda = 10 */ tpI = calculate_thinPlate (psharp, pblur, 12, 10);/*lambda = 10 */ /*---Image Ilumination Normalization B&W---*/ printf ("Normalizing image illumination...\n"); imgN = image_normalization (imgT, tpI); #ifdef SAVE_INTERMEDIATE_IMGS write_pgm_normalize_float("illumination_normalized_image.pgm", imgN->val, imgN->ncol, imgN->nrow); #endif /*---CRF Estimation and Correction---*/ printf ("Estimating and correcting CRF...\n"); imgEq = crf_correction (imgN, tpI); #ifdef SAVE_INTERMEDIATE_IMGS write_pgm_normalize_float("crf_corrected_image.pgm", imgEq->val, imgEq->ncol, imgEq->nrow); #endif /*---Extract Noise Region from the observed image*/ printf ("Extracting noise region...\n"); imgW = extract_noise_region (imgEq, tpI, &xmin, &xmax, &ymin, &ymax, &imgMask); #ifdef SAVE_INTERMEDIATE_IMGS write_pgm_normalize_float("noise_region_image.pgm", imgW->val, imgW->ncol, imgW->nrow); write_pgm_normalize_float("mask_image.pgm", imgMask->val, imgMask->ncol, imgMask->nrow); #endif /*--- Pattern Rasterization --- */ /*--------> Cut the spectrum- */ /* * int m = up_res*512; * int n = up_res*512; * double fcx = q*s/(2*n); * double fcy = p*s/(2*m); */ /* fcx = imgW->ncol*s/(2*UP_RES*512); fcy = imgW->nrow*s/(2*UP_RES*512); */ printf ("Filtering and interpolating sharp pattern image...\n"); fcx = roundfi (imgW->ncol * s); fcy = roundfi (imgW->nrow * s); imgPf = lpf_image_dct (imgP, (int) fcx, (int) fcy); /* Pattern sx Interpolation */ ps = 1 / ((float) s); ncs = (xmax - xmin) * s + 1; nrs = (ymax - ymin) * s + 1; cblur = (float *) malloc (nrs * ncs * 2 * sizeof (float)); csharp = (float *) malloc (nrs * ncs * 2 * sizeof (float)); /*Generating the sx-sampling grid */ for (i = 0; i < nrs; i++) for (j = 0; j < ncs; j++) { cblur[2 * i * ncs + 2 * j] = xmin + j * ps; cblur[2 * i * ncs + 2 * j + 1] = ymin + i * ps; } /*Applying TP to the sx-sampling grid and interpolate the Sharp pattern */ evaluate_thinPlate (tp, cblur, csharp, nrs * ncs); xGrid = new_imageFloat (ncs, nrs); yGrid = new_imageFloat (ncs, nrs); /*The Sharp pattern image only contains the noise part * so i need to translate the x,y Grid. Noise regions * starts in (PATTERN_BLOCK_SIZE,PATTERN_BLOCK_SIZE)*UP_RES */ for (i = 0; i < nrs; i++) for (j = 0; j < ncs; j++) { xGrid->val[i * ncs + j] = csharp[2 * i * ncs + 2 * j] - PATTERN_BLOCK_SIZE * UP_RES; yGrid->val[i * ncs + j] = csharp[2 * i * ncs + 2 * j + 1] - PATTERN_BLOCK_SIZE * UP_RES; } /*In version 1.0 the parameter was wrongly set to 0.5 instead of -0.5*/ imgC = bicubic (xGrid, yGrid, imgPf, -0.5); #ifdef SAVE_INTERMEDIATE_IMGS write_pgm_normalize_float("pattern_interpolated_image.pgm", imgC->val, imgC->ncol, imgC->nrow); #endif /*Generating A and b for Ax = b system */ printf ("Generating A,b for Ax = b linear system...\n"); make_Ab (imgC, imgW, imgMask, psf_nrow, psf_ncol, s, &A, &b, &ncol, &nrow); /*There are three different ways of solving * x / Ax = b. * i) least squares * ii) least squares and then projection (x>=th) * iii) non-negative least squares (x>=0) */ printf ("Estimating the PSF: solving Ax = b...\n"); if(solver==0) { x = solve_lsd(A, b, nrow, ncol); } else if (solver==1) { x = solve_lsd_th (A, b, nrow, ncol, 0.001); } else if (solver ==2) { x = solve_nnlsd(A, b, nrow, ncol); } else { error("Solver not recognized. Solver must be 0,1,2"); } printf ("Cleaning the house...\n"); free_imageFloat (imgW); free_imageFloat (imgN); free_imageFloat (imgT); free_imageFloat (imgEq); free_imageFloat (xGrid); free_imageFloat (yGrid); free_imageFloat (imgC); free_imageFloat (imgP); free_imageFloat (imgPf); free_imageFloat (in); free_thinPlate (tp); free_thinPlate (tpI); free ((void *) cblur); free ((void *) csharp); free ((void *) psharp); free ((void *) pblur); free ((void *) A); free((void*) b); return x; }
void inter_image_kernel_to_psf(float *H, float* xinter, float *h, int nx, int ny) { int it_max = 3; int it=0; int i,j; float lambda_x, lambda_y; float scale_x, scale_y, nx2, ny2, nxS2, nyS2, tx, ty; int nxS,nyS; ImageFloat x, xn, xGrid,yGrid,scaled_x,aux; nx2 = (((float)nx)-1)/2; ny2 = (((float)ny)-1)/2; /*Create image with the kernel*/ x = new_imageFloat(nx,ny); xn = new_imageFloat(nx,ny); memcpy (x->val, xinter, nx * ny * sizeof (float)); memcpy (xn->val, xinter, nx * ny * sizeof (float)); /*lambda from ThinPlate Affine Part*/ lambda_x = H[0]; lambda_y = H[4]; /* Initialize scale=lambda^n, n=1*/ scale_x = lambda_x; scale_y = lambda_y; /*nxS = (int)(nx*scale_x+1); nyS = (int)(ny*scale_y+1); */ while (scale_x < 50 && scale_y < 50 && it< it_max) { nxS = ceil(nx*scale_x); nyS = ceil(ny*scale_y); nxS2 = (((float)nxS)-1)/2; nyS2 = (((float)nyS)-1)/2; xGrid = new_imageFloat (nxS, nyS); yGrid = new_imageFloat (nxS, nyS); tx = nx2 - nxS2/scale_x; ty = ny2 - nyS2/scale_y; /*Start from the center so the (tx,ty); is needed*/ for (i = 0; i < xGrid->nrow; i++) for (j = 0; j < xGrid->ncol; j++) { xGrid->val[i * xGrid->ncol + j] = ((float)j)/scale_x + tx; yGrid->val[i * xGrid->ncol + j] = ((float)i)/scale_y + ty; } scaled_x = bicubic (xGrid, yGrid, x, -0.5); free_imageFloat(xGrid); free_imageFloat(yGrid); printf("Iteration %d :: scale x: %f, y: %f\n",it, scale_x, scale_y); aux = convol(scaled_x,xn); free_imageFloat(xn); free_imageFloat(scaled_x); xn = new_imageFloat(aux->ncol,aux->nrow); memcpy (xn->val, aux->val, aux->ncol * aux->nrow * sizeof (float)); free_imageFloat(aux); scale_x = scale_x*lambda_x; scale_y = scale_y*lambda_y; it = it+1; } /*I added one extra scale...*/ scale_x = scale_x/lambda_x; scale_y = scale_y/lambda_y; xGrid = new_imageFloat (nx,ny); yGrid = new_imageFloat (nx,ny); tx = nxS2 - nx2*scale_x; ty = nyS2 - ny2*scale_y; /*I start from the center*/ for (i = 0; i < ny; i++) for (j = 0; j < nx; j++) { xGrid->val[i * xGrid->ncol + j] = j*scale_x + tx; yGrid->val[i * xGrid->ncol + j] = i*scale_y + ty; } aux = bicubic (xGrid, yGrid, xn, -0.5); /*h = (float *) malloc (nx * ny * sizeof (float));*/ memcpy (h, aux->val, nx * ny * sizeof (float)); free_imageFloat(aux); free_imageFloat(xGrid); free_imageFloat(yGrid); free_imageFloat(xn); free_imageFloat(x); }
/** * @brief Interpolate the closest image \f$\textbf{v}_1\f$ * to generate \f$\textbf{H}_{\lambda/s} \tilde{\textbf{v}}_1\f$ */ void closest_image_interpolation(float* H, int s, ImageFloat imgW, ImageFloat imgP, ImageFloat* imgC, ImageFloat* imgMask, float* offset_LR, float* offset_HR) { ImageFloat imgPf, imgMaskPf, imgMaskC, xGrid, yGrid; float *coordImgLRsx, *coordImgHRsx; float ps; int ncs, nrs, i, j; /* Cut all frequencies above fcx or fcy: * fcx = imgW->ncol*s/(2*UP_RES*512); * fcy = imgW->nrow*s/(2*UP_RES*512); */ float fcx,fcy; fcx = roundfi (imgW->ncol * s); fcy = roundfi (imgW->nrow * s); /*Filter to avoid aliasing*/ imgPf = lpf_image_dct (imgP, (int) fcx, (int) fcy); /* Image sx Interpolation H_lambda/s v1 */ ps = 1 / ((float) s); ncs = (imgW->ncol-1) * s + 1; nrs = (imgW->nrow-1) * s + 1; /*Sampling Grids points*/ coordImgLRsx = (float *) malloc (nrs * ncs * 2 * sizeof (float)); coordImgHRsx = (float *) malloc (nrs * ncs * 2 * sizeof (float)); /*Generating the sx-sampling grid */ for (i = 0; i < nrs; i++) for (j = 0; j < ncs; j++) { /*Add the offset to reach the common part*/ coordImgLRsx[2 * i * ncs + 2 * j] = j * ps + offset_LR[0]; coordImgLRsx[2 * i * ncs + 2 * j + 1] = i * ps + offset_LR[1]; } /*Apply Homography to the sx-sampling grid and then interpolate the *closest image */ evaluate_homography (H, coordImgLRsx, coordImgHRsx, nrs * ncs); /*Sampling Grids at the common region*/ xGrid = new_imageFloat (ncs, nrs); yGrid = new_imageFloat (ncs, nrs); for (i = 0; i < nrs; i++) for (j = 0; j < ncs; j++) { /*Remove the offset to reach the common region*/ xGrid->val[i * ncs + j] = coordImgHRsx[2 * i * ncs + 2 * j] - offset_HR[0]; yGrid->val[i * ncs + j] = coordImgHRsx[2 * i * ncs + 2 * j + 1] - offset_HR[1]; } /*Bicubic interpolation of the filtered closest image at the sampling grid *sx the resolution of the farthest image */ *imgC = bicubic (xGrid, yGrid, imgPf, -0.5); /*Create a Mask where the interpolation is valid *of course recomputing the interpolation is not optimal but it works. */ imgMaskPf = new_imageFloat(imgPf->ncol,imgPf->nrow); for(i=0;i<imgMaskPf->ncol*imgMaskPf->nrow;i++) imgMaskPf->val[i] = 1; /*Mask at the sx grid*/ imgMaskC = bicubic (xGrid, yGrid, imgMaskPf, -0.5); /*Mask at the 1x grid*/ *imgMask = new_imageFloat(imgW->ncol,imgW->nrow); for(i=0;i< (*imgMask)->nrow;i++) for(j=0;j< (*imgMask)->ncol;j++) (*imgMask)->val[i * (*imgMask)->ncol +j] = imgMaskC->val[i*s*imgMaskC->ncol+j*s]; /*Do the cleaning*/ free_imageFloat (imgPf); free_imageFloat (imgMaskPf); free_imageFloat (imgMaskC); free_imageFloat (xGrid); free_imageFloat (yGrid); free ((void *) coordImgLRsx); free ((void *) coordImgHRsx); }