Leptonica  1.82.0
Image processing and image analysis suite
baseline.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
50 #ifdef HAVE_CONFIG_H
51 #include <config_auto.h>
52 #endif /* HAVE_CONFIG_H */
53 
54 #include <math.h>
55 #include "allheaders.h"
56 
57  /* Min to travel after finding max before abandoning peak */
58 static const l_int32 MinDistInPeak = 35;
59 
60  /* Thresholds for peaks and zeros, relative to the max peak */
61 static const l_int32 PeakThresholdRatio = 20;
62 static const l_int32 ZeroThresholdRatio = 100;
63 
64  /* Default values for determining local skew */
65 static const l_int32 DefaultSlices = 10;
66 static const l_int32 DefaultSweepReduction = 2;
67 static const l_int32 DefaultBsReduction = 1;
68 static const l_float32 DefaultSweepRange = 5.; /* degrees */
69 static const l_float32 DefaultSweepDelta = 1.; /* degrees */
70 static const l_float32 DefaultMinbsDelta = 0.01; /* degrees */
71 
72  /* Overlap slice fraction added to top and bottom of each slice */
73 static const l_float32 OverlapFraction = 0.5;
74 
75  /* Minimum allowed confidence (ratio) for accepting a value */
76 static const l_float32 MinAllowedConfidence = 3.0;
77 
78 
79 /*---------------------------------------------------------------------*
80  * Locate text baselines in an image *
81  *---------------------------------------------------------------------*/
116 NUMA *
118  PTA **ppta,
119  PIXA *pixadb)
120 {
121 l_int32 h, i, j, nbox, val1, val2, ndiff, bx, by, bw, bh;
122 l_int32 imaxloc, peakthresh, zerothresh, inpeak;
123 l_int32 mintosearch, max, maxloc, nloc, locval;
124 l_int32 *array;
125 l_float32 maxval;
126 BOXA *boxa1, *boxa2, *boxa3;
127 GPLOT *gplot;
128 NUMA *nasum, *nadiff, *naloc, *naval;
129 PIX *pix1, *pix2;
130 PTA *pta;
131 
132  PROCNAME("pixFindBaselines");
133 
134  if (ppta) *ppta = NULL;
135  if (!pixs || pixGetDepth(pixs) != 1)
136  return (NUMA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
137 
138  /* Close up the text characters, removing noise */
139  pix1 = pixMorphSequence(pixs, "c25.1 + e15.1", 0);
140 
141  /* Estimate the resolution */
142  if (pixadb) pixaAddPix(pixadb, pixScale(pix1, 0.25, 0.25), L_INSERT);
143 
144  /* Save the difference of adjacent row sums.
145  * The high positive-going peaks are the baselines */
146  if ((nasum = pixCountPixelsByRow(pix1, NULL)) == NULL) {
147  pixDestroy(&pix1);
148  return (NUMA *)ERROR_PTR("nasum not made", procName, NULL);
149  }
150  h = pixGetHeight(pixs);
151  nadiff = numaCreate(h);
152  numaGetIValue(nasum, 0, &val2);
153  for (i = 0; i < h - 1; i++) {
154  val1 = val2;
155  numaGetIValue(nasum, i + 1, &val2);
156  numaAddNumber(nadiff, val1 - val2);
157  }
158  numaDestroy(&nasum);
159 
160  if (pixadb) { /* show the difference signal */
161  lept_mkdir("lept/baseline");
162  gplotSimple1(nadiff, GPLOT_PNG, "/tmp/lept/baseline/diff", "Diff Sig");
163  pix2 = pixRead("/tmp/lept/baseline/diff.png");
164  pixaAddPix(pixadb, pix2, L_INSERT);
165  }
166 
167  /* Use the zeroes of the profile to locate each baseline. */
168  array = numaGetIArray(nadiff);
169  ndiff = numaGetCount(nadiff);
170  numaGetMax(nadiff, &maxval, &imaxloc);
171  numaDestroy(&nadiff);
172 
173  /* Use this to begin locating a new peak: */
174  peakthresh = (l_int32)maxval / PeakThresholdRatio;
175  /* Use this to begin a region between peaks: */
176  zerothresh = (l_int32)maxval / ZeroThresholdRatio;
177 
178  naloc = numaCreate(0);
179  naval = numaCreate(0);
180  inpeak = FALSE;
181  for (i = 0; i < ndiff; i++) {
182  if (inpeak == FALSE) {
183  if (array[i] > peakthresh) { /* transition to in-peak */
184  inpeak = TRUE;
185  mintosearch = i + MinDistInPeak; /* accept no zeros
186  * between i and mintosearch */
187  max = array[i];
188  maxloc = i;
189  }
190  } else { /* inpeak == TRUE; look for max */
191  if (array[i] > max) {
192  max = array[i];
193  maxloc = i;
194  mintosearch = i + MinDistInPeak;
195  } else if (i > mintosearch && array[i] <= zerothresh) { /* leave */
196  inpeak = FALSE;
197  numaAddNumber(naval, max);
198  numaAddNumber(naloc, maxloc);
199  }
200  }
201  }
202  LEPT_FREE(array);
203 
204  /* If array[ndiff-1] is max, eg. no descenders, baseline at bottom */
205  if (inpeak) {
206  numaAddNumber(naval, max);
207  numaAddNumber(naloc, maxloc);
208  }
209 
210  if (pixadb) { /* show the raster locations for the peaks */
211  gplot = gplotCreate("/tmp/lept/baseline/loc", GPLOT_PNG, "Peak locs",
212  "rasterline", "height");
213  gplotAddPlot(gplot, naloc, naval, GPLOT_POINTS, "locs");
214  gplotMakeOutput(gplot);
215  gplotDestroy(&gplot);
216  pix2 = pixRead("/tmp/lept/baseline/loc.png");
217  pixaAddPix(pixadb, pix2, L_INSERT);
218  }
219  numaDestroy(&naval);
220 
221  /* Generate an approximate profile of text line width.
222  * First, filter the boxes of text, where there may be
223  * more than one box for a given textline. */
224  pix2 = pixMorphSequence(pix1, "r11 + c20.1 + o30.1 +c1.3", 0);
225  if (pixadb) pixaAddPix(pixadb, pix2, L_COPY);
226  boxa1 = pixConnComp(pix2, NULL, 4);
227  pixDestroy(&pix1);
228  pixDestroy(&pix2);
229  if (boxaGetCount(boxa1) == 0) {
230  numaDestroy(&naloc);
231  boxaDestroy(&boxa1);
232  L_INFO("no components after filtering\n", procName);
233  return NULL;
234  }
235  boxa2 = boxaTransform(boxa1, 0, 0, 4., 4.);
236  boxa3 = boxaSort(boxa2, L_SORT_BY_Y, L_SORT_INCREASING, NULL);
237  boxaDestroy(&boxa1);
238  boxaDestroy(&boxa2);
239 
240  /* Optionally, find the baseline segments */
241  pta = NULL;
242  if (ppta) {
243  pta = ptaCreate(0);
244  *ppta = pta;
245  }
246  if (pta) {
247  nloc = numaGetCount(naloc);
248  nbox = boxaGetCount(boxa3);
249  for (i = 0; i < nbox; i++) {
250  boxaGetBoxGeometry(boxa3, i, &bx, &by, &bw, &bh);
251  for (j = 0; j < nloc; j++) {
252  numaGetIValue(naloc, j, &locval);
253  if (L_ABS(locval - (by + bh)) > 25)
254  continue;
255  ptaAddPt(pta, bx, locval);
256  ptaAddPt(pta, bx + bw, locval);
257  break;
258  }
259  }
260  }
261  boxaDestroy(&boxa3);
262 
263  if (pixadb && pta) { /* display baselines */
264  l_int32 npts, x1, y1, x2, y2;
265  pix1 = pixConvertTo32(pixs);
266  npts = ptaGetCount(pta);
267  for (i = 0; i < npts; i += 2) {
268  ptaGetIPt(pta, i, &x1, &y1);
269  ptaGetIPt(pta, i + 1, &x2, &y2);
270  pixRenderLineArb(pix1, x1, y1, x2, y2, 2, 255, 0, 0);
271  }
272  pixWriteDebug("/tmp/lept/baseline/baselines.png", pix1, IFF_PNG);
273  pixaAddPix(pixadb, pixScale(pix1, 0.25, 0.25), L_INSERT);
274  pixDestroy(&pix1);
275  }
276 
277  return naloc;
278 }
279 
280 
281 /*---------------------------------------------------------------------*
282  * Projective transform to remove local skew *
283  *---------------------------------------------------------------------*/
323 PIX *
325  l_int32 nslices,
326  l_int32 redsweep,
327  l_int32 redsearch,
328  l_float32 sweeprange,
329  l_float32 sweepdelta,
330  l_float32 minbsdelta)
331 {
332 l_int32 ret;
333 PIX *pixd;
334 PTA *ptas, *ptad;
335 
336  PROCNAME("pixDeskewLocal");
337 
338  if (!pixs || pixGetDepth(pixs) != 1)
339  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
340 
341  /* Skew array gives skew angle (deg) as fctn of raster line
342  * where it intersects the LHS of the image */
343  ret = pixGetLocalSkewTransform(pixs, nslices, redsweep, redsearch,
344  sweeprange, sweepdelta, minbsdelta,
345  &ptas, &ptad);
346  if (ret != 0)
347  return (PIX *)ERROR_PTR("transform pts not found", procName, NULL);
348 
349  /* Use a projective transform */
350  pixd = pixProjectiveSampledPta(pixs, ptad, ptas, L_BRING_IN_WHITE);
351 
352  ptaDestroy(&ptas);
353  ptaDestroy(&ptad);
354  return pixd;
355 }
356 
357 
358 /*---------------------------------------------------------------------*
359  * Determine the local skew *
360  *---------------------------------------------------------------------*/
392 l_ok
394  l_int32 nslices,
395  l_int32 redsweep,
396  l_int32 redsearch,
397  l_float32 sweeprange,
398  l_float32 sweepdelta,
399  l_float32 minbsdelta,
400  PTA **pptas,
401  PTA **pptad)
402 {
403 l_int32 w, h, i;
404 l_float32 deg2rad, angr, angd, dely;
405 NUMA *naskew;
406 PTA *ptas, *ptad;
407 
408  PROCNAME("pixGetLocalSkewTransform");
409 
410  if (!pptas || !pptad)
411  return ERROR_INT("&ptas and &ptad not defined", procName, 1);
412  *pptas = *pptad = NULL;
413  if (!pixs || pixGetDepth(pixs) != 1)
414  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
415  if (nslices < 2 || nslices > 20)
416  nslices = DefaultSlices;
417  if (redsweep < 1 || redsweep > 8)
418  redsweep = DefaultSweepReduction;
419  if (redsearch < 1 || redsearch > redsweep)
420  redsearch = DefaultBsReduction;
421  if (sweeprange == 0.0)
422  sweeprange = DefaultSweepRange;
423  if (sweepdelta == 0.0)
424  sweepdelta = DefaultSweepDelta;
425  if (minbsdelta == 0.0)
426  minbsdelta = DefaultMinbsDelta;
427 
428  naskew = pixGetLocalSkewAngles(pixs, nslices, redsweep, redsearch,
429  sweeprange, sweepdelta, minbsdelta,
430  NULL, NULL, 0);
431  if (!naskew)
432  return ERROR_INT("naskew not made", procName, 1);
433 
434  deg2rad = 3.14159265 / 180.;
435  w = pixGetWidth(pixs);
436  h = pixGetHeight(pixs);
437  ptas = ptaCreate(4);
438  ptad = ptaCreate(4);
439  *pptas = ptas;
440  *pptad = ptad;
441 
442  /* Find i for skew line that intersects LHS at i and RHS at h / 20 */
443  for (i = 0; i < h; i++) {
444  numaGetFValue(naskew, i, &angd);
445  angr = angd * deg2rad;
446  dely = w * tan(angr);
447  if (i - dely > 0.05 * h)
448  break;
449  }
450  ptaAddPt(ptas, 0, i);
451  ptaAddPt(ptas, w - 1, i - dely);
452  ptaAddPt(ptad, 0, i);
453  ptaAddPt(ptad, w - 1, i);
454 
455  /* Find i for skew line that intersects LHS at i and RHS at 19h / 20 */
456  for (i = h - 1; i > 0; i--) {
457  numaGetFValue(naskew, i, &angd);
458  angr = angd * deg2rad;
459  dely = w * tan(angr);
460  if (i - dely < 0.95 * h)
461  break;
462  }
463  ptaAddPt(ptas, 0, i);
464  ptaAddPt(ptas, w - 1, i - dely);
465  ptaAddPt(ptad, 0, i);
466  ptaAddPt(ptad, w - 1, i);
467 
468  numaDestroy(&naskew);
469  return 0;
470 }
471 
472 
513 NUMA *
515  l_int32 nslices,
516  l_int32 redsweep,
517  l_int32 redsearch,
518  l_float32 sweeprange,
519  l_float32 sweepdelta,
520  l_float32 minbsdelta,
521  l_float32 *pa,
522  l_float32 *pb,
523  l_int32 debug)
524 {
525 l_int32 w, h, hs, i, ystart, yend, ovlap, npts;
526 l_float32 angle, conf, ycenter, a, b;
527 BOX *box;
528 GPLOT *gplot;
529 NUMA *naskew, *nax, *nay;
530 PIX *pix;
531 PTA *pta;
532 
533  PROCNAME("pixGetLocalSkewAngles");
534 
535  if (!pixs || pixGetDepth(pixs) != 1)
536  return (NUMA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
537  if (nslices < 2 || nslices > 20)
538  nslices = DefaultSlices;
539  if (redsweep < 1 || redsweep > 8)
540  redsweep = DefaultSweepReduction;
541  if (redsearch < 1 || redsearch > redsweep)
542  redsearch = DefaultBsReduction;
543  if (sweeprange == 0.0)
544  sweeprange = DefaultSweepRange;
545  if (sweepdelta == 0.0)
546  sweepdelta = DefaultSweepDelta;
547  if (minbsdelta == 0.0)
548  minbsdelta = DefaultMinbsDelta;
549 
550  pixGetDimensions(pixs, &w, &h, NULL);
551  hs = h / nslices;
552  ovlap = (l_int32)(OverlapFraction * hs);
553  pta = ptaCreate(nslices);
554  for (i = 0; i < nslices; i++) {
555  ystart = L_MAX(0, hs * i - ovlap);
556  yend = L_MIN(h - 1, hs * (i + 1) + ovlap);
557  ycenter = (l_float32)(ystart + yend) / 2;
558  box = boxCreate(0, ystart, w, yend - ystart + 1);
559  pix = pixClipRectangle(pixs, box, NULL);
560  pixFindSkewSweepAndSearch(pix, &angle, &conf, redsweep, redsearch,
561  sweeprange, sweepdelta, minbsdelta);
562  if (conf > MinAllowedConfidence)
563  ptaAddPt(pta, ycenter, angle);
564  pixDestroy(&pix);
565  boxDestroy(&box);
566  }
567 
568  /* Do linear least squares fit */
569  if ((npts = ptaGetCount(pta)) < 2) {
570  ptaDestroy(&pta);
571  return (NUMA *)ERROR_PTR("can't fit skew", procName, NULL);
572  }
573  ptaGetLinearLSF(pta, &a, &b, NULL);
574  if (pa) *pa = a;
575  if (pb) *pb = b;
576 
577  /* Make skew angle array as function of raster line */
578  naskew = numaCreate(h);
579  for (i = 0; i < h; i++) {
580  angle = a * i + b;
581  numaAddNumber(naskew, angle);
582  }
583 
584  if (debug) {
585  lept_mkdir("lept/baseline");
586  ptaGetArrays(pta, &nax, &nay);
587  gplot = gplotCreate("/tmp/lept/baseline/skew", GPLOT_PNG,
588  "skew as fctn of y", "y (in raster lines from top)",
589  "angle (in degrees)");
590  gplotAddPlot(gplot, NULL, naskew, GPLOT_POINTS, "linear lsf");
591  gplotAddPlot(gplot, nax, nay, GPLOT_POINTS, "actual data pts");
592  gplotMakeOutput(gplot);
593  gplotDestroy(&gplot);
594  numaDestroy(&nax);
595  numaDestroy(&nay);
596  }
597 
598  ptaDestroy(&pta);
599  return naskew;
600 }
void gplotDestroy(GPLOT **pgplot)
gplotDestroy()
Definition: gplot.c:255
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
pixCountPixelsByRow()
Definition: pix3.c:2143
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:719
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218
BOXA * boxaSort(BOXA *boxas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex)
boxaSort()
Definition: boxfunc2.c:637
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3332
l_ok pixGetLocalSkewTransform(PIX *pixs, l_int32 nslices, l_int32 redsweep, l_int32 redsearch, l_float32 sweeprange, l_float32 sweepdelta, l_float32 minbsdelta, PTA **pptas, PTA **pptad)
pixGetLocalSkewTransform()
Definition: baseline.c:393
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:343
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok gplotMakeOutput(GPLOT *gplot)
gplotMakeOutput()
Definition: gplot.c:466
GPLOT * gplotCreate(const char *rootname, l_int32 outformat, const char *title, const char *xlabel, const char *ylabel)
gplotCreate()
Definition: gplot.c:187
Definition: pix.h:712
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
l_ok ptaGetArrays(PTA *pta, NUMA **pnax, NUMA **pnay)
ptaGetArrays()
Definition: ptabasic.c:639
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:527
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
PIX * pixDeskewLocal(PIX *pixs, l_int32 nslices, l_int32 redsweep, l_int32 redsearch, l_float32 sweeprange, l_float32 sweepdelta, l_float32 minbsdelta)
pixDeskewLocal()
Definition: baseline.c:324
l_ok ptaGetLinearLSF(PTA *pta, l_float32 *pa, l_float32 *pb, NUMA **pnafit)
ptaGetLinearLSF()
Definition: ptafunc1.c:1106
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
Definition: pix.h:491
l_ok pixRenderLineArb(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderLineArb()
Definition: graphics.c:1536
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:847
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:151
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
Definition: array.h:70
BOXA * boxaTransform(BOXA *boxas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
boxaTransform()
Definition: boxfunc2.c:102
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:879
PIX * pixMorphSequence(PIX *pixs, const char *sequence, l_int32 dispsep)
pixMorphSequence()
Definition: morphseq.c:137
Definition: gplot.h:76
l_ok gplotAddPlot(GPLOT *gplot, NUMA *nax, NUMA *nay, l_int32 plotstyle, const char *plotlabel)
gplotAddPlot()
Definition: gplot.c:320
NUMA * pixFindBaselines(PIX *pixs, PTA **ppta, PIXA *pixadb)
pixFindBaselines()
Definition: baseline.c:117
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
Definition: pix.h:711
Definition: pix.h:455
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:193
NUMA * pixGetLocalSkewAngles(PIX *pixs, l_int32 nslices, l_int32 redsweep, l_int32 redsearch, l_float32 sweeprange, l_float32 sweepdelta, l_float32 minbsdelta, l_float32 *pa, l_float32 *pb, l_int32 debug)
pixGetLocalSkewAngles()
Definition: baseline.c:514
Definition: pix.h:138
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
l_ok pixFindSkewSweepAndSearch(PIX *pixs, l_float32 *pangle, l_float32 *pconf, l_int32 redsweep, l_int32 redsearch, l_float32 sweeprange, l_float32 sweepdelta, l_float32 minbsdelta)
pixFindSkewSweepAndSearch()
Definition: skew.c:563
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:578
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:496
PIX * pixProjectiveSampledPta(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor)
pixProjectiveSampledPta()
Definition: projective.c:144
Definition: pix.h:480
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
l_ok gplotSimple1(NUMA *na, l_int32 outformat, const char *outroot, const char *title)
gplotSimple1()
Definition: gplot.c:665
Definition: pix.h:516