Exemplo n.º 1
0
/**
 *  @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;
}
/**
 *
 *  Procedure to handle the pyramidal approach.
 *  This procedure relies on the previous functions to calculate
 *  large optical flow fields using a pyramidal scheme.
 *
 */
 void horn_schunck_pyramidal(
	const float *I1,              // source image
	const float *I2,              // target image
	float       *u,               // x component of optical flow
	float       *v,               // y component of optical flow
	const int    nx,              // image width
	const int    ny,              // image height
	const float  alpha,           // smoothing weight
	const int    nscales,         // number of scales
	const float  zfactor,         // zoom factor
	const int    warps,           // number of warpings per scale
	const float  TOL,             // stopping criterion threshold
	const int    maxiter,         // maximum number of iterations
	const bool   verbose          // switch on messages
)
{
	if (verbose) fprintf(stderr, "Multiscale Horn-Schunck of a %dx%d pair"
			"\n\ta=%g ns=%d zf=%g nw=%d eps=%g mi=%d\n", nx, ny,
			alpha, nscales, zfactor, warps, TOL, maxiter);

	int size = nx * ny;

	float *I1s[nscales];
	float *I2s[nscales];
	float *us[nscales];
	float *vs[nscales];
	int nxx[nscales];
	int nyy[nscales];


	I1s[0] = xmalloc(size * sizeof(float));
	I2s[0] = xmalloc(size * sizeof(float));

	// normalize the finest scale images between 0 and 255
	image_normalization(I1, I2, I1s[0], I2s[0], size);

	// presmoothing the finest scale images
	gaussian(I1s[0], nx, ny, INPUT_PRESMOOTHING_SIGMA);
	gaussian(I2s[0], nx, ny, INPUT_PRESMOOTHING_SIGMA);

	us[0] = u;
	vs[0] = v;
	nxx[0] = nx;
	nyy[0] = ny;

	// create the scales
	for(int s = 1; s < nscales; s++)
	{
		zoom_size(nxx[s-1], nyy[s-1], nxx+s, nyy+s, zfactor);
		const int sizes = nxx[s] * nyy[s];

		I1s[s] = xmalloc(sizes * sizeof(float));
		I2s[s] = xmalloc(sizes * sizeof(float));
		us[s] = xmalloc(sizes * sizeof(float));
		vs[s] = xmalloc(sizes * sizeof(float));

		// compute the zoom from the previous finer scale
		zoom_out(I1s[s-1], I1s[s], nxx[s-1], nyy[s-1], zfactor);
		zoom_out(I2s[s-1], I2s[s], nxx[s-1], nyy[s-1], zfactor);
	}

	// initialize the flow
	for (int i = 0; i < nxx[nscales-1] * nyy[nscales-1]; i++)
	{
		us[nscales-1][i] = 0;
		vs[nscales-1][i] = 0;
	}

	// pyramidal approximation to the optic flow
	for(int s = nscales-1; s >= 0; s--)
	{
		if(verbose)
			fprintf(stderr, "Scale: %d %dx%d\n", s, nxx[s], nyy[s]);

		// compute the optical flow at this scale
		horn_schunck_optical_flow(
			I1s[s], I2s[s], us[s], vs[s], nxx[s], nyy[s],
			alpha, warps, TOL, maxiter, verbose
		);

		// if this was the last scale, finish now
		if (!s) break;

		// otherwise, upsample the optical flow

		// zoom the optic flow for the next finer scale
		zoom_in(us[s], us[s-1], nxx[s], nyy[s], nxx[s-1], nyy[s-1]);
		zoom_in(vs[s], vs[s-1], nxx[s], nyy[s], nxx[s-1], nyy[s-1]);

		// scale the optic flow with the appropriate zoom factor
		for(int i = 0; i < nxx[s-1] * nyy[s-1]; i++)
		{
			us[s-1][i] *= 1.0 / zfactor;
			vs[s-1][i] *= 1.0 / zfactor;
		}
	}

	// free the allocated memory
	free(I1s[0]);
	free(I2s[0]);
	for(int i = 1; i < nscales; i++)
	{
		free(I1s[i]);
		free(I2s[i]);
		free(us[i]);
		free(vs[i]);
	}
}
Exemplo n.º 3
0
/**
 *
 * Function to compute the optical flow using multiple scales
 *
 **/
void Dual_TVL1_optic_flow_multiscale(
		float *I0,           // source image
		float *I1,           // target image
		float *u1,           // x component of the optical flow
		float *u2,           // y component of the optical flow
		const int   nxx,     // image width
		const int   nyy,     // image height
		const float tau,     // time step
		const float lambda,  // weight parameter for the data term
		const float theta,   // weight parameter for (u - v)²
		const int   nscales, // number of scales
		const float zfactor, // factor for building the image piramid
		const int   warps,   // number of warpings per scale
		const float epsilon, // tolerance for numerical convergence
		const bool  verbose  // enable/disable the verbose mode
)
{
	int size = nxx * nyy;

	// allocate memory for the pyramid structure
	float **I0s = xmalloc(nscales * sizeof(float*));
	float **I1s = xmalloc(nscales * sizeof(float*));
	float **u1s = xmalloc(nscales * sizeof(float*));
	float **u2s = xmalloc(nscales * sizeof(float*));
	int    *nx  = xmalloc(nscales * sizeof(int));
	int    *ny  = xmalloc(nscales * sizeof(int));

	I0s[0] = xmalloc(size*sizeof(float));
	I1s[0] = xmalloc(size*sizeof(float));

	u1s[0] = u1;
	u2s[0] = u2;
	nx [0] = nxx;
	ny [0] = nyy;

	// normalize the images between 0 and 255
	image_normalization(I0, I1, I0s[0], I1s[0], size);

	// pre-smooth the original images
	gaussian(I0s[0], nx[0], ny[0], PRESMOOTHING_SIGMA);
	gaussian(I1s[0], nx[0], ny[0], PRESMOOTHING_SIGMA);

	// create the scales
	for (int s = 1; s < nscales; s++)
	{
		zoom_size(nx[s-1], ny[s-1], &nx[s], &ny[s], zfactor);
		const int sizes = nx[s] * ny[s];

		// allocate memory
		I0s[s] = xmalloc(sizes*sizeof(float));
		I1s[s] = xmalloc(sizes*sizeof(float));
		u1s[s] = xmalloc(sizes*sizeof(float));
		u2s[s] = xmalloc(sizes*sizeof(float));

		// zoom in the images to create the pyramidal structure
		zoom_out(I0s[s-1], I0s[s], nx[s-1], ny[s-1], zfactor);
		zoom_out(I1s[s-1], I1s[s], nx[s-1], ny[s-1], zfactor);
	}

	// initialize the flow at the coarsest scale
	for (int i = 0; i < nx[nscales-1] * ny[nscales-1]; i++)
		u1s[nscales-1][i] = u2s[nscales-1][i] = 0.0;

	// pyramidal structure for computing the optical flow
	for (int s = nscales-1; s >= 0; s--)
	{
		if (verbose)
			fprintf(stderr, "Scale %d: %dx%d\n", s, nx[s], ny[s]);

		// compute the optical flow at the current scale
		Dual_TVL1_optic_flow(
				I0s[s], I1s[s], u1s[s], u2s[s], nx[s], ny[s],
				tau, lambda, theta, warps, epsilon, verbose
		);

		// if this was the last scale, finish now
		if (!s) break;

		// otherwise, upsample the optical flow

		// zoom the optical flow for the next finer scale
		zoom_in(u1s[s], u1s[s-1], nx[s], ny[s], nx[s-1], ny[s-1]);
		zoom_in(u2s[s], u2s[s-1], nx[s], ny[s], nx[s-1], ny[s-1]);

		// scale the optical flow with the appropriate zoom factor
		for (int i = 0; i < nx[s-1] * ny[s-1]; i++)
		{
			u1s[s-1][i] *= (float) 1.0 / zfactor;
			u2s[s-1][i] *= (float) 1.0 / zfactor;
		}
	}

	// delete allocated memory
	for (int i = 1; i < nscales; i++)
	{
		free(I0s[i]);
		free(I1s[i]);
		free(u1s[i]);
		free(u2s[i]);
	}
	free(I0s[0]);
	free(I1s[0]);

	free(I0s);
	free(I1s);
	free(u1s);
	free(u2s);
	free(nx);
	free(ny);
}