cI = NULL;
/* render u and v change */
- rc = colorize(I, mI, NULL, NULL, 5, 1, 0, 0, feat_names, NULL);
+ rc = colorize(I, mI, NULL, NULL, 5, 10, 0.01, 0, 0, feat_names, NULL);
if (rc < 0) {
printerror("No memory! Use smaller image or add more memory.");
goto error;
set_I_ptr(I, mI, width, height, 0, features, change_alpha, change_bc, &ptr_y, &ptr_u, &ptr_v, &ptr_a, &ptr_r, &ptr_b, &ptr_c, &ptr_m);
/* render u and v change */
- rc = colorize(I, mI, NULL, NULL, 1, 1, 1, 0, feat_names, &col);
+ rc = colorize(I, mI, NULL, NULL, 1, 1, 0.0, 1, 0, feat_names, &col);
if (rc < 0) {
printerror("No memory! Use smaller image or add more memory.");
thread_preview = PREVIEW_OFF;
#ifndef TEST_NO_RENDER
/* colorize component */
if (quick) {
- rc = solve_mg(col->max_depth, col->inner_iter, 1, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz);
+ rc = solve_mg(col->max_depth, col->inner_iter, 1, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz, 0.0);
if (rc < 0)
goto error;
+ } else /*if (col->target_residual_change)*/ {
+ rc = solve_mg(col->max_depth, col->inner_iter, col->outer_iter, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz, col->target_residual_change);
+ if (rc < 0)
+ goto error;
+#if 0
} else {
+ /* original algorithm: handling of outer iteration */
int i;
for (i = 0; i < col->outer_iter; i++) {
- rc = solve_mg(col->max_depth, col->inner_iter, 2, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz);
+ rc = solve_mg(col->max_depth, col->inner_iter, 2, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz, 0.0);
if (rc < 0)
goto error;
- rc = solve_mg((col->max_depth+1) / 2, col->inner_iter, 2, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz);
+ rc = solve_mg((col->max_depth+1) / 2, col->inner_iter, 2, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz, 0.0);
if (rc < 0)
goto error;
- rc = solve_mg(2, col->inner_iter, 2, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz);
+ rc = solve_mg(2, col->inner_iter, 2, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz, 0.0);
if (rc < 0)
goto error;
- rc = solve_mg(1, col->inner_iter, 4, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz);
+ rc = solve_mg(1, col->inner_iter, 4, col->values, col->marks, col->init, col->nb_list, col->flows_xy, col->scalexyz, 0.0);
if (rc < 0)
goto error;
}
+#endif
}
#endif
darrayDestroy(col->init);
}
-int colorize(const darray_t *image, const darray_t *image_mark, const darray_t *flow, const darray_t *flow_i, int inner_iter, int outer_iter, int quick, int scalexyz, char **feat_names, struct colorize **_col)
+int colorize(const darray_t *image, const darray_t *image_mark, const darray_t *flow, const darray_t *flow_i, int inner_iter, int outer_iter, double target_residual_change, int quick, int scalexyz, char **feat_names, struct colorize **_col)
{
struct colorize *col;
int rc = -1;
col->flow_i = flow_i;
col->inner_iter = inner_iter;
col->outer_iter = outer_iter;
+ col->target_residual_change = target_residual_change;
col->scalexyz = scalexyz;
alloc = 1;
}
const darray_t *flow_i;
int inner_iter;
int outer_iter;
+ double target_residual_change;
int scalexyz;
/* internal stuff */
int colorize_solve(struct colorize *col, int quick, char **feat_names);
void colorize_free(struct colorize *col);
-int colorize(const darray_t *image, const darray_t *image_mark, const darray_t *flow, const darray_t *flow_i, int inner_iter, int outer_iter, int quick, int scalexyz, char **feat_names, struct colorize **_col);
+int colorize(const darray_t *image, const darray_t *image_mark, const darray_t *flow, const darray_t *flow_i, int inner_iter, int outer_iter, double target_residual_change, int quick, int scalexyz, char **feat_names, struct colorize **_col);
#endif
#include "multigrid.h"
/* if defined, residual is calculated and loop is aborted, if no improvement
- * is reached. this does not seem to work, so it should be undefined */
-//#define RESIDUAL
+ * is reached or the target resudual change is reached. */
+#define RESIDUAL
/* just process, but do not generate neighbor list and do not solve multigrid */
//#define TEST_NO_RENDER
* before z)!
*
*/
-int solve_mg(int nlevel, int iters, int ncycle, darray_t **values, darray_t **marks, const darray_t *init, unsigned char **nb_list, darray_t **flows, int scalexyz)
+int solve_mg(int nlevel, int iters, int ncycle, darray_t **values, darray_t **marks, const darray_t *init, unsigned char **nb_list, darray_t **flows, int scalexyz, double target_residual_change)
{
#ifdef RESIDUAL
double curr_residual, prev_residual = 10000000000000.0;
for (i = 0; i < iters; i++)
smooth(level, values[level], marks[level], init, nb_list[level]);
#ifdef RESIDUAL
- curr_residual += residual(level, values[level], marks[level], init, nb_list[level]);
+ if (target_residual_change)
+ curr_residual += residual(level, values[level], marks[level], init, nb_list[level]);
#endif
if (level < scalexyz)
rc = restrict(values[level], values[level+1], flows[level]);
/* end if residual raises again */
#ifdef RESIDUAL
- if (prev_residual < curr_residual)
+//printf("residual %.8f (change=%%%.4f)\n", curr_residual, (prev_residual-curr_residual)/prev_residual*100);
+ if (target_residual_change)
+ printf(" %.1f%%", (prev_residual-curr_residual)/prev_residual*100); fflush(stdout);
+ if (target_residual_change && (prev_residual-curr_residual)/prev_residual < target_residual_change)
break;
- curr_residual = prev_residual;
+ prev_residual = curr_residual;
#endif
}
void multiply(const darray_t *array, double factor);
unsigned char *gen_neighbor(int w, int h, int k, const darray_t *flow, const darray_t *flow_i);
void weighten(const darray_t *luminance, unsigned char *neighbors);
-int solve_mg(int nlevel, int iters, int ncycle, darray_t **values, darray_t **marks, const darray_t *init, unsigned char **nb_list, darray_t **flows, int scalexyz);
+int solve_mg(int nlevel, int iters, int ncycle, darray_t **values, darray_t **marks, const darray_t *init, unsigned char **nb_list, darray_t **flows, int scalexyz, double target_residual_change);
#endif
* options
*/
-static int in_itr_num = 5, out_itr_num = 1, quick = 0, optical_flow = 1, bright_contrast = 1, alpha_change = 1;
+static int in_itr_num = 5, out_itr_num = 10, quick = 0, optical_flow = 1, bright_contrast = 1, alpha_change = 1;
+static double target_residual_change = 0.01;
int scale = 1, scalexyz = 999;
static char output_prefix[256] = "";
{"output-prefix", 1, 0, 'O'},
{"in-itr-num", 1, 0, 'i'},
{"out-itr-num", 1, 0, 'o'},
+ {"residual-change", 1, 0, 'r'},
{"quick", 0, 0, 'q'},
{"zscale", 1, 0, 'z'},
{"brightness-contrast", 1, 0, 'b'},
{0, 0, 0, 0},
};
- c = getopt_long(argc, argv, "hd:O:i:o:qz:b:f:s:t:", long_options, &option_index);
+ c = getopt_long(argc, argv, "hd:O:i:o:r:qz:b:f:s:t:", long_options, &option_index);
if (c == -1)
break;
out_itr_num = atoi(optarg);
skip_args += 2;
break;
+ case 'r':
+ target_residual_change = atoi(optarg) / 100.0;
+ skip_args += 2;
+ break;
case 'q':
quick = 1;
skip_args += 1;
printf(" -h --help This help\n");
printf(" -d --depth <bits> Save images with given color bit depth (default=%d)\n", save_depth);
printf(" -O --output-prefix <path>/<prefix> Store result image of a sequence using this prefix\n");
- printf(" -i --in-itr-num <num> Alter inner iterations (weightening count) of colorization algorithm (default=%d)\n", in_itr_num);
- printf(" -o --out-itr-num <num> Alter outer iterations (complete turns) of colorization algorithm (default=%d)\n", out_itr_num);
+ printf(" -i --in-itr-num <num> Alter inner iterations (smoothing count) of colorization algorithm (default=%d)\n", in_itr_num);
+ printf(" -o --out-itr-num <num> Set iterations (fixed turns) of colorization algorithm (default=%d)\n", out_itr_num);
+ printf(" -r --residual-change <percent> Abort iterations if residual has reached minimum change (default=%.0f)\n", target_residual_change*100);
printf(" -q --quick Use quick render, but sufaces may be colorized incomplete\n");
printf(" -z --zscale <levels> How many grids (staring with the finest) should be scaled in z direction to generate the next coarse grid ");
if (scalexyz < 999)
if (test != FLOW_NEXT && test != FLOW_PREV && test != MARKED && test != MASK && test != MASK_COLOR && test != BC_ONLY && test != BC_IMAGE) {
printf("Colorizing %d frames, please wait...\n", k);
- rc = colorize(I, mI, flow, flow_i, in_itr_num, out_itr_num, quick, scalexyz, feat_names, NULL);
+ rc = colorize(I, mI, flow, flow_i, in_itr_num, out_itr_num, target_residual_change, quick, scalexyz, feat_names, NULL);
if (rc < 0) {
if (k > 1)
printf("No memory! Use smaller frames or less frames between key frames or add more memory.");