⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 li_recognizer.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
		       (next_reg->end - next_reg->start) < LP_FILTER_MIN;
		     next_reg = curr_reg->next) {
		    /* next_reg must not be plain, and it must be followed by a plain */
		    /* assert(next_reg->type != RGN_PLAIN); */
		    /* assert(next_reg->next != NULL && (next_reg->next)->type == RGN_PLAIN); */

		    curr_reg->next = (next_reg->next)->next;
		    curr_reg->end = (next_reg->next)->end;

		    free(next_reg->next);
		    free(next_reg);
		}
	    }

	/* Add-in pseudo-extremes. */
	{
	    region_list *tmp, *prev_reg;

	    tmp = regions;
	    regions = NULL;
	    prev_reg = NULL;
	    for (curr_reg = tmp; curr_reg; curr_reg = curr_reg->next) {
		if (curr_reg->type == RGN_PLAIN) {
		    int arclen = lialg_compute_pathlen_subset(pts,
								curr_reg->start,
								curr_reg->end);
		    int dx = pts->pts[curr_reg->end].x -
		      pts->pts[curr_reg->start].x;
		    int dy = pts->pts[curr_reg->end].y -
		      pts->pts[curr_reg->start].y;
		    int chordlen = isqrt(10000 * (dx * dx + dy * dy));
		    int atcr = (chordlen == 0) ? 0 : (100 * arclen + chordlen / 2) / chordlen;

		    if (lidebug)
			fprintf(stderr, "%d, %d, %d\n", arclen, chordlen, atcr);

		    /* Split region if necessary. */
		    if (arclen >= PE_AL_THLD && atcr >= PE_ATCR_THLD) {
			int mid = curr_reg->start + (curr_reg->end - curr_reg->start) / 2;
			int end = curr_reg->end;
			region_list *saved_next = curr_reg->next;

			curr_reg->end = mid - 1;
			if (prev_reg == NULL)
			    regions = curr_reg;
			else
			    prev_reg->next = curr_reg;
			prev_reg = curr_reg;

			/* curr_reg = (region_list *)safe_malloc(sizeof(region_list));*/
			curr_reg = allocate(1, region_list);
			curr_reg->start = mid;
			curr_reg->end = mid;
			curr_reg->type = RGN_PSEUDO;
			curr_reg->next = NULL;
			prev_reg->next = curr_reg;
			prev_reg = curr_reg;

			/* curr_reg = (region_list *)safe_malloc(sizeof(region_list)); */
			curr_reg = allocate(1, region_list);
			curr_reg->start = mid + 1;
			curr_reg->end = end;
			curr_reg->type = RGN_PLAIN;
			curr_reg->next = NULL;
			prev_reg->next = curr_reg;
			prev_reg = curr_reg;

			curr_reg->next = saved_next;
			continue;
		    }
		}

		if (prev_reg == NULL)
		    regions = curr_reg;
		else
		    prev_reg->next = curr_reg;
		prev_reg = curr_reg;
	    }
	}
    }

    free(junk);
    return(regions);
}


static point_list *lialg_compute_dompts(point_list *pts, region_list *regions) {
    point_list *dpts = NULL;
    int ndpts;
    int *cas = NULL;
    int nonplain;
    region_list *r;

    /* Compute contour angle set. */
    cas = lialg_compute_contour_angle_set(pts, regions);
/*    assert(cas != NULL);*/

    /* Dominant points include:  start_pt, end_pt, extrema_of_non_plain_regions, midpts of the preceding. */
    nonplain = 0;
    for (r = regions; r != NULL; r = r->next)
	if (r->type != RGN_PLAIN) nonplain++;
    ndpts = 2 * (2 + nonplain) - 1;
    /* dpts = (point_list *)safe_malloc(sizeof(point_list)); */
    dpts = allocate(1, point_list);
    dpts->pts = make_pen_point_array(ndpts);
    if (dpts->pts == NULL) {
	free(dpts);
	return(NULL);
    }
    dpts->npts = ndpts;
    dpts->next = NULL;

    /* Pick out dominant points. */
    {
	region_list *curr;
	int dp;
	int previx;
	int currix;

	/* Record start point. */
	dp = 0;
	previx = 0;
	dpts->pts[dp++] = pts->pts[previx];

	for (curr = regions; curr != NULL; curr = curr->next)
	    if (curr->type != RGN_PLAIN) {
		int max_v = 0;
		int min_v = MAXINT;
		int max_ix = -1;
		int min_ix = -1;
		int i;

		for (i = curr->start; i <= curr->end; i++) {
		    int v = cas[i];
		    if (v > max_v) { max_v = v; max_ix = i; }
		    if (v < min_v) { min_v = v; min_ix = i; }
		    if (lidebug > 1)
			fprintf(stderr, "  %d\n", v);
		}

		currix = (curr->type == RGN_CONVEX ? max_ix : min_ix);

		/* Record midpoint. */
		dpts->pts[dp++] = pts->pts[previx + (currix - previx) / 2];

		/* Record extreme point. */
		dpts->pts[dp++] = pts->pts[currix];

		previx = currix;
	    }

	/* Record last mid-point and end point. */
	currix = pts->npts - 1;
	dpts->pts[dp++] = pts->pts[previx + (currix - previx) / 2];
	dpts->pts[dp++] = pts->pts[currix];
    }

    /* Compute chain-code. */
    lialg_compute_chain_code(dpts);

    free(cas);
    return(dpts);
}


static int *lialg_compute_contour_angle_set(point_list *pts,
					       region_list *regions) {
    int *V = NULL;
    region_list *curr_reg, *prev_reg;
    int i;

    /*    V = (int *)safe_malloc(pts->npts * sizeof(int));*/
    V = allocate(pts->npts, int);

    V[0] = 18000;
    for (curr_reg = regions; curr_reg != NULL;
	    prev_reg = curr_reg, curr_reg = curr_reg->next) {
	for (i = curr_reg->start; i <= curr_reg->end; i++) {
	    if (curr_reg->type == RGN_PLAIN) {
		V[i] = 18000;
	    }
	    else {
#ifdef	notdef
		/* XXX - eliminate floating point */
		region_list *next_reg = curr_reg->next;
		int b = curr_reg->start;
		int h = prev_reg->start;
		int t = next_reg->end;
		int pts_before = i - h;
		int pts_after = t - i;
		int min_pts = (pts_before < pts_after)
		  ? pts_before
		  : pts_after;
		int k = (min_pts < T_ONE)
		  ? T_ONE
		  : (min_pts > T_TWO)
		  ? T_TWO
		  : min_pts;
		float sum = 0.0;

		for (j = 1; j <= k; j++) {
		    int ptA = i - j;
		    int ptB = i + j - 1;
		    int d_A = pts->pts[ptA].chaincode;
		    int d_B = pts->pts[ptB].chaincode;
		    int a_i;

		    if (d_A < d_B)
			d_A += 8;

		    a_i = (d_A - d_B) % 8;

		    /* convert to radians */
		    if (a_i == 4 && curr_reg->type == RGN_CONVEX)
			sum += M_2_PI;
		    else
			sum += (float)((12 - a_i) % 8) / 4.0 * M_PI;
		}
		V[i] = sum / (float)k;
#else
		/* For now, simply choose the mid-point. */
		int isMidPt = (i == (curr_reg->start +
				     (curr_reg->end - curr_reg->start) / 2));
		V[i] = (curr_reg->type == RGN_CONVEX)
		  ? (isMidPt ? 18000 : 0)
		  : (isMidPt ? 0 : 18000);
#endif
	    }
	}
    }
    V[pts->npts - 1] = 18000;

    return(V);
}


/*
 *  First compute the similarity between the two strings.
 *  If it's above a threshold, compute the distance between
 *  the two and return it as the ``score.''
 *  Otherwise, return the constant WORST_SCORE.
 *
 */
static void lialg_score_stroke(point_list *input_dompts, point_list *curr_dompts, int *sim, int *dist) {
    *sim = MIN_SIM;
    *dist = MAX_DIST;

    *sim = lialg_compute_similarity(input_dompts, curr_dompts);
    if (*sim < SIM_THLD) goto done;

    *dist = lialg_compute_distance(input_dompts, curr_dompts);

done:
    if (lidebug)
	fprintf(stderr, "%d, %d\n", *sim, *dist);
}


static int lialg_compute_similarity(point_list *input_dompts,
				     point_list *curr_dompts) {
    int sim = 0;
    point_list *A, *B;
    int N, M;
    int **G = NULL;
    int *junk = NULL;
    int i, j;

    /* A is the	longer sequence, length	N. */
    /* B is the shorter sequence, length M. */
    if (input_dompts->npts >= curr_dompts->npts) {
	A = input_dompts;
	N = input_dompts->npts;
	B = curr_dompts;
	M = curr_dompts->npts;
    }
    else {
	A = curr_dompts;
	N = curr_dompts->npts;
	B = input_dompts;
	M = input_dompts->npts;
    }

    /* Allocate and initialize the Gain matrix, G. */
    /* The size of G is M x (N + 1). */
    /* Note that row 0 is unused. */
    /* Similarities are x 10. */
    {
        /*	G = (int **)safe_malloc(M * sizeof(int *));*/
        G = allocate(M, int *);
        /*	junk = (int *)safe_malloc(M * (N + 1) * sizeof(int)); */
	junk = allocate(M * (N + 1), int);
	for (i = 0; i < M; i++)
	    G[i] = junk + (i * (N + 1));

	for (i = 1; i < M; i++) {
	    int bval = B->pts[i-1].chaincode;

	    /* Source column. */
	    G[i][0] = 0;

	    for (j = 1; j < N; j++) {
		int aval = A->pts[j-1].chaincode;
		int diff = abs(bval - aval);
		if (diff > 4) diff = 8 - diff;

		G[i][j] = (diff == 0)
		  ? 10
		  : (diff == 1)
		  ? 6
		  : 0;
	    }

	    /* Sink column. */
	    G[i][N] = 0;
	}
    }

    /* Do the DP algorithm. */
    /* Proceed in column order, from highest column to the lowest. */
    /* Within each column, proceed from the highest row to the lowest. */
    /* Skip the highest column. */
    {
	for (j = N - 1; j >= 0; j--)
	    for (i = M - 1; i > 0; i--) {
		int max = G[i][j + 1];

		if (i < (M - 1)) {
		    int tmp = G[i + 1][j + 1];
		    if (tmp > max) max = tmp;
		}

		G[i][j] += max;
	    }

	sim = (10 * G[1][0] + (N - 1) / 2) / (N - 1);
    }

    if (G != NULL) free(G);
    if (junk != NULL) free(junk);
    return(sim);
}


static int lialg_compute_distance(point_list *input_dompts,
				   point_list *curr_dompts) {
    int dist = MAX_DIST;
    point_list *A, *B;
    int N, M;
    int **C = NULL;
    int *junk = NULL;
    int *BE = NULL;
    int *TE = NULL;
    int i, j;

    /* A is the	longer sequence, length	N. */
    /* B is the shorter sequence, length M. */
    if (input_dompts->npts >= curr_dompts->npts) {
	A = input_dompts;
	N = input_dompts->npts;
	B = curr_dompts;
	M = curr_dompts->npts;
    }
    else {
	A = curr_dompts;
	N = curr_dompts->npts;
	B = input_dompts;
	M = input_dompts->npts;
    }

    /* Construct the helper vectors, BE and TE, which say for each column */
    /* what are the ``bottom'' and ``top'' rows of interest. */
    {
        /*	BE = (int *)safe_malloc((N + 1) * sizeof(int));*/
	BE = allocate((N + 1), int);
	/*	TE = (int *)safe_malloc((N + 1) * sizeof(int)); */
	TE = allocate((N + 1), int);

	for (j = 1; j <= N; j++) {
	    int bot, top;

	    bot = j + (M - DP_BAND);
	    if (bot > M) bot = M;
	    BE[j] = bot;

	    top = j - (N - DP_BAND);
	    if (top < 1) top = 1;
	    TE[j] = top;
	}
    }

    /* Allocate and initialize the Cost matrix, C. */
    /* The size of C is (M + 1) x (N + 1). */
    /* Note that row and column 0 are unused. */
    /* Costs are x 100. */
    {
        /*	C = (int **)safe_malloc((M + 1) * sizeof(int *)); */
	C = allocate((M + 1), int *);
	/*	junk = (int *)safe_malloc((M + 1) * (N + 1) * sizeof(int)); */
	junk = allocate((M + 1) * (N + 1), int);
	for (i = 0; i <= M; i++)
	    C[i] = junk + (i * (N + 1));

	for (i = 1; i <= M; i++) {
	    int bx = B->pts[i-1].x;
	    int by = B->pts[i-1].y;

	    for (j = 1; j <= N; j++) {
		int ax = A->pts[j-1].x;
		int ay = A->pts[j-1].y;
		int dx = bx - ax;
		int dy = by - ay;
		int dist = isqrt(10000 * (dx * dx + dy * dy));

		C[i][j] = dist;
	    }
	}
    }

    /* Do the DP algorithm. */
    /* Proceed in column order, from highest column to the lowest. */
    /* Within each column, proceed from the highest row to the lowest. */
    {
	for (j = N; j > 0; j--)
	    for (i = M; i > 0; i--) {
		int min = MAX_DIST;

		if (i > BE[j] || i < TE[j] || (j == N && i == M))
		    continue;

		if (j < N) {
		    if (i >= TE[j+1]) {
			int tmp = C[i][j+1];
			if (tmp < min) min = tmp;
		    }

		    if (i < M) {
			int tmp = C[i+1][j+1];
			if (tmp < min) min = tmp;
		    }
		}

		if (i < BE[j]) {
		    int tmp = C[i+1][j];
		    if (tmp < min) min = tmp;
		}

		C[i][j] += min;
	    }

	dist = (C[1][1] + N / 2) / N;
    }

    if (C != NULL) free(C);
    if (junk != NULL) free(junk);
    if (BE != NULL) free(BE);
    if (TE != NULL) free(TE);
    return(dist);
}


/*************************************************************

  Digest-processing routines

 *************************************************************/

static int lialg_read_classifier_digest(rClassifier *rec) {
    int nclasses;
    FILE *fp = NULL;

    /* Try to open the corresponding digest file. */
    {
	char *clx_path;
	char *dot;

	/* Get a copy of the filename, with some room on the end. */
	/*	clx_path = safe_malloc(strlen(rec->file_name) + 5); */
	clx_path = allocate(strlen(rec->file_name) + 5, char);
	strcpy(clx_path, rec->file_name);

	/* Truncate the path after the last dot. */
	dot = strrchr(clx_path, '.');
	if (dot == NULL) { free(clx_path); return(-1); }
	*(dot + 1) = 0;

	/* Append the classifier-digest extension. */
	strcat(clx_path, "clx");

	fp = fopen(clx_path, "r");
	if (fp == NULL) { free(clx_path); return(-1); }

	free(clx_path);
    }

    /* Read-in the name and dominant points for each class. */
    for (nclasses = 0; !feof(fp); nclasses++) {
	point_list *dpts = NULL;
	char class[BUFSIZ];
	int npts;
	int j;

	if (fscanf(fp, "%s %d", class, &npts) != 2) {
	    if (feof(fp)) break;

	    goto failed;
	}
	rec->cnames[nclasses] = strdup(class);

	/* Allocate a dominant-points list. */
	/* dpts = (point_list *)safe_malloc(sizeof(point_list)); */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -