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; }
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); }
/** * 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); }
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; }
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; }
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); }
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); }
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; }
/** * 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); }
/** * 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); }
/** * 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); }
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); }