Leptonica  1.77.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 #include <math.h>
51 #include "allheaders.h"
52 
53  /* Min to travel after finding max before abandoning peak */
54 static const l_int32 MIN_DIST_IN_PEAK = 35;
55 
56  /* Thresholds for peaks and zeros, relative to the max peak */
57 static const l_int32 PEAK_THRESHOLD_RATIO = 20;
58 static const l_int32 ZERO_THRESHOLD_RATIO = 100;
59 
60  /* Default values for determining local skew */
61 static const l_int32 DEFAULT_SLICES = 10;
62 static const l_int32 DEFAULT_SWEEP_REDUCTION = 2;
63 static const l_int32 DEFAULT_BS_REDUCTION = 1;
64 static const l_float32 DEFAULT_SWEEP_RANGE = 5.; /* degrees */
65 static const l_float32 DEFAULT_SWEEP_DELTA = 1.; /* degrees */
66 static const l_float32 DEFAULT_MINBS_DELTA = 0.01; /* degrees */
67 
68  /* Overlap slice fraction added to top and bottom of each slice */
69 static const l_float32 OVERLAP_FRACTION = 0.5;
70 
71  /* Minimum allowed confidence (ratio) for accepting a value */
72 static const l_float32 MIN_ALLOWED_CONFIDENCE = 3.0;
73 
74 
75 /*---------------------------------------------------------------------*
76  * Locate text baselines in an image *
77  *---------------------------------------------------------------------*/
112 NUMA *
114  PTA **ppta,
115  PIXA *pixadb)
116 {
117 l_int32 h, i, j, nbox, val1, val2, ndiff, bx, by, bw, bh;
118 l_int32 imaxloc, peakthresh, zerothresh, inpeak;
119 l_int32 mintosearch, max, maxloc, nloc, locval;
120 l_int32 *array;
121 l_float32 maxval;
122 BOXA *boxa1, *boxa2, *boxa3;
123 GPLOT *gplot;
124 NUMA *nasum, *nadiff, *naloc, *naval;
125 PIX *pix1, *pix2;
126 PTA *pta;
127 
128  PROCNAME("pixFindBaselines");
129 
130  if (ppta) *ppta = NULL;
131  if (!pixs || pixGetDepth(pixs) != 1)
132  return (NUMA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
133 
134  /* Close up the text characters, removing noise */
135  pix1 = pixMorphSequence(pixs, "c25.1 + e15.1", 0);
136 
137  /* Estimate the resolution */
138  if (pixadb) pixaAddPix(pixadb, pixScale(pix1, 0.25, 0.25), L_INSERT);
139 
140  /* Save the difference of adjacent row sums.
141  * The high positive-going peaks are the baselines */
142  if ((nasum = pixCountPixelsByRow(pix1, NULL)) == NULL) {
143  pixDestroy(&pix1);
144  return (NUMA *)ERROR_PTR("nasum not made", procName, NULL);
145  }
146  h = pixGetHeight(pixs);
147  nadiff = numaCreate(h);
148  numaGetIValue(nasum, 0, &val2);
149  for (i = 0; i < h - 1; i++) {
150  val1 = val2;
151  numaGetIValue(nasum, i + 1, &val2);
152  numaAddNumber(nadiff, val1 - val2);
153  }
154  numaDestroy(&nasum);
155 
156  if (pixadb) { /* show the difference signal */
157  lept_mkdir("lept/baseline");
158  gplotSimple1(nadiff, GPLOT_PNG, "/tmp/lept/baseline/diff", "Diff Sig");
159  pix2 = pixRead("/tmp/lept/baseline/diff.png");
160  pixaAddPix(pixadb, pix2, L_INSERT);
161  }
162 
163  /* Use the zeroes of the profile to locate each baseline. */
164  array = numaGetIArray(nadiff);
165  ndiff = numaGetCount(nadiff);
166  numaGetMax(nadiff, &maxval, &imaxloc);
167  numaDestroy(&nadiff);
168 
169  /* Use this to begin locating a new peak: */
170  peakthresh = (l_int32)maxval / PEAK_THRESHOLD_RATIO;
171  /* Use this to begin a region between peaks: */
172  zerothresh = (l_int32)maxval / ZERO_THRESHOLD_RATIO;
173 
174  naloc = numaCreate(0);
175  naval = numaCreate(0);
176  inpeak = FALSE;
177  for (i = 0; i < ndiff; i++) {
178  if (inpeak == FALSE) {
179  if (array[i] > peakthresh) { /* transition to in-peak */
180  inpeak = TRUE;
181  mintosearch = i + MIN_DIST_IN_PEAK; /* accept no zeros
182  * between i and mintosearch */
183  max = array[i];
184  maxloc = i;
185  }
186  } else { /* inpeak == TRUE; look for max */
187  if (array[i] > max) {
188  max = array[i];
189  maxloc = i;
190  mintosearch = i + MIN_DIST_IN_PEAK;
191  } else if (i > mintosearch && array[i] <= zerothresh) { /* leave */
192  inpeak = FALSE;
193  numaAddNumber(naval, max);
194  numaAddNumber(naloc, maxloc);
195  }
196  }
197  }
198  LEPT_FREE(array);
199 
200  /* If array[ndiff-1] is max, eg. no descenders, baseline at bottom */
201  if (inpeak) {
202  numaAddNumber(naval, max);
203  numaAddNumber(naloc, maxloc);
204  }
205 
206  if (pixadb) { /* show the raster locations for the peaks */
207  gplot = gplotCreate("/tmp/lept/baseline/loc", GPLOT_PNG, "Peak locs",
208  "rasterline", "height");
209  gplotAddPlot(gplot, naloc, naval, GPLOT_POINTS, "locs");
210  gplotMakeOutput(gplot);
211  gplotDestroy(&gplot);
212  pix2 = pixRead("/tmp/lept/baseline/loc.png");
213  pixaAddPix(pixadb, pix2, L_INSERT);
214  }
215  numaDestroy(&naval);
216 
217  /* Generate an approximate profile of text line width.
218  * First, filter the boxes of text, where there may be
219  * more than one box for a given textline. */
220  pix2 = pixMorphSequence(pix1, "r11 + c20.1 + o30.1 +c1.3", 0);
221  if (pixadb) pixaAddPix(pixadb, pix2, L_COPY);
222  boxa1 = pixConnComp(pix2, NULL, 4);
223  pixDestroy(&pix1);
224  pixDestroy(&pix2);
225  if (boxaGetCount(boxa1) == 0) {
226  numaDestroy(&naloc);
227  boxaDestroy(&boxa1);
228  L_INFO("no compnents after filtering\n", procName);
229  return NULL;
230  }
231  boxa2 = boxaTransform(boxa1, 0, 0, 4., 4.);
232  boxa3 = boxaSort(boxa2, L_SORT_BY_Y, L_SORT_INCREASING, NULL);
233  boxaDestroy(&boxa1);
234  boxaDestroy(&boxa2);
235 
236  /* Optionally, find the baseline segments */
237  pta = NULL;
238  if (ppta) {
239  pta = ptaCreate(0);
240  *ppta = pta;
241  }
242  if (pta) {
243  nloc = numaGetCount(naloc);
244  nbox = boxaGetCount(boxa3);
245  for (i = 0; i < nbox; i++) {
246  boxaGetBoxGeometry(boxa3, i, &bx, &by, &bw, &bh);
247  for (j = 0; j < nloc; j++) {
248  numaGetIValue(naloc, j, &locval);
249  if (L_ABS(locval - (by + bh)) > 25)
250  continue;
251  ptaAddPt(pta, bx, locval);
252  ptaAddPt(pta, bx + bw, locval);
253  break;
254  }
255  }
256  }
257  boxaDestroy(&boxa3);
258 
259  if (pixadb && pta) { /* display baselines */
260  l_int32 npts, x1, y1, x2, y2;
261  pix1 = pixConvertTo32(pixs);
262  npts = ptaGetCount(pta);
263  for (i = 0; i < npts; i += 2) {
264  ptaGetIPt(pta, i, &x1, &y1);
265  ptaGetIPt(pta, i + 1, &x2, &y2);
266  pixRenderLineArb(pix1, x1, y1, x2, y2, 2, 255, 0, 0);
267  }
268  pixWriteDebug("/tmp/lept/baseline/baselines.png", pix1, IFF_PNG);
269  pixaAddPix(pixadb, pixScale(pix1, 0.25, 0.25), L_INSERT);
270  pixDestroy(&pix1);
271  }
272 
273  return naloc;
274 }
275 
276 
277 /*---------------------------------------------------------------------*
278  * Projective transform to remove local skew *
279  *---------------------------------------------------------------------*/
319 PIX *
321  l_int32 nslices,
322  l_int32 redsweep,
323  l_int32 redsearch,
324  l_float32 sweeprange,
325  l_float32 sweepdelta,
326  l_float32 minbsdelta)
327 {
328 l_int32 ret;
329 PIX *pixd;
330 PTA *ptas, *ptad;
331 
332  PROCNAME("pixDeskewLocal");
333 
334  if (!pixs || pixGetDepth(pixs) != 1)
335  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
336 
337  /* Skew array gives skew angle (deg) as fctn of raster line
338  * where it intersects the LHS of the image */
339  ret = pixGetLocalSkewTransform(pixs, nslices, redsweep, redsearch,
340  sweeprange, sweepdelta, minbsdelta,
341  &ptas, &ptad);
342  if (ret != 0)
343  return (PIX *)ERROR_PTR("transform pts not found", procName, NULL);
344 
345  /* Use a projective transform */
346  pixd = pixProjectiveSampledPta(pixs, ptad, ptas, L_BRING_IN_WHITE);
347 
348  ptaDestroy(&ptas);
349  ptaDestroy(&ptad);
350  return pixd;
351 }
352 
353 
354 /*---------------------------------------------------------------------*
355  * Determine the local skew *
356  *---------------------------------------------------------------------*/
387 l_ok
389  l_int32 nslices,
390  l_int32 redsweep,
391  l_int32 redsearch,
392  l_float32 sweeprange,
393  l_float32 sweepdelta,
394  l_float32 minbsdelta,
395  PTA **pptas,
396  PTA **pptad)
397 {
398 l_int32 w, h, i;
399 l_float32 deg2rad, angr, angd, dely;
400 NUMA *naskew;
401 PTA *ptas, *ptad;
402 
403  PROCNAME("pixGetLocalSkewTransform");
404 
405  if (!pptas || !pptad)
406  return ERROR_INT("&ptas and &ptad not defined", procName, 1);
407  *pptas = *pptad = NULL;
408  if (!pixs || pixGetDepth(pixs) != 1)
409  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
410  if (nslices < 2 || nslices > 20)
411  nslices = DEFAULT_SLICES;
412  if (redsweep < 1 || redsweep > 8)
413  redsweep = DEFAULT_SWEEP_REDUCTION;
414  if (redsearch < 1 || redsearch > redsweep)
415  redsearch = DEFAULT_BS_REDUCTION;
416  if (sweeprange == 0.0)
417  sweeprange = DEFAULT_SWEEP_RANGE;
418  if (sweepdelta == 0.0)
419  sweepdelta = DEFAULT_SWEEP_DELTA;
420  if (minbsdelta == 0.0)
421  minbsdelta = DEFAULT_MINBS_DELTA;
422 
423  naskew = pixGetLocalSkewAngles(pixs, nslices, redsweep, redsearch,
424  sweeprange, sweepdelta, minbsdelta,
425  NULL, NULL, 0);
426  if (!naskew)
427  return ERROR_INT("naskew not made", procName, 1);
428 
429  deg2rad = 3.14159265 / 180.;
430  w = pixGetWidth(pixs);
431  h = pixGetHeight(pixs);
432  ptas = ptaCreate(4);
433  ptad = ptaCreate(4);
434  *pptas = ptas;
435  *pptad = ptad;
436 
437  /* Find i for skew line that intersects LHS at i and RHS at h / 20 */
438  for (i = 0; i < h; i++) {
439  numaGetFValue(naskew, i, &angd);
440  angr = angd * deg2rad;
441  dely = w * tan(angr);
442  if (i - dely > 0.05 * h)
443  break;
444  }
445  ptaAddPt(ptas, 0, i);
446  ptaAddPt(ptas, w - 1, i - dely);
447  ptaAddPt(ptad, 0, i);
448  ptaAddPt(ptad, w - 1, i);
449 
450  /* Find i for skew line that intersects LHS at i and RHS at 19h / 20 */
451  for (i = h - 1; i > 0; i--) {
452  numaGetFValue(naskew, i, &angd);
453  angr = angd * deg2rad;
454  dely = w * tan(angr);
455  if (i - dely < 0.95 * h)
456  break;
457  }
458  ptaAddPt(ptas, 0, i);
459  ptaAddPt(ptas, w - 1, i - dely);
460  ptaAddPt(ptad, 0, i);
461  ptaAddPt(ptad, w - 1, i);
462 
463  numaDestroy(&naskew);
464  return 0;
465 }
466 
467 
505 NUMA *
507  l_int32 nslices,
508  l_int32 redsweep,
509  l_int32 redsearch,
510  l_float32 sweeprange,
511  l_float32 sweepdelta,
512  l_float32 minbsdelta,
513  l_float32 *pa,
514  l_float32 *pb,
515  l_int32 debug)
516 {
517 l_int32 w, h, hs, i, ystart, yend, ovlap, npts;
518 l_float32 angle, conf, ycenter, a, b;
519 BOX *box;
520 GPLOT *gplot;
521 NUMA *naskew, *nax, *nay;
522 PIX *pix;
523 PTA *pta;
524 
525  PROCNAME("pixGetLocalSkewAngles");
526 
527  if (!pixs || pixGetDepth(pixs) != 1)
528  return (NUMA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
529  if (nslices < 2 || nslices > 20)
530  nslices = DEFAULT_SLICES;
531  if (redsweep < 1 || redsweep > 8)
532  redsweep = DEFAULT_SWEEP_REDUCTION;
533  if (redsearch < 1 || redsearch > redsweep)
534  redsearch = DEFAULT_BS_REDUCTION;
535  if (sweeprange == 0.0)
536  sweeprange = DEFAULT_SWEEP_RANGE;
537  if (sweepdelta == 0.0)
538  sweepdelta = DEFAULT_SWEEP_DELTA;
539  if (minbsdelta == 0.0)
540  minbsdelta = DEFAULT_MINBS_DELTA;
541 
542  pixGetDimensions(pixs, &w, &h, NULL);
543  hs = h / nslices;
544  ovlap = (l_int32)(OVERLAP_FRACTION * hs);
545  pta = ptaCreate(nslices);
546  for (i = 0; i < nslices; i++) {
547  ystart = L_MAX(0, hs * i - ovlap);
548  yend = L_MIN(h - 1, hs * (i + 1) + ovlap);
549  ycenter = (l_float32)(ystart + yend) / 2;
550  box = boxCreate(0, ystart, w, yend - ystart + 1);
551  pix = pixClipRectangle(pixs, box, NULL);
552  pixFindSkewSweepAndSearch(pix, &angle, &conf, redsweep, redsearch,
553  sweeprange, sweepdelta, minbsdelta);
554  if (conf > MIN_ALLOWED_CONFIDENCE)
555  ptaAddPt(pta, ycenter, angle);
556  pixDestroy(&pix);
557  boxDestroy(&box);
558  }
559 
560  /* Do linear least squares fit */
561  if ((npts = ptaGetCount(pta)) < 2) {
562  ptaDestroy(&pta);
563  return (NUMA *)ERROR_PTR("can't fit skew", procName, NULL);
564  }
565  ptaGetLinearLSF(pta, &a, &b, NULL);
566  if (pa) *pa = a;
567  if (pb) *pb = b;
568 
569  /* Make skew angle array as function of raster line */
570  naskew = numaCreate(h);
571  for (i = 0; i < h; i++) {
572  angle = a * i + b;
573  numaAddNumber(naskew, angle);
574  }
575 
576  if (debug) {
577  lept_mkdir("lept/baseline");
578  ptaGetArrays(pta, &nax, &nay);
579  gplot = gplotCreate("/tmp/lept/baseline/skew", GPLOT_PNG,
580  "skew as fctn of y", "y (in raster lines from top)",
581  "angle (in degrees)");
582  gplotAddPlot(gplot, NULL, naskew, GPLOT_POINTS, "linear lsf");
583  gplotAddPlot(gplot, nax, nay, GPLOT_POINTS, "actual data pts");
584  gplotMakeOutput(gplot);
585  gplotDestroy(&gplot);
586  numaDestroy(&nax);
587  numaDestroy(&nay);
588  }
589 
590  ptaDestroy(&pta);
591  return naskew;
592 }
void gplotDestroy(GPLOT **pgplot)
gplotDestroy()
Definition: gplot.c:197
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
pixCountPixelsByRow()
Definition: pix3.c:2029
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:692
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:1944
Definition: pix.h:717
l_ok gplotAddPlot(GPLOT *gplot, NUMA *nax, NUMA *nay, l_int32 plotstyle, const char *plottitle)
gplotAddPlot()
Definition: gplot.c:263
BOXA * boxaSort(BOXA *boxas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex)
boxaSort()
Definition: boxfunc2.c:568
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3233
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:388
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:342
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
l_ok gplotMakeOutput(GPLOT *gplot)
gplotMakeOutput()
Definition: gplot.c:379
GPLOT * gplotCreate(const char *rootname, l_int32 outformat, const char *title, const char *xlabel, const char *ylabel)
gplotCreate()
Definition: gplot.c:138
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:116
l_ok ptaGetArrays(PTA *pta, NUMA **pnax, NUMA **pnay)
ptaGetArrays()
Definition: ptabasic.c:616
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:504
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:580
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:320
l_ok ptaGetLinearLSF(PTA *pta, l_float32 *pa, l_float32 *pb, NUMA **pnafit)
ptaGetLinearLSF()
Definition: ptafunc1.c:1044
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1020
Definition: pix.h:492
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:1523
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:820
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:147
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
Definition: array.h:59
BOXA * boxaTransform(BOXA *boxas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
boxaTransform()
Definition: boxfunc2.c:93
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:631
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:863
PIX * pixMorphSequence(PIX *pixs, const char *sequence, l_int32 dispsep)
pixMorphSequence()
Definition: morphseq.c:133
Definition: gplot.h:75
NUMA * pixFindBaselines(PIX *pixs, PTA **ppta, PIXA *pixadb)
pixFindBaselines()
Definition: baseline.c:113
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
Definition: pix.h:454
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:190
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:506
Definition: pix.h:718
Definition: pix.h:134
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:192
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:558
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:718
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:555
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:486
PIX * pixProjectiveSampledPta(PIX *pixs, PTA *ptad, PTA *ptas, l_int32 incolor)
pixProjectiveSampledPta()
Definition: projective.c:141
Definition: pix.h:480
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:244
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:165
l_ok gplotSimple1(NUMA *na, l_int32 outformat, const char *outroot, const char *title)
gplotSimple1()
Definition: gplot.c:575
Definition: pix.h:517