示例#1
0
文件: tip.c 项目: svn2github/gwyddion
static GwyDataField*
i_largefield_to_datafield(gint **field,
                          GwyDataField *ret,
                          GwyDataField *tipfield,
                          gdouble min,
                          gdouble step)
{
    gint col, row;
    gint xnew, ynew;
    gint txr2, tyr2;

    xnew = ret->xres + tipfield->xres;
    ynew = ret->yres + tipfield->yres;
    txr2 = tipfield->xres/2;
    tyr2 = tipfield->yres/2;

    for (col = 0; col < xnew; col++) {
        for (row = 0; row < ynew; row++) {
            if (col >= txr2
                && col < (ret->xres + txr2)
                && row >= tyr2
                && row < (ret->yres + tyr2)) {
                ret->data[col - txr2 + ret->xres*(row - tyr2)]
                    = field[col][row]*step + min;
            }
        }
    }

    gwy_data_field_invalidate(ret);
    return ret;
}
示例#2
0
static void
gfilter_process(GwyDataField *mfield, GFilterArgs *args)
{
    GwyInventory *inventory;
    GrainLogical logical;
    const gdouble *v[NQUANTITIES];
    const guint *grains;
    const RangeRecord *ranges;
    gboolean *keep_grain;
    guint i, k, n, ngrains;

    inventory = gwy_grain_values();
    for (i = 0; i < NQUANTITIES; i++) {
        k = gwy_inventory_get_item_position(inventory,
                                            args->ranges[i].quantity);
        v[i] = g_ptr_array_index(args->valuedata, k);
    }

    ngrains = args->ngrains;
    grains = args->grains;
    logical = args->logical;
    ranges = &args->ranges[0];

    keep_grain = g_new(gboolean, ngrains+1);
    keep_grain[0] = FALSE;
    for (k = 1; k <= ngrains; k++) {
        gboolean is_ok[NQUANTITIES];

        for (i = 0; i < NQUANTITIES; i++) {
             is_ok[i] = check_threshold(v[i][k],
                                        ranges[i].lower,
                                        ranges[i].upper);
        }
        if (logical == GRAIN_LOGICAL_A)
            keep_grain[k] = is_ok[0];
        else if (logical == GRAIN_LOGICAL_A_AND_B)
            keep_grain[k] = is_ok[0] && is_ok[1];
        else if (logical == GRAIN_LOGICAL_A_OR_B)
            keep_grain[k] = is_ok[0] || is_ok[1];
        else if (logical == GRAIN_LOGICAL_A_AND_B_AND_C)
            keep_grain[k] = is_ok[0] && is_ok[1] && is_ok[2];
        else if (logical == GRAIN_LOGICAL_A_OR_B_OR_C)
            keep_grain[k] = is_ok[0] || is_ok[1] || is_ok[2];
        else if (logical == GRAIN_LOGICAL_A_AND_B_OR_C)
            keep_grain[k] = (is_ok[0] && is_ok[1]) || is_ok[2];
        else if (logical == GRAIN_LOGICAL_A_OR_B_AND_C)
            keep_grain[k] = (is_ok[0] || is_ok[1]) && is_ok[2];
        else {
            g_assert_not_reached();
        }
    }

    n = mfield->xres * mfield->yres;
    for (k = 0; k < n; k++)
        mfield->data[k] = keep_grain[grains[k]];
    gwy_data_field_invalidate(mfield);

    g_free(keep_grain);
}
示例#3
0
/**
 * gwy_data_field_correlate_iteration:
 * @state: Correlation iterator.
 *
 * Performs one iteration of correlation.
 *
 * An iterator can be created with gwy_data_field_correlate_init().
 * When iteration ends, either by finishing or being aborted,
 * gwy_data_field_correlate_finalize() must be called to release allocated
 * resources.
 **/
void
gwy_data_field_correlate_iteration(GwyComputationState *cstate)
{
    GwyCorrelationState *state = (GwyCorrelationState*)cstate;
    gint xres, yres, kxres, kyres, k, xoff, yoff;
    gdouble s, davg, drms;

    xres = state->data_field->xres;
    yres = state->data_field->yres;
    kxres = state->kernel_field->xres;
    kyres = state->kernel_field->yres;
    xoff = (kxres - 1)/2;
    yoff = (kyres - 1)/2;

    if (state->cs.state == GWY_COMPUTATION_STATE_INIT) {
        gwy_data_field_fill(state->score, -1);
        state->kavg = gwy_data_field_get_avg(state->kernel_field);
        state->krms = gwy_data_field_get_rms(state->kernel_field);
        state->avg = gwy_data_field_duplicate(state->data_field);
        state->rms = gwy_data_field_duplicate(state->data_field);
        calculate_normalization(state->avg, state->rms, kxres, kyres);
        state->cs.state = GWY_COMPUTATION_STATE_ITERATE;
        state->cs.fraction = 0.0;
        state->i = yoff;
        state->j = xoff;
    }
    else if (state->cs.state == GWY_COMPUTATION_STATE_ITERATE) {
        k = state->i*xres + state->j;
        davg = state->avg->data[k];
        drms = state->rms->data[k];
        if (drms && state->krms) {
            s = gwy_data_field_get_raw_correlation_score(state->data_field,
                                                         state->kernel_field,
                                                         state->j - xoff,
                                                         state->i - yoff,
                                                         0, 0,
                                                         kxres, kyres,
                                                         davg, state->kavg);
            state->score->data[k] = s/(drms*state->krms);
        }
        else
            state->score->data[k] = 0.0;

        state->j++;
        if (state->j + kxres - xoff > xres) {
            state->j = xoff;
            state->i++;
            if (state->i + kyres - yoff > yres)
                state->cs.state = GWY_COMPUTATION_STATE_FINISHED;
        }
        state->cs.fraction += 1.0/((xres - kxres + 1)*(yres - kyres + 1));
        state->cs.fraction = MIN(state->cs.fraction, 1.0);
    }
    else if (state->cs.state == GWY_COMPUTATION_STATE_FINISHED)
        return;

    gwy_data_field_invalidate(state->score);
}
示例#4
0
文件: tip.c 项目: svn2github/gwyddion
static GwyDataField*
field_to_datafield(gdouble **field, GwyDataField *ret)
{
    gint col, row;
    for (col = 0; col < ret->xres; col++) {
        for (row = 0; row < ret->yres; row++) {
            ret->data[col  + ret->xres*row] = field[col][row];
        }
    }

    gwy_data_field_invalidate(ret);
    return ret;
}
示例#5
0
文件: tip.c 项目: svn2github/gwyddion
static GwyDataField*
i_field_to_datafield(gint **field,
                     GwyDataField *ret,
                     gdouble min,
                     gdouble step)
{
    gint col, row;

    for (col = 0; col < ret->xres; col++) {
        for (row = 0; row < ret->yres; row++) {
            ret->data[col + ret->xres*row] = (gdouble)field[col][row]*step
                                             + min;
        }
    }

    gwy_data_field_invalidate(ret);
    return ret;
}
示例#6
0
文件: tip.c 项目: svn2github/gwyddion
static void
create_pyramide(GwyDataField *tip, gdouble alpha, gint n, gdouble theta)
{
    gint col, row;
    gdouble rcol, rrow;
    gdouble scol, srow;
    gdouble ccol, crow;
    gdouble phi, phic;
    gdouble vm, radius;
    gdouble height;
    gdouble nangle;
    gdouble add = G_PI/4;

    if (n == 3)
        add = G_PI/6;

    add += theta;
    radius = sqrt((tip->xres/2)*(tip->xres/2)+(tip->yres/2)*(tip->yres/2));
    nangle = G_PI/n;
    height = gwy_data_field_itor(tip, radius)*cos(nangle)/tan(alpha);

    scol = tip->xres/2;
    srow = tip->yres/2;

    for (col = 0; col < tip->xres; col++) {
        for (row = 0; row < tip->yres; row++) {
            ccol = col - scol;
            crow = row - srow;
            rcol = -ccol*cos(add) + crow*sin(add);
            rrow = ccol*sin(add) + crow*cos(add);
            phi = atan2(rrow, rcol) + G_PI;
            phic = floor(phi/(2*G_PI/n))*2*G_PI/n + G_PI/n;
            vm = rcol*cos(phic) + rrow*sin(phic);
            tip->data[col + tip->xres*row]
                = height*(1 + vm/(radius*cos(G_PI/n)));
        }
    }

    gwy_data_field_invalidate(tip);
}
示例#7
0
文件: tip.c 项目: svn2github/gwyddion
static void
round_pyramide(GwyDataField *tip, gdouble angle, gint n, gdouble ballradius)
{
    gdouble center_x, center_y, center_z;
    gdouble height = gwy_data_field_get_max(tip);
    gint col, row;
    gdouble dcol, drow;
    gdouble sphere, radius;
    gdouble beta, zd;

    radius = sqrt((tip->xres/2)*(tip->xres/2) + (tip->yres/2)*(tip->yres/2));
    beta = atan(gwy_data_field_itor(tip, radius)/height);
    center_x = tip->xreal/2;
    center_y = tip->yreal/2;
    beta = atan(tan(angle)/cos(G_PI/n));
    center_z = height - ballradius/sin(beta);
    gwy_debug("z:%g, height=%g, ballradius=%g, cosbeta=%g, beta=%g "
              "(%g deg of %g deg)\n",
              center_z, height, ballradius, cos(beta), beta,
              beta*180/G_PI, angle*180/G_PI);
    for (row = 0; row < tip->yres; row++) {
        gdouble *datarow = tip->data + tip->xres*row;

        for (col = 0; col < tip->xres; col++) {
            if (datarow[col] > (center_z + ballradius*sin(beta))) {
                dcol = gwy_data_field_itor(tip, col) - center_x;
                drow = gwy_data_field_jtor(tip, row) - center_y;
                sphere = (ballradius*ballradius - dcol*dcol - drow*drow);
                zd = G_LIKELY(sphere >= 0) ? sqrt(sphere) : 0.0;
                datarow[col] = MIN(datarow[col], center_z + zd);
            }
        }
    }

    gwy_data_field_invalidate(tip);
}
示例#8
0
static GwyContainer*
zeiss_load_tiff(const GwyTIFF *tiff, GError **error)
{
    GwyContainer *container = NULL, *meta = NULL;
    GwyDataField *dfield;
    GwySIUnit *siunit;
    GwyTIFFImageReader *reader = NULL;
    GHashTable *hash = NULL;
    gint i, power10;
    gchar *value, *end, *comment = NULL;
    gdouble *data;
    gboolean new_file;
    double factor, dx;

    /* Comment with parameters is common for all data fields */
    if (!gwy_tiff_get_string0(tiff, ZEISS_HEADER_TAG, &comment)) {
        err_FILE_TYPE(error, "Carl Zeiss SEM");
        goto fail;
    }

    if (strstr(comment, MAGIC_COMMENT))
        new_file = TRUE;
    else if (g_str_has_prefix(comment, SOMEWHAT_LESS_MAGIC_COMMENT))
        new_file = FALSE;
    else {
        err_FILE_TYPE(error, "Carl Zeiss SEM");
        goto fail;
    }

    /* Read the comment header. */
    if (new_file) {
        hash = parse_comment(comment);
        if ((value = g_hash_table_lookup(hash, "Image Pixel Size"))) {
            gwy_debug("Using dx from Image Pixel Size: %s", value);
        }
        else if ((value = g_hash_table_lookup(hash, "Pixel Size"))) {
            gwy_debug("Using dx from Pixel Size: %s", value);
        }
        else {
            err_MISSING_FIELD(error, "Pixel Size");
            goto fail;
        }
    }
    else {
        /* The first thing is the pixel size, apparently. */
        value = comment + strlen(SOMEWHAT_LESS_MAGIC_COMMENT);
        gwy_debug("Using dx from old-style comment: %s", value);
    }

    dx = g_ascii_strtod(value, &end);
    /* Use negated positive conditions to catch NaNs */
    if (!((dx = fabs(dx)) > 0)) {
        g_warning("Real pixel size is 0.0, fixing to 1.0");
        dx = 1.0;
    }
    if (!new_file)
        end = "m";

    /* Request a reader, this ensures dimensions and stuff are defined.
     * NB: Newer versions store the image as RGB.  Not useful here; just
     * average the channels.  */
    if (!(reader = gwy_tiff_get_image_reader(tiff, 0, 3, error)))
        goto fail;

    siunit = gwy_si_unit_new_parse(end, &power10);
    factor = pow10(power10);
    dfield = gwy_data_field_new(reader->width, reader->height,
                                reader->width * factor * dx,
                                reader->height * factor * dx,
                                FALSE);
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);

    data = gwy_data_field_get_data(dfield);
    if (reader->samples_per_pixel > 1) {
        gdouble *datarow = g_new(gdouble, reader->width);
        gint ch, j, spp = reader->samples_per_pixel;

        gwy_data_field_clear(dfield);
        for (i = 0; i < reader->height; i++) {
            for (ch = 0; ch < spp; ch++) {
                gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0, datarow);
                for (j = 0; j < reader->width; j++)
                    data[i*reader->width + j] += datarow[j];
            }
        }
        g_free(datarow);
        gwy_data_field_multiply(dfield, 1.0/spp);
        gwy_data_field_invalidate(dfield);
    }
    else {
        for (i = 0; i < reader->height; i++)
            gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0,
                                    data + i*reader->width);
    }

    container = gwy_container_new();
    gwy_container_set_object_by_name(container, "/0/data", dfield);
    g_object_unref(dfield);
    gwy_container_set_string_by_name(container, "/0/data/title",
                                     g_strdup("Secondary electron count"));

    if (new_file) {
        meta = gwy_container_new();
        g_hash_table_foreach(hash, add_meta, meta);
        if (gwy_container_get_n_items(meta))
            gwy_container_set_object_by_name(container, "/0/meta", meta);
        g_object_unref(meta);
    }

fail:
    if (hash)
        g_hash_table_destroy(hash);
    g_free(comment);

    return container;
}
示例#9
0
/**
 * gwy_data_field_crosscorrelate_iteration:
 * @state: Cross-correlation iterator.
 *
 * Performs one iteration of cross-correlation.
 *
 * Cross-correlation matches two different images of the same object under
 * changes.
 *
 * It does not use any special features
 * for matching. It simply searches for all points (with their neighbourhood)
 * of @data_field1 within @data_field2. Parameters @search_width and
 * @search_height determine maimum area where to search for points.
 * The area is cenetered in the @data_field2 at former position of points at
 * @data_field1.
 *
 * A cross-correlation iterator can be created with
 * gwy_data_field_crosscorrelate_init().  When iteration ends, either
 * by finishing or being aborted, gwy_data_field_crosscorrelate_finalize()
 * must be called to release allocated resources.
 **/
void
gwy_data_field_crosscorrelate_iteration(GwyComputationState *cstate)
{
    GwyCrossCorrelationState *state = (GwyCrossCorrelationState*)cstate;
    gint xres, yres, m, n, col, row, colmax, rowmax;
    gdouble cormax, lscore;
    gdouble zm, zp, z0, ipos, jpos;
    

    xres = state->data_field1->xres;
    yres = state->data_field1->yres;

    if (state->cs.state == GWY_COMPUTATION_STATE_INIT) {
        if (state->x_dist)
            gwy_data_field_clear(state->x_dist);
        if (state->y_dist)
            gwy_data_field_clear(state->y_dist);
        if (state->score)
            gwy_data_field_clear(state->score);
        state->cs.state = GWY_COMPUTATION_STATE_ITERATE;
        state->cs.fraction = 0.0;
        state->i = state->search_height/2;
        state->j = state->search_width/2;
    }
    else if (state->cs.state == GWY_COMPUTATION_STATE_ITERATE) {
        /*iterate over search area in the second datafield */
        row = rowmax = state->i;
        col = colmax = state->j;
        cormax = -1.0;
        for (m = row - state->search_height/2; m < (row + state->search_height/2 - state->window_height + 1); m++) {
            for (n = col - state->search_width/2; n < (col + state->search_width/2 - state->window_width + 1); n++) {
                lscore = gwy_data_field_get_correlation_score
                                                (state->data_field1,
                                                 state->data_field2,
                                                 col - state->window_width/2,
                                                 row - state->window_height/2,
                                                 n, m,
                                                 state->window_width,
                                                 state->window_height);

                /* add a little to score at exactly same point
                 * - to prevent problems on flat data */
                if (m == row - state->search_height/2
                    && n == col - state->search_width/2)
                    lscore *= 1.01;

                if (lscore > cormax) {
                    cormax = lscore;
                    colmax = n + state->window_width/2;
                    rowmax = m + state->window_height/2;
                }

            }
        }
        if (state->score)
            state->score->data[col + xres * row] = cormax;
        if (state->x_dist) {
            z0 = zp = zm = cormax;
            zm = gwy_data_field_get_correlation_score(state->data_field1,
                                                      state->data_field2,
                                                      col - state->window_width/2,
                                                      row - state->window_height/2,
                                                      colmax - state->window_width/2 - 1,
                                                      rowmax - state->window_height/2,
                                                      state->window_width,
                                                      state->window_height);
            zp = gwy_data_field_get_correlation_score(state->data_field1,
                                                      state->data_field2,
                                                      col - state->window_width/2,
                                                      row - state->window_height/2,
                                                      colmax - state->window_width/2 + 1,
                                                      rowmax - state->window_height/2,
                                                      state->window_width,
                                                      state->window_height);


            ipos = colmax + (zm - zp)/(zm + zp - 2*z0)/2.0;
            state->x_dist->data[col + xres * row]
                = (ipos - col)*state->data_field1->xreal/state->data_field1->xres;
        }
        if (state->y_dist) {
            z0 = zp = zm = cormax;
            zm = gwy_data_field_get_correlation_score(state->data_field1,
                                                      state->data_field2,
                                                      col - state->window_width/2,
                                                      row - state->window_height/2,
                                                      colmax - state->window_width/2,
                                                      rowmax - state->window_height/2 - 1,
                                                      state->window_width,
                                                      state->window_height);
            zp = gwy_data_field_get_correlation_score(state->data_field1,
                                                      state->data_field2,
                                                      col - state->window_width/2,
                                                      row - state->window_height/2,
                                                      colmax - state->window_width/2,
                                                      rowmax - state->window_height/2 + 1,
                                                      state->window_width,
                                                      state->window_height);


            jpos = rowmax + (zm - zp)/(zm + zp - 2*z0)/2.0;
            state->y_dist->data[col + xres * row]
                = (jpos - row)*state->data_field1->yreal/state->data_field1->yres;
        }
        
        state->j++;
        if (state->j == xres - (state->search_width
                                - state->search_width/2)) {
            state->j = state->search_width/2;
            state->i++;
            if (state->i == yres - (state->search_height
                                    - state->search_height/2)) {
                state->cs.state = GWY_COMPUTATION_STATE_FINISHED;
            }
        }
        state->cs.fraction
            += 1.0/(xres - state->search_width + 1)
                  /(yres - state->search_height + 1);
        state->cs.fraction = MIN(state->cs.fraction, 1.0);
    }
    else if (state->cs.state == GWY_COMPUTATION_STATE_FINISHED)
        return;

    if (state->score)
        gwy_data_field_invalidate(state->score);
    if (state->x_dist)
        gwy_data_field_invalidate(state->x_dist);
    if (state->y_dist)
        gwy_data_field_invalidate(state->y_dist);
}
示例#10
0
/**
 * gwy_data_field_crosscorrelate:
 * @data_field1: A data field.
 * @data_field2: A data field.
 * @x_dist: A data field to store x-distances to.
 * @y_dist: A data field to store y-distances to.
 * @score: Data field to store correlation scores to.
 * @search_width: Search area width.
 * @search_height: Search area height.
 * @window_width: Correlation window width.
 * @window_height: Correlation window height.
 *
 * Algorithm for matching two different images of the same object under changes.
 *
 * It does not use any special features
 * for matching. It simply searches for all points (with their neighbourhood)
 * of @data_field1 within @data_field2. Parameters @search_width and
 * @search_height
 * determine maimum area where to search for points. The area is cenetered
 * in the @data_field2 at former position of points at @data_field1.
 **/
void
gwy_data_field_crosscorrelate(GwyDataField *data_field1,
                              GwyDataField *data_field2, GwyDataField *x_dist,
                              GwyDataField *y_dist, GwyDataField *score,
                              gint search_width, gint search_height,
                              gint window_width,
                              gint window_height)
{
    gint xres, yres, i, j, m, n;
    gint imax, jmax;
    gdouble cormax, lscore;
    gdouble zm, zp, z0, ipos, jpos;

    g_return_if_fail(data_field1 != NULL && data_field2 != NULL);

    xres = data_field1->xres;
    yres = data_field1->yres;

    g_return_if_fail(xres == data_field2->xres && yres == data_field2->yres);

    gwy_data_field_clear(x_dist);
    gwy_data_field_clear(y_dist);
    gwy_data_field_clear(score);

    /*iterate over all the points */
    for (i = (search_width/2); i < (xres - search_height/2); i++) {
        for (j = (search_height/2); j < (yres - search_height/2); j++) {
            /*iterate over search area in the second datafield */
            imax = i;
            jmax = j;
            cormax = -1;
            for (m = (i - search_width); m < i; m++) {
                for (n = (j - search_height); n < j; n++) {
                    lscore =
                        gwy_data_field_get_correlation_score(data_field1,
                                                             data_field2,
                                                             i-search_width/2,
                                                             j-search_height/2,
                                                             m, n,
                                                             m + search_width,
                                                             n + search_height);

                    /* add a little to score at exactly same point
                     * - to prevent problems on flat data */
                    if (m == (i - search_width/2)
                        && n == (j - search_height/2))
                        lscore *= 1.0001;

                    if (cormax < lscore) {
                        cormax = lscore;
                        imax = m + search_width/2;
                        jmax = n + search_height/2;
                    }
                }
            }
            score->data[i + xres * j] = cormax;

            z0 = cormax;
            zm = gwy_data_field_get_correlation_score(data_field1,
                                                      data_field2,
                                                      i-search_width/2,
                                                      j-search_height/2,
                                                      imax - search_width/2 - 1,
                                                      jmax - search_height/2,
                                                      imax + search_width/2 - 1,
                                                      jmax + search_height/2);
            zp = gwy_data_field_get_correlation_score(data_field1,
                                                      data_field2,
                                                      i-search_width/2,
                                                      j-search_height/2,
                                                      imax - search_width/2 + 1,
                                                      jmax - search_height/2,
                                                      imax + search_width/2 + 1,
                                                      jmax + search_height/2);


            ipos = imax + (zm - zp)/(zm + zp - 2*z0)/2.0;
            x_dist->data[i + xres * j]
                = (gdouble)(ipos - i)*data_field1->xreal/data_field1->xres;

            zm = gwy_data_field_get_correlation_score(data_field1,
                                                      data_field2,
                                                      i-search_width/2,
                                                      j-search_height/2,
                                                      imax - search_width/2,
                                                      jmax - search_height/2 - 1,
                                                      imax + search_width/2,
                                                      jmax + search_height/2 - 1);
            zp = gwy_data_field_get_correlation_score(data_field1,
                                                      data_field2,
                                                      i-search_width/2,
                                                      j-search_height/2,
                                                      imax - search_width/2,
                                                      jmax - search_height/2 + 1,
                                                      imax + search_width/2,
                                                      jmax + search_height/2 + 1);


            jpos = jmax + (zm - zp)/(zm + zp - 2*z0)/2.0;
             y_dist->data[i + xres * j]
                = (gdouble)(jpos - j)*data_field1->yreal/data_field1->yres;
        }
    }

    gwy_data_field_invalidate(score);
    gwy_data_field_invalidate(x_dist);
    gwy_data_field_invalidate(y_dist);
}
示例#11
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);
}
示例#12
0
void
gwy_data_field_crosscorrelate_iteration(GwyComputationState *cstate)
{
    GwyCrossCorrelationState *state = (GwyCrossCorrelationState*)cstate;
    gint xres, yres, m, n, k, col, row, colmax, rowmax;
    gdouble cormax, lscore;
    gdouble ipos, jpos, scores[9];
    gdouble xmaximum, ymaximum;
    


    xres = state->data_field1->xres;
    yres = state->data_field1->yres;

    if (state->cs.state == GWY_COMPUTATION_STATE_INIT) {
        if (state->x_dist)
            gwy_data_field_clear(state->x_dist);
        if (state->y_dist)
            gwy_data_field_clear(state->y_dist);
        if (state->score)
            gwy_data_field_clear(state->score);
        state->cs.state = GWY_COMPUTATION_STATE_ITERATE;
        state->cs.fraction = 0.0;
        state->i = state->window_width/2 + 1;
        state->j = state->window_height/2 + 1;

    }
    else if (state->cs.state == GWY_COMPUTATION_STATE_ITERATE) {
        //iterate over search area in the second datafield 
        col = colmax = state->i;
        row = rowmax = state->j;
        cormax = -G_MAXDOUBLE;
        for (m = MAX(0, row - state->search_height/2 - state->window_height/2); m < MIN(yres-state->window_height, (row + state->search_height/2 - state->window_height/2)); m++) {
            for (n = MAX(0, col - state->search_width/2 - state->window_width/2); n < MIN(xres-state->window_width, (col + state->search_width/2 - state->window_width/2)); n++) {


                lscore = gwy_data_field_get_weighted_correlation_score
                                                (state->data_field1,
                                                 state->data_field2,
                                                 state->weights,
                                                 col-state->window_width/2,
                                                 row-state->window_height/2,
                                                 n, 
                                                 m,
                                                 state->window_width,
                                                 state->window_height);
 


                // add a little to score at exactly same point - to prevent problems on flat data 
                if (m == 0 && n == 0) lscore *= 1.0001;

                if (lscore > cormax) {
                    cormax = lscore;
                    colmax = n + state->window_width/2;
                    rowmax = m + state->window_height/2;
                }
      

            }
        }

        if (state->score)
            state->score->data[col + xres * row] = cormax;

        if (state->x_dist || state->x_dist) {
            k = 0;
            for (m=-1; m<=1; m++) {
               for (n=-1; n<=1; n++) {
    
                  if (m==0 && n==0) scores[k++] = cormax;
                  else scores[k++] = gwy_data_field_get_weighted_correlation_score(state->data_field1,
                                                      state->data_field2,
                                                      state->weights,
                                                      col - state->window_width/2,
                                                      row - state->window_height/2,
                                                      colmax - state->window_width/2 + n,
                                                      rowmax - state->window_height/2 + m,
                                                      state->window_width,
                                                      state->window_height);
                  }
            }


            if (gwy_math_refine_maximum(scores, &xmaximum, &ymaximum))
            {
                ipos = colmax + xmaximum;
                jpos = rowmax + ymaximum;
            }
            else {
                ipos = colmax;
                jpos = rowmax;
            }


            state->x_dist->data[col + xres * row]
                = (ipos - col)*state->data_field1->xreal/state->data_field1->xres;

            state->y_dist->data[col + xres * row]
                = (jpos - row)*state->data_field1->yreal/state->data_field1->yres;
        }

        state->i++;
        if (state->i == (xres - state->window_width/2 - 1)) {
            state->i = state->window_width/2 + 1;
            state->j++;
            if (state->j == (yres - state->window_height/2 - 1)) {
                state->cs.state = GWY_COMPUTATION_STATE_FINISHED;
            }
        }
        state->cs.fraction
            += 1.0/(xres - state->window_width - 2)
                  /(yres - state->window_height - 2);
        state->cs.fraction = MIN(state->cs.fraction, 1.0);
    }
    else if (state->cs.state == GWY_COMPUTATION_STATE_FINISHED)
        return;

    if (state->score)
        gwy_data_field_invalidate(state->score);
    if (state->x_dist)
        gwy_data_field_invalidate(state->x_dist);
    if (state->y_dist)
        gwy_data_field_invalidate(state->y_dist);
}