Exemple #1
0
static gboolean
prewitt_vertical(GwyContainer *data, GwyRunType run)
{
    GObject *shadefield;
    GwyDataField *dfield;

    g_assert(run & GRADIENT_RUN_MODES);
    
    dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(data, "/0/data"));
    gwy_app_undo_checkpoint(data, "/0/show", NULL);
    if (gwy_container_gis_object_by_name(data, "/0/show", &shadefield)) {
        gwy_data_field_resample(GWY_DATA_FIELD(shadefield),
                                gwy_data_field_get_xres(dfield),
                                gwy_data_field_get_yres(dfield),
                                GWY_INTERPOLATION_NONE);
    }
    else {
        shadefield = gwy_serializable_duplicate(G_OBJECT(dfield));
        gwy_container_set_object_by_name(data, "/0/show", shadefield);
        g_object_unref(shadefield);
    }

    gwy_data_field_area_copy(dfield, GWY_DATA_FIELD(shadefield), 
                             0, 0, gwy_data_field_get_xres(dfield),
                             gwy_data_field_get_yres(dfield), 0, 0);
    
    gwy_data_field_area_filter_prewitt(GWY_DATA_FIELD(shadefield), GTK_ORIENTATION_VERTICAL, 
                                     0, 0,
                                     gwy_data_field_get_xres(dfield),
                                     gwy_data_field_get_yres(dfield));
    return TRUE;
}
Exemple #2
0
static void
rotate_datafield(GwyDataField *dfield,
                 RotateArgs *args)
{
    gint xres, yres, xborder, yborder;
    gdouble xreal, yreal, phi, min;
    GwyDataField *df;

    if (!args->expand) {
        gwy_data_field_rotate(dfield, args->angle, args->interp);
        return;
    }

    xres = gwy_data_field_get_xres(dfield);
    yres = gwy_data_field_get_yres(dfield);
    xreal = gwy_data_field_get_xreal(dfield);
    yreal = gwy_data_field_get_yreal(dfield);
    min = gwy_data_field_get_min(dfield);
    phi = args->angle;
    xborder = fabs(xres/2.0 * cos(phi)) + fabs(yres/2.0 * sin(phi));
    xborder -= xres/2;
    yborder = fabs(yres/2.0 * cos(phi)) + fabs(xres/2.0 * sin(phi));
    yborder -= yres/2;
    df = gwy_data_field_new(xres + fabs(2*xborder), yres + fabs(2*yborder), 1.0, 1.0,
                            FALSE);
    gwy_data_field_fill(df, min);
    gwy_data_field_area_copy(dfield, df, 0, 0, xres, yres, fabs(xborder), fabs(yborder));
    gwy_data_field_rotate(df, args->angle, args->interp);
    gwy_data_field_resample(dfield, xres + 2*xborder, yres + 2*yborder,
                            GWY_INTERPOLATION_NONE);
    if (xborder <= 0)
        gwy_data_field_area_copy(df, dfield, fabs(2*xborder), 0, xres + 2*xborder, yres + 2*yborder, 0, 0);
    else {
          if (yborder <= 0)
              gwy_data_field_area_copy(df, dfield, 0, fabs(2*yborder), xres + 2*xborder, yres + 2*yborder, 0, 0);
          else
            gwy_data_field_area_copy(df, dfield, 0, 0, xres + 2*xborder, yres + 2*yborder, 0, 0);
    }
    gwy_data_field_set_xreal(dfield, xreal*(xres + 2.0*xborder)/xres);
    gwy_data_field_set_yreal(dfield, yreal*(yres + 2.0*yborder)/yres);
    g_object_unref(df);
}
Exemple #3
0
static void
preview(DepositControls *controls,
        DepositArgs *args)
{
    GwyDataField *dfield, *lfield, *zlfield, *zdfield;
    gint xres, yres, oxres, oyres;
    gint add, i, ii, m, k;
    gdouble size, width;
    gint xdata[10000];
    gint ydata[10000];
    gdouble disizes[10000];
    gdouble rdisizes[10000];
    gdouble rx[10000];
    gdouble ry[10000];
    gdouble rz[10000];
    gdouble ax[10000];
    gdouble ay[10000];
    gdouble az[10000];
    gdouble vx[10000];
    gdouble vy[10000];
    gdouble vz[10000];
    gdouble fx[10000];
    gdouble fy[10000];
    gdouble fz[10000];
     gint xpos, ypos, ndata, too_close;
    gdouble disize, mdisize;
    gdouble xreal, yreal, oxreal, oyreal;
    gdouble diff;
    gdouble mass = 1;
    gint presetval;
    gint nloc, maxloc = 1;
    gint max = 5000000;
    gdouble rxv, ryv, rzv, timestep = 3e-7; //5e-7

    deposit_dialog_update_values(controls, args);
    dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(controls->mydata,
                                                             "/0/data"));

    gwy_container_set_object_by_name(controls->mydata, "/0/data", gwy_data_field_duplicate(controls->old_dfield));
    dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(controls->mydata,
                                                                      "/0/data"));

    if (controls->in_init)
    {
        gwy_data_field_data_changed(dfield); 
        while (gtk_events_pending())
            gtk_main_iteration();
        return;
    }


    oxres = gwy_data_field_get_xres(dfield);
    oyres = gwy_data_field_get_yres(dfield);
    oxreal = gwy_data_field_get_xreal(dfield);
    oyreal = gwy_data_field_get_yreal(dfield);
    diff = oxreal/oxres/10;


    size = args->size*5e-9;
   // width = args->width*5e-9 + 2*size; //increased manually to fill boundaries
    width = 2*size;
    add = gwy_data_field_rtoi(dfield, size + width);
    mdisize = gwy_data_field_rtoi(dfield, size);
    xres = oxres + 2*add;
    yres = oyres + 2*add;
    xreal = oxreal + 2*(size+width);
    yreal = oyreal + 2*(size+width);


//    printf("For field of size %g and particle nominak %g, real %g (%g), the final size will change from %d to %d\n",
//           gwy_data_field_get_xreal(dfield), args->size, size, disize, oxres, xres);

    /*make copy of datafield, with mirrored boundaries*/
    lfield = gwy_data_field_new(xres, yres, 
                                gwy_data_field_itor(dfield, xres), 
                                gwy_data_field_jtor(dfield, yres),
                                TRUE);
    gwy_data_field_area_copy(dfield, lfield, 0, 0, oxres, oyres, add, add);

    gwy_data_field_invert(dfield, 1, 0, 0);
    gwy_data_field_area_copy(dfield, lfield, 0, oyres-add-1, oxres, add, add, 0);
    gwy_data_field_area_copy(dfield, lfield, 0, 0, oxres, add, add, yres-add-1);
    gwy_data_field_invert(dfield, 1, 0, 0);

    gwy_data_field_invert(dfield, 0, 1, 0);
    gwy_data_field_area_copy(dfield, lfield, oxres-add-1, 0, add, oyres, 0, add);
    gwy_data_field_area_copy(dfield, lfield, 0, 0, add, oyres, xres-add-1, add);
    gwy_data_field_invert(dfield, 0, 1, 0);

    gwy_data_field_invert(dfield, 1, 1, 0);
    gwy_data_field_area_copy(dfield, lfield, oxres-add-1, oyres-add-1, add, add, 0, 0);
    gwy_data_field_area_copy(dfield, lfield, 0, 0, add, add, xres-add-1, yres-add-1);
    gwy_data_field_area_copy(dfield, lfield, oxres-add-1, 0, add, add, 0, yres-add-1);
    gwy_data_field_area_copy(dfield, lfield, 0, oyres-add-1, add, add, xres-add-1, 0);
    gwy_data_field_invert(dfield, 1, 1, 0);

    zlfield = gwy_data_field_duplicate(lfield);
    zdfield = gwy_data_field_duplicate(dfield);
    /*determine number of spheres necessary for given coverage*/

    for (i=0; i<10000; i++) 
    {
        ax[i] = ay[i] = az[i] = vx[i] = vy[i] = vz[i] = 0;
    }
    
    srand ( time(NULL) );

    ndata = 0;
 
    /* for test only */
    /*
    disize = mdisize;
    
    xpos = oxres/2 - 2*disize;
    ypos = oyres/2;
    xdata[ndata] = xpos;
    ydata[ndata] = ypos;
    disizes[ndata] = disize;
    rdisizes[ndata] = size;
    rx[ndata] = (gdouble)xpos*oxreal/(gdouble)oxres;
    ry[ndata] = (gdouble)ypos*oyreal/(gdouble)oyres;
    rz[ndata] = 2.0*gwy_data_field_get_val(lfield, xpos, ypos) + rdisizes[ndata];
    ndata++;

    xpos = oxres/2 + 2*disize;
    ypos = oyres/2;
    xdata[ndata] = xpos;
    ydata[ndata] = ypos;
    disizes[ndata] = disize;
    rdisizes[ndata] = size;
    rx[ndata] = (gdouble)xpos*oxreal/(gdouble)oxres;
    ry[ndata] = (gdouble)ypos*oyreal/(gdouble)oyres;
    rz[ndata] = 2.0*gwy_data_field_get_val(lfield, xpos, ypos) + rdisizes[ndata];
    ndata++;
    */
    /*end of test*/

    i = 0;
    presetval = args->coverage*10;
    while (ndata < presetval && i<max)
    {
        //disize = mdisize*(0.8+(double)(rand()%20)/40.0);   
        disize = mdisize;

        xpos = disize+(rand()%(xres-2*(gint)(disize+1))) + 1;
        ypos = disize+(rand()%(yres-2*(gint)(disize+1))) + 1;
        i++;
        

        {
            too_close = 0;

            /*sync real to integer positions*/
            for (k=0; k<ndata; k++)
            {
                if (((xpos-xdata[k])*(xpos-xdata[k]) + (ypos-ydata[k])*(ypos-ydata[k]))<(4*disize*disize))
                {
                    too_close = 1;
                    break;
                }
            }
            if (too_close) continue;
            if (ndata>=10000) {
                break;
            }

            xdata[ndata] = xpos;
            ydata[ndata] = ypos;
            disizes[ndata] = disize;
            rdisizes[ndata] = size;
            rx[ndata] = (gdouble)xpos*oxreal/(gdouble)oxres;
            ry[ndata] = (gdouble)ypos*oyreal/(gdouble)oyres;
            //printf("surface at %g, particle size %g\n", gwy_data_field_get_val(lfield, xpos, ypos), rdisizes[ndata]);
            rz[ndata] = 1.0*gwy_data_field_get_val(lfield, xpos, ypos) + rdisizes[ndata]; //2
            ndata++;
        }
    };
//    if (i==max) printf("Maximum reached, only %d particles depositd instead of %d\n", ndata, presetval);
//    else printf("%d particles depositd\n", ndata);

    /*refresh shown data and integer positions (necessary in md calculation)*/
    gwy_data_field_copy(zlfield, lfield, 0);
    showit(lfield, zdfield, rdisizes, rx, ry, rz, xdata, ydata, ndata, 
                  oxres, oxreal, oyres, oyreal, add, xres, yres);


    gwy_data_field_area_copy(lfield, dfield, add, add, oxres, oyres, 0, 0);
    gwy_data_field_data_changed(dfield);


    for (i=0; i<(20*args->revise); i++)
    {
//        printf("###### step %d of %d ##########\n", i, (gint)(20*args->revise));

        /*try to add some particles if necessary, do this only for first half of molecular dynamics*/
        if (ndata<presetval && i<(10*args->revise)) {
            ii = 0;
            nloc = 0;
            
            while (ndata < presetval && ii<(max/1000) && nloc<maxloc)
            {
                disize = mdisize;
                xpos = disize+(rand()%(xres-2*(gint)(disize+1))) + 1;
                ypos = disize+(rand()%(yres-2*(gint)(disize+1))) + 1;
                ii++;


                {
                    too_close = 0;

                    rxv = ((gdouble)xpos*oxreal/(gdouble)oxres);
                    ryv = ((gdouble)ypos*oyreal/(gdouble)oyres);
                    rzv = gwy_data_field_get_val(zlfield, xpos, ypos) + 5*size;
                    
                    for (k=0; k<ndata; k++)
                    {
                        if (((rxv-rx[k])*(rxv-rx[k]) 
                             + (ryv-ry[k])*(ryv-ry[k])
                             + (rzv-rz[k])*(rzv-rz[k]))<(4.0*size*size))
                        {
                            too_close = 1;
                            break;
                        }
                    }
                    if (too_close) continue;
                    if (ndata>=10000) {
//                        printf("Maximum reached!\n");
                        break;
                    }

                    xdata[ndata] = xpos;
                    ydata[ndata] = ypos;
                    disizes[ndata] = disize;
                    rdisizes[ndata] = size;
                    rx[ndata] = rxv;
                    ry[ndata] = ryv;
                    rz[ndata] = rzv;
                    vz[ndata] = -0.01;
                    ndata++;
                    nloc++;

                }
            };
//            if (ii==(max/100)) printf("Maximum reached, only %d particles now present instead of %d\n", ndata, presetval);
//            else printf("%d particles now at surface\n", ndata);
            
        }

        /*test succesive LJ steps on substrate (no relaxation)*/
        for (k=0; k<ndata; k++)
        {
            fx[k] = fy[k] = fz[k] = 0;
            /*calculate forces for all particles on substrate*/

            if (gwy_data_field_rtoi(lfield, rx[k])<0 
                || gwy_data_field_rtoj(lfield, ry[k])<0 
                || gwy_data_field_rtoi(lfield, rx[k])>=xres
                || gwy_data_field_rtoj(lfield, ry[k])>=yres)
                continue;

            for (m=0; m<ndata; m++)
            {
               
                if (m==k) continue;

            //    printf("(%g %g %g) on (%g %g %g)\n", rx[m], ry[m], rz[m], rx[k], ry[k], rz[k]);
                fx[k] -= (get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k]+diff, ry[k], rz[k], gwy_data_field_itor(dfield, disizes[k]))
                              -get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k]-diff, ry[k], rz[k], gwy_data_field_itor(dfield, disizes[k])))/2/diff; 
                fy[k] -= (get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k], ry[k]+diff, rz[k], gwy_data_field_itor(dfield, disizes[k]))
                              -get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k], ry[k]-diff, rz[k], gwy_data_field_itor(dfield, disizes[k])))/2/diff; 
                fz[k] -= (get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k], ry[k], rz[k]+diff, gwy_data_field_itor(dfield, disizes[k]))
                              -get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k], ry[k], rz[k]-diff, gwy_data_field_itor(dfield, disizes[k])))/2/diff; 

            }
                
            fx[k] -= (integrate_lj_substrate(zlfield, rx[k]+diff, ry[k], rz[k], rdisizes[k]) 
                    - integrate_lj_substrate(zlfield, rx[k]-diff, ry[k], rz[k], rdisizes[k]))/2/diff;
            fy[k] -= (integrate_lj_substrate(zlfield, rx[k], ry[k]-diff, rz[k], rdisizes[k]) 
                    - integrate_lj_substrate(zlfield, rx[k], ry[k]+diff, rz[k], rdisizes[k]))/2/diff;
            fz[k] -= (integrate_lj_substrate(zlfield, rx[k], ry[k], rz[k]+diff, rdisizes[k]) 
                    - integrate_lj_substrate(zlfield, rx[k], ry[k], rz[k]-diff, rdisizes[k]))/2/diff;
        } 
        for (k=0; k<ndata; k++)
        {
          if (gwy_data_field_rtoi(lfield, rx[k])<0 
                || gwy_data_field_rtoj(lfield, ry[k])<0 
                || gwy_data_field_rtoi(lfield, rx[k])>=xres
                || gwy_data_field_rtoj(lfield, ry[k])>=yres)
                continue;

            /*move all particles*/
            rx[k] += vx[k]*timestep + 0.5*ax[k]*timestep*timestep;
            vx[k] += 0.5*ax[k]*timestep;
            ax[k] = fx[k]/mass;
            vx[k] += 0.5*ax[k]*timestep;
            vx[k] *= 0.9;
            if (fabs(vx[k])>0.01) vx[k] = 0; //0.2

            ry[k] += vy[k]*timestep + 0.5*ay[k]*timestep*timestep;
            vy[k] += 0.5*ay[k]*timestep;
            ay[k] = fy[k]/mass;
            vy[k] += 0.5*ay[k]*timestep;
            vy[k] *= 0.9;
            if (fabs(vy[k])>0.01) vy[k] = 0; //0.2

            rz[k] += vz[k]*timestep + 0.5*az[k]*timestep*timestep;
            vz[k] += 0.5*az[k]*timestep;
            az[k] = fz[k]/mass;
            vz[k] += 0.5*az[k]*timestep;
            vz[k] *= 0.9;
            if (fabs(vz[k])>0.01) vz[k] = 0;

            if (rx[k]<=gwy_data_field_itor(dfield, disizes[k])) rx[k] = gwy_data_field_itor(dfield, disizes[k]);
            if (ry[k]<=gwy_data_field_itor(dfield, disizes[k])) ry[k] = gwy_data_field_itor(dfield, disizes[k]);
            if (rx[k]>=(xreal-gwy_data_field_itor(dfield, disizes[k]))) rx[k] = xreal-gwy_data_field_itor(dfield, disizes[k]);
            if (ry[k]>=(yreal-gwy_data_field_itor(dfield, disizes[k]))) ry[k] = yreal-gwy_data_field_itor(dfield, disizes[k]);

        }
        

        gwy_data_field_copy(zlfield, lfield, 0);
        showit(lfield, zdfield, rdisizes, rx, ry, rz, xdata, ydata, ndata, 
               oxres, oxreal, oyres, oyreal, add, xres, yres);
        


        gwy_data_field_area_copy(lfield, dfield, add, add, oxres, oyres, 0, 0);
        gwy_data_field_data_changed(dfield); 
        while (gtk_events_pending())
                    gtk_main_iteration();

       
    }


    gwy_data_field_area_copy(lfield, dfield, add, add, oxres, oyres, 0, 0);

    gwy_data_field_data_changed(dfield);
    args->computed = TRUE;
    gwy_object_unref(lfield);
    gwy_object_unref(zlfield);
    gwy_object_unref(zdfield);

}
Exemple #4
0
static void
immerse_do(ImmerseArgs *args)
{
    GwyDataField *resampled, *image, *detail, *result;
    GwyContainer *data;
    gint newid;
    gint kxres, kyres;
    gint x, y, w, h;
    gdouble iavg, davg;
    GQuark quark;

    data = gwy_app_data_browser_get(args->image.datano);
    quark = gwy_app_get_data_key_for_id(args->image.id);
    image = GWY_DATA_FIELD(gwy_container_get_object(data, quark));

    data = gwy_app_data_browser_get(args->detail.datano);
    quark = gwy_app_get_data_key_for_id(args->detail.id);
    detail = GWY_DATA_FIELD(gwy_container_get_object(data, quark));
    davg = gwy_data_field_get_avg(detail);

    kxres = gwy_data_field_get_xres(detail);
    kyres = gwy_data_field_get_yres(detail);

    switch (args->sampling) {
        case GWY_IMMERSE_SAMPLING_DOWN:
        result = gwy_data_field_duplicate(image);
        x = gwy_data_field_rtoj(image, args->xpos);
        y = gwy_data_field_rtoi(image, args->ypos);
        w = GWY_ROUND(gwy_data_field_get_xreal(detail)
                      /gwy_data_field_get_xmeasure(image));
        h = GWY_ROUND(gwy_data_field_get_yreal(detail)
                      /gwy_data_field_get_ymeasure(image));
        w = MAX(w, 1);
        h = MAX(h, 1);
        gwy_debug("w: %d, h: %d", w, h);
        resampled = gwy_data_field_new_resampled(detail, w, h,
                                                 GWY_INTERPOLATION_LINEAR);
        if (args->leveling == GWY_IMMERSE_LEVEL_MEAN) {
            iavg = gwy_data_field_area_get_avg(result, NULL, x, y, w, h);
            gwy_data_field_add(resampled, iavg - davg);
        }
        gwy_data_field_area_copy(resampled, result, 0, 0, w, h, x, y);
        g_object_unref(resampled);
        break;

        case GWY_IMMERSE_SAMPLING_UP:
        w = GWY_ROUND(gwy_data_field_get_xreal(image)
                      /gwy_data_field_get_xmeasure(detail));
        h = GWY_ROUND(gwy_data_field_get_yreal(image)
                      /gwy_data_field_get_ymeasure(detail));
        gwy_debug("w: %d, h: %d", w, h);
        result = gwy_data_field_new_resampled(image, w, h,
                                              GWY_INTERPOLATION_LINEAR);
        x = gwy_data_field_rtoj(result, args->xpos);
        y = gwy_data_field_rtoi(result, args->ypos);
        if (args->leveling == GWY_IMMERSE_LEVEL_MEAN) {
            iavg = gwy_data_field_area_get_avg(result, NULL,
                                               x, y, kxres, kyres);
            gwy_data_field_area_copy(detail, result, 0, 0, kxres, kyres, x, y);
            gwy_data_field_area_add(result, x, y, kxres, kyres, iavg - davg);
        }
        else
            gwy_data_field_area_copy(detail, result, 0, 0, kxres, kyres, x, y);
        break;

        default:
        g_return_if_reached();
        break;
    }

    gwy_app_data_browser_get_current(GWY_APP_CONTAINER, &data, 0);
    newid = gwy_app_data_browser_add_data_field(result, data, TRUE);
    gwy_app_set_data_field_title(data, newid, _("Immersed detail"));
    g_object_unref(result);
    gwy_app_channel_log_add_proc(data, args->image.id, newid);
}
Exemple #5
0
static void
put_fields(GwyDataField *dfield1, GwyDataField *dfield2,
           GwyDataField *result, GwyDataField *outsidemask,
           GwyMergeBoundaryType boundary,
           gint px1, gint py1,
           gint px2, gint py2)
{
    GwyRectangle res_rect;
    GwyCoord f1_pos;
    GwyCoord f2_pos;
    gint w1, w2, h1, h2;
    gdouble xreal, yreal;

    gwy_debug("field1 %dx%d", dfield1->xres, dfield1->yres);
    gwy_debug("field2 %dx%d", dfield2->xres, dfield2->yres);
    gwy_debug("result %dx%d", result->xres, result->yres);
    gwy_debug("px1: %d, py1: %d, px2: %d, py2: %d", px1, py1, px2, py2);

    gwy_data_field_fill(result,
                        MIN(gwy_data_field_get_min(dfield1),
                            gwy_data_field_get_min(dfield2)));

    w1 = gwy_data_field_get_xres(dfield1);
    h1 = gwy_data_field_get_yres(dfield1);
    w2 = gwy_data_field_get_xres(dfield2);
    h2 = gwy_data_field_get_yres(dfield2);

    if (boundary == GWY_MERGE_BOUNDARY_SECOND) {
        gwy_data_field_area_copy(dfield1, result, 0, 0, w1, h1, px1, py1);
        gwy_data_field_area_copy(dfield2, result, 0, 0, w2, h2, px2, py2);
    }
    else {
        gwy_data_field_area_copy(dfield2, result, 0, 0, w2, h2, px2, py2);
        gwy_data_field_area_copy(dfield1, result, 0, 0, w1, h1, px1, py1);
    }

    if (outsidemask) {
        gwy_data_field_fill(outsidemask, 1.0);
        gwy_data_field_area_clear(outsidemask, px1, py1, w1, h1);
        gwy_data_field_area_clear(outsidemask, px2, py2, w2, h2);
    }

    /* adjust boundary to be as smooth as possible */
    if (boundary == GWY_MERGE_BOUNDARY_AVERAGE
            || boundary == GWY_MERGE_BOUNDARY_INTERPOLATE) {
        if (px1 < px2) {
            res_rect.x = px2;
            res_rect.width = px1 + w1 - px2;
        }
        else {
            res_rect.x = px1;
            res_rect.width = px2 + w2 - px1;
        }

        if (py1 < py2) {
            res_rect.y = py2;
            res_rect.height = py1 + h1 - py2;
        }
        else {
            res_rect.y = py1;
            res_rect.height = py2 + h2 - py1;
        }

        res_rect.height = MIN(res_rect.height, MIN(h1, h2));
        res_rect.width = MIN(res_rect.width, MIN(w1, w2));

        /* This is where the result rectangle is positioned in the fields,
         * not where the fields themselves are placed! */
        f1_pos.x = res_rect.x - px1;
        f1_pos.y = res_rect.y - py1;
        f2_pos.x = res_rect.x - px2;
        f2_pos.y = res_rect.y - py2;

        merge_boundary(dfield1, dfield2, result, res_rect, f1_pos, f2_pos,
                       boundary);
    }

    /* Use the pixels sizes of field 1 -- they must be identical. */
    xreal = result->xres * gwy_data_field_get_xmeasure(dfield1);
    yreal = result->yres * gwy_data_field_get_ymeasure(dfield1);
    gwy_data_field_set_xreal(result, xreal);
    gwy_data_field_set_yreal(result, yreal);
    if (outsidemask) {
        gwy_data_field_set_xreal(outsidemask, xreal);
        gwy_data_field_set_yreal(outsidemask, yreal);
    }
}
Exemple #6
0
/**
 * gwy_data_field_correlate:
 * @data_field: A data field.
 * @kernel_field: Correlation kernel.
 * @score: Data field to store correlation scores to.
 * @method: Correlation score calculation method.
 *
 * Computes correlation score for all positions in a data field.
 *
 * Correlation score is compute for all points in data field @data_field
 * and full size of correlation kernel @kernel_field.
 *
 * The points in @score correspond to centers of kernel.  More precisely, the
 * point ((@kxres-1)/2, (@kyres-1)/2) in @score corresponds to kernel field
 * top left corner coincident with data field top left corner.  Points outside
 * the area where the kernel field fits into the data field completely are
 * set to -1 for %GWY_CORRELATION_NORMAL.
 **/
void
gwy_data_field_correlate(GwyDataField *data_field, GwyDataField *kernel_field,
                         GwyDataField *score, GwyCorrelationType method)
{

    gint xres, yres, kxres, kyres, i, j, k, fftxres, fftyres;
    GwyDataField *data_in_re, *data_out_re, *data_out_im;
    GwyDataField *kernel_in_re, *kernel_out_re, *kernel_out_im;
    gdouble norm;

    g_return_if_fail(data_field != NULL && kernel_field != NULL);

    xres = data_field->xres;
    yres = data_field->yres;
    kxres = kernel_field->xres;
    kyres = kernel_field->yres;

    if (kxres <= 0 || kyres <= 0) {
        g_warning("Correlation kernel has nonpositive size.");
        return;
    }

    switch (method) {
        case GWY_CORRELATION_NORMAL:
        gwy_data_field_fill(score, -1);
        /*correlation request outside kernel */
        if (kxres > xres || kyres > yres) {
            return;
        }

        {
            GwyDataField *avg, *rms;
            gdouble s, davg, drms, kavg, krms;
            gint xoff, yoff;

            /* The number of pixels the correlation kernel extends to the
             * negative direction */
            xoff = (kxres - 1)/2;
            yoff = (kyres - 1)/2;
            kavg = gwy_data_field_get_avg(kernel_field);
            krms = gwy_data_field_get_rms(kernel_field);
            avg = gwy_data_field_duplicate(data_field);
            rms = gwy_data_field_duplicate(data_field);
            calculate_normalization(avg, rms, kxres, kyres);
            for (i = yoff; i + kyres - yoff <= yres; i++) {
                for (j = xoff; j + kxres - xoff <= xres; j++) {
                    k = i*xres + j;
                    davg = avg->data[k];
                    drms = rms->data[k];
                    if (!krms || !drms) {
                        score->data[k] = 0.0;
                        continue;
                    }
                    s = gwy_data_field_get_raw_correlation_score(data_field,
                                                                 kernel_field,
                                                                 j - xoff,
                                                                 i - yoff,
                                                                 0, 0,
                                                                 kxres, kyres,
                                                                 davg, kavg);
                    score->data[k] = s/(drms*krms);
                }
            }
            g_object_unref(avg);
            g_object_unref(rms);
        }
        break;

        case GWY_CORRELATION_FFT:
        case GWY_CORRELATION_POC:
        fftxres = gwy_fft_find_nice_size(xres);
        fftyres = gwy_fft_find_nice_size(yres);
        data_in_re = gwy_data_field_new_resampled(data_field,
                                                  fftxres, fftyres,
                                                  GWY_INTERPOLATION_BILINEAR);
        kernel_in_re = gwy_data_field_new_alike(data_field, TRUE);
        gwy_data_field_area_copy(kernel_field, kernel_in_re,
                                 0, 0, kernel_field->xres, kernel_field->yres,
                                 kernel_in_re->xres/2 - kernel_field->xres/2,
                                 kernel_in_re->yres/2 - kernel_field->yres/2);
        gwy_data_field_resample(kernel_in_re, fftxres, fftyres,
                                GWY_INTERPOLATION_BILINEAR);
        gwy_data_field_resample(score, fftxres, fftyres,
                                GWY_INTERPOLATION_NONE);

        data_out_re = gwy_data_field_new_alike(data_in_re, TRUE);
        data_out_im = gwy_data_field_new_alike(data_in_re, TRUE);
        kernel_out_re = gwy_data_field_new_alike(data_in_re, TRUE);
        kernel_out_im = gwy_data_field_new_alike(data_in_re, TRUE);

        gwy_data_field_2dfft(data_in_re, NULL, data_out_re, data_out_im,
                             GWY_WINDOWING_NONE,
                             GWY_TRANSFORM_DIRECTION_FORWARD,
                             GWY_INTERPOLATION_BILINEAR, FALSE, FALSE);
        gwy_data_field_2dfft(kernel_in_re, NULL, kernel_out_re, kernel_out_im,
                             GWY_WINDOWING_NONE,
                             GWY_TRANSFORM_DIRECTION_FORWARD,
                             GWY_INTERPOLATION_BILINEAR, FALSE, FALSE);

        for (i = 0; i < fftxres*fftyres; i++) {
            /*NOTE: now we construct new "complex field" from data
             * and kernel fields, just to save memory*/
            data_in_re->data[i] = data_out_re->data[i]*kernel_out_re->data[i]
                + data_out_im->data[i]*kernel_out_im->data[i];
            kernel_in_re->data[i] = -data_out_re->data[i]*kernel_out_im->data[i]
                + data_out_im->data[i]*kernel_out_re->data[i];
            if (method == GWY_CORRELATION_POC) {
                norm = hypot(data_in_re->data[i], kernel_in_re->data[i]);
                data_in_re->data[i] /= norm;
                kernel_in_re->data[i] /= norm;
            }
        }
        gwy_data_field_2dfft(data_in_re, kernel_in_re, score, data_out_im,
                             GWY_WINDOWING_NONE,
                             GWY_TRANSFORM_DIRECTION_BACKWARD,
                             GWY_INTERPOLATION_BILINEAR, FALSE, FALSE);
        gwy_data_field_2dfft_humanize(score);

        /*TODO compute it and put to score field*/
        g_object_unref(data_in_re);
        g_object_unref(data_out_re);
        g_object_unref(data_out_im);
        g_object_unref(kernel_in_re);
        g_object_unref(kernel_out_re);
        g_object_unref(kernel_out_im);
        break;
    }

    gwy_data_field_invalidate(score);
}