/*! * recogaDestroy() * * Input: &recoga (<will be set to null before returning>) * Return: void * * Notes: * (1) If a recog has a parent, the parent owns it. To destroy * a recog, it must first be "orphaned". */ void recogaDestroy(L_RECOGA **precoga) { l_int32 i; L_RECOG *recog; L_RECOGA *recoga; PROCNAME("recogaDestroy"); if (precoga == NULL) { L_WARNING("ptr address is null!\n", procName); return; } if ((recoga = *precoga) == NULL) return; rchaDestroy(&recoga->rcha); for (i = 0; i < recoga->n; i++) { if ((recog = recoga->recog[i]) == NULL) { L_ERROR("recog not found for index %d\n", procName, i); continue; } recog->parent = NULL; /* orphan it */ recogDestroy(&recog); } FREE(recoga->recog); FREE(recoga); *precoga = NULL; return; }
/*! * recogReplaceInRecoga() * * Input: &recog1 (old recog, to be destroyed) * recog2 (new recog, to be inserted in place of @recog1) * Return: 0 if OK, 1 on error * * Notes: * (1) This always destroys recog1. * (2) If recog1 belongs to a recoga, this inserts recog2 into * the slot that recog1 previously occupied. */ l_int32 recogReplaceInRecoga(L_RECOG **precog1, L_RECOG *recog2) { l_int32 n, index; L_RECOG *recog1; L_RECOGA *recoga; PROCNAME("recogReplaceInRecoga"); if (!precog1) return ERROR_INT("&recog1 not defined", procName, 1); if (!recog2) return ERROR_INT("recog2 not defined", procName, 1); if ((recog1 = *precog1) == NULL) return ERROR_INT("recog1 not defined", procName, 1); if ((recoga = recogGetParent(recog1)) == NULL) { recogDestroy(precog1); return 0; } n = recogaGetCount(recoga); recogGetIndex(recog1, &index); if (index >= n) { L_ERROR("invalid index %d in recog1; no replacement\n", procName, recog1->index); recogDestroy(precog1); return 1; } recog1->parent = NULL; /* necessary to destroy recog1 */ recogDestroy(precog1); recoga->recog[index] = recog2; recog2->index = index; recog2->parent = recoga; return 0; }
/*! * \brief recogAddAllSamples() * * \param[in] precog addr of recog * \param[in] paa pixaa from previously trained recog * \param[in] debug * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) On error, the input recog is destroyed. * (2) This is used with the serialization routine recogRead(), * where each pixa in the pixaa represents a set of characters * in a different class. Before calling this function, we have * verified that the number of character classes, given by the * setsize field in %recog, equals the number of pixa in the paa. * The character labels for each set are in the sa_text field. * </pre> */ static l_int32 recogAddAllSamples(L_RECOG **precog, PIXAA *paa, l_int32 debug) { char *text; l_int32 i, j, nc, ns; PIX *pix; PIXA *pixa, *pixa1; L_RECOG *recog; PROCNAME("recogAddAllSamples"); if (!precog) return ERROR_INT("&recog not defined", procName, 1); if ((recog = *precog) == NULL) return ERROR_INT("recog not defined", procName, 1); if (!paa) { recogDestroy(&recog); return ERROR_INT("paa not defined", procName, 1); } nc = pixaaGetCount(paa, NULL); for (i = 0; i < nc; i++) { pixa = pixaaGetPixa(paa, i, L_CLONE); ns = pixaGetCount(pixa); text = sarrayGetString(recog->sa_text, i, L_NOCOPY); pixa1 = pixaCreate(ns); pixaaAddPixa(recog->pixaa_u, pixa1, L_INSERT); for (j = 0; j < ns; j++) { pix = pixaGetPix(pixa, j, L_CLONE); if (debug) fprintf(stderr, "pix[%d,%d]: text = %s\n", i, j, text); pixaaAddPix(recog->pixaa_u, i, pix, NULL, L_INSERT); } pixaDestroy(&pixa); } recogTrainingFinished(&recog, 0, -1, -1.0); /* For second parameter, see comment in recogRead() */ if (!recog) return ERROR_INT("bad templates; recog destroyed", procName, 1); return 0; }
PIXA *MakeBootnum2(void) { char *fname; l_int32 i, n, w, h; BOX *box; PIX *pix; PIXA *pixa; L_RECOG *recog; SARRAY *sa; /* Phase 1: generate recog from the digit data */ recog = recogCreate(20, 32, L_USE_ALL, 120, 1); sa = getSortedPathnamesInDirectory("recog/bootnums", "png", 0, 0); n = sarrayGetCount(sa); for (i = 0; i < n; i++) { /* Read each pix: grayscale, multi-character, labelled */ fname = sarrayGetString(sa, i, L_NOCOPY); if ((pix = pixRead(fname)) == NULL) { fprintf(stderr, "Can't read %s\n", fname); continue; } /* Convert to a set of 1 bpp, single character, labelled */ pixGetDimensions(pix, &w, &h, NULL); box = boxCreate(0, 0, w, h); recogTrainLabelled(recog, pix, box, NULL, 1, 0); pixDestroy(&pix); boxDestroy(&box); } recogTrainingFinished(recog, 1); sarrayDestroy(&sa); /* Phase 2: generate pixa consisting of 1 bpp, single character pix */ recogWritePixa("/tmp/lept/recog/digits/bootnum2.pa", recog); pixa = pixaRead("/tmp/lept/recog/digits/bootnum2.pa"); recogDestroy(&recog); return pixa; }
/*! * \brief recogReadStream() * * \param[in] fp file stream * \return recog, or NULL on error */ L_RECOG * recogReadStream(FILE *fp) { l_int32 version, setsize, threshold, scalew, scaleh, linew; l_int32 maxyshift, nc; L_DNA *dna_tochar; PIXAA *paa; L_RECOG *recog; SARRAY *sa_text; PROCNAME("recogReadStream"); if (!fp) return (L_RECOG *)ERROR_PTR("stream not defined", procName, NULL); if (fscanf(fp, "\nRecog Version %d\n", &version) != 1) return (L_RECOG *)ERROR_PTR("not a recog file", procName, NULL); if (version != RECOG_VERSION_NUMBER) return (L_RECOG *)ERROR_PTR("invalid recog version", procName, NULL); if (fscanf(fp, "Size of character set = %d\n", &setsize) != 1) return (L_RECOG *)ERROR_PTR("setsize not read", procName, NULL); if (fscanf(fp, "Binarization threshold = %d\n", &threshold) != 1) return (L_RECOG *)ERROR_PTR("binary thresh not read", procName, NULL); if (fscanf(fp, "Maxyshift = %d\n", &maxyshift) != 1) return (L_RECOG *)ERROR_PTR("maxyshift not read", procName, NULL); if (fscanf(fp, "Scale to width = %d\n", &scalew) != 1) return (L_RECOG *)ERROR_PTR("width not read", procName, NULL); if (fscanf(fp, "Scale to height = %d\n", &scaleh) != 1) return (L_RECOG *)ERROR_PTR("height not read", procName, NULL); if (fscanf(fp, "Normalized line width = %d\n", &linew) != 1) return (L_RECOG *)ERROR_PTR("line width not read", procName, NULL); if ((recog = recogCreate(scalew, scaleh, linew, threshold, maxyshift)) == NULL) return (L_RECOG *)ERROR_PTR("recog not made", procName, NULL); if (fscanf(fp, "\nLabels for character set:\n") != 0) { recogDestroy(&recog); return (L_RECOG *)ERROR_PTR("label intro not read", procName, NULL); } l_dnaDestroy(&recog->dna_tochar); if ((dna_tochar = l_dnaReadStream(fp)) == NULL) { recogDestroy(&recog); return (L_RECOG *)ERROR_PTR("dna_tochar not read", procName, NULL); } recog->dna_tochar = dna_tochar; sarrayDestroy(&recog->sa_text); if ((sa_text = sarrayReadStream(fp)) == NULL) { recogDestroy(&recog); return (L_RECOG *)ERROR_PTR("sa_text not read", procName, NULL); } recog->sa_text = sa_text; if (fscanf(fp, "\nPixaa of all samples in the training set:\n") != 0) { recogDestroy(&recog); return (L_RECOG *)ERROR_PTR("pixaa intro not read", procName, NULL); } if ((paa = pixaaReadStream(fp)) == NULL) { recogDestroy(&recog); return (L_RECOG *)ERROR_PTR("pixaa not read", procName, NULL); } recog->setsize = setsize; nc = pixaaGetCount(paa, NULL); if (nc != setsize) { recogDestroy(&recog); pixaaDestroy(&paa); L_ERROR("(setsize = %d) != (paa count = %d)\n", procName, setsize, nc); return NULL; } recogAddAllSamples(&recog, paa, 0); /* this finishes */ pixaaDestroy(&paa); if (!recog) return (L_RECOG *)ERROR_PTR("bad templates", procName, NULL); return recog; }