static void gwy_data_field_absdiff_line_correct(GwyDataField *dfield) { MedianLineData mldata; gint xres, yres, i, j; gdouble shift, csum, mindiff, maxdiff, x; gdouble *d; yres = gwy_data_field_get_yres(dfield); xres = gwy_data_field_get_xres(dfield); d = gwy_data_field_get_data(dfield); csum = 0.0; mldata.n = xres; for (i = 1; i < yres; i++) { mldata.a = d + xres*(i - 1); mldata.b = d + xres*i; mindiff = G_MAXDOUBLE; maxdiff = -G_MAXDOUBLE; for (j = 0; j < xres; j++) { x = mldata.b[j] - mldata.a[j]; if (x < mindiff) mindiff = x; if (x > maxdiff) maxdiff = x; } shift = find_minima_golden(sum_of_abs_diff, mindiff, maxdiff, &mldata); gwy_data_field_area_add(dfield, 0, i, xres, 1, -shift); csum -= shift; } gwy_data_field_add(dfield, -csum/(xres*yres)); }
static void line_correct_match(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; GwyDataLine *shifts; gint xres, yres, i; gdouble *d, *s; GQuark dquark; g_return_if_fail(run & LINECORR_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_KEY, &dquark, 0); g_return_if_fail(dfield && dquark); gwy_app_undo_qcheckpointv(data, 1, &dquark); yres = gwy_data_field_get_yres(dfield); xres = gwy_data_field_get_xres(dfield); d = gwy_data_field_get_data(dfield); shifts = gwy_data_line_new(yres, 1.0, TRUE); s = gwy_data_line_get_data(shifts); s[0] = 0.0; for (i = 1; i < yres; i++) { s[i] = find_shift(xres, d + i*xres, d + (i - 1)*xres); g_printerr("%d %g\n", i, s[i]); } gwy_data_line_cumulate(shifts); for (i = 1; i < yres; i++) gwy_data_field_area_add(dfield, 0, i, xres, 1, s[i]); gwy_data_field_add(dfield, -s[yres-1]/(xres*yres)); g_object_unref(shifts); gwy_data_field_data_changed(dfield); }
static void line_correct_median(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; GwyDataLine *line, *modi; gint xres, yres, i; GQuark dquark; gdouble median; g_return_if_fail(run & LINECORR_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_KEY, &dquark, 0); g_return_if_fail(dfield && dquark); gwy_app_undo_qcheckpointv(data, 1, &dquark); xres = gwy_data_field_get_xres(dfield); line = gwy_data_line_new(xres, 1.0, FALSE); yres = gwy_data_field_get_yres(dfield); modi = gwy_data_line_new(yres, 1.0, FALSE); for (i = 0; i < yres; i++) { gwy_data_field_get_row(dfield, line, i); median = gwy_math_median(xres, gwy_data_line_get_data(line)); gwy_data_line_set_val(modi, i, median); } median = gwy_data_line_get_median(modi); for (i = 0; i < yres; i++) { gwy_data_field_area_add(dfield, 0, i, xres, 1, median - gwy_data_line_get_val(modi, i)); } g_object_unref(modi); g_object_unref(line); gwy_data_field_data_changed(dfield); }
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); }
static void selection_finished_cb(GwyUnitoolState *state) { GwyContainer *data; GObject *dfield; GwyDataField *mask = NULL; GwyDataViewLayer *layer; ToolControls *controls; GwySIUnit *siunit; gint isel[4]; controls = (ToolControls*)state->user_data; layer = GWY_DATA_VIEW_LAYER(state->layer); data = gwy_data_view_get_data(GWY_DATA_VIEW(layer->parent)); dfield = gwy_container_get_object_by_name(data, "/0/data"); gwy_container_gis_object_by_name(data, "/0/mask", (GObject**)&mask); gwy_unitool_rect_info_table_fill(state, &controls->labels, NULL, isel); switch (controls->mode) { case MASK_EDIT_SET: gwy_app_undo_checkpoint(data, "/0/mask", NULL); if (!mask) { mask = GWY_DATA_FIELD(gwy_serializable_duplicate(dfield)); siunit = GWY_SI_UNIT(gwy_si_unit_new("")); gwy_data_field_set_si_unit_z(mask, siunit); g_object_unref(siunit); gwy_container_set_object_by_name(data, "/0/mask", (GObject*)mask); g_object_unref(mask); } gwy_data_field_fill(mask, 0.0); gwy_data_field_area_fill(mask, isel[0], isel[1], isel[2], isel[3], 1.0); break; case MASK_EDIT_ADD: gwy_app_undo_checkpoint(data, "/0/mask", NULL); if (!mask) { mask = GWY_DATA_FIELD(gwy_serializable_duplicate(dfield)); siunit = GWY_SI_UNIT(gwy_si_unit_new("")); gwy_data_field_set_si_unit_z(mask, siunit); g_object_unref(siunit); gwy_container_set_object_by_name(data, "/0/mask", (GObject*)mask); g_object_unref(mask); gwy_data_field_fill(mask, 0.0); } gwy_data_field_area_fill(mask, isel[0], isel[1], isel[2], isel[3], 1.0); break; case MASK_EDIT_REMOVE: if (mask) { gwy_app_undo_checkpoint(data, "/0/mask", NULL); gwy_data_field_area_fill(mask, isel[0], isel[1], isel[2], isel[3], 0.0); } break; case MASK_EDIT_INTERSECT: if (mask) { gwy_app_undo_checkpoint(data, "/0/mask", NULL); gwy_data_field_clamp(mask, 0.0, 1.0); gwy_data_field_area_add(mask, isel[0], isel[1], isel[2], isel[3], 1.0); gwy_data_field_add(mask, -1.0); gwy_data_field_clamp(mask, 0.0, 1.0); } break; default: break; } gwy_vector_layer_unselect(GWY_VECTOR_LAYER(layer)); gwy_app_data_view_update(layer->parent); }
static void line_correct_match(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; GwyDataLine *shifts; gint xres, yres, i, j; gdouble m, wsum, lambda, x; gdouble *d, *s, *w; const gdouble *a, *b; GQuark dquark; g_return_if_fail(run & LINECORR_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_KEY, &dquark, 0); g_return_if_fail(dfield && dquark); gwy_app_undo_qcheckpointv(data, 1, &dquark); yres = gwy_data_field_get_yres(dfield); xres = gwy_data_field_get_xres(dfield); d = gwy_data_field_get_data(dfield); shifts = gwy_data_line_new(yres, 1.0, TRUE); s = gwy_data_line_get_data(shifts); w = g_new(gdouble, xres-1); for (i = 1; i < yres; i++) { a = d + xres*(i - 1); b = d + xres*i; /* Diffnorm */ wsum = 0.0; for (j = 0; j < xres-1; j++) { x = a[j+1] - a[j] - b[j+1] + b[j]; wsum += fabs(x); } if (wsum == 0) continue; m = wsum/(xres-1); /* Weights */ wsum = 0.0; for (j = 0; j < xres-1; j++) { x = a[j+1] - a[j] - b[j+1] + b[j]; w[j] = exp(-(x*x/(2.0*m))); wsum += w[j]; } /* Correction */ lambda = (a[0] - b[0])*w[0]; for (j = 1; j < xres-1; j++) lambda += (a[j] - b[j])*(w[j-1] + w[j]); lambda += (a[xres-1] - b[xres-1])*w[xres-2]; lambda /= 2.0*wsum; gwy_debug("%g %g %g", m, wsum, lambda); s[i] = lambda; } gwy_data_line_cumulate(shifts); for (i = 1; i < yres; i++) gwy_data_field_area_add(dfield, 0, i, xres, 1, s[i]); gwy_data_field_add(dfield, -s[yres-1]/(xres*yres)); g_object_unref(shifts); g_free(w); gwy_data_field_data_changed(dfield); }