Leptonica  1.73
Image processing and image analysis suite
kernel.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 
27 
83 #include <string.h>
84 #include <math.h>
85 #include "allheaders.h"
86 
87 
88 /*------------------------------------------------------------------------*
89  * Create / Destroy *
90  *------------------------------------------------------------------------*/
104 L_KERNEL *
105 kernelCreate(l_int32 height,
106  l_int32 width)
107 {
108 L_KERNEL *kel;
109 
110  PROCNAME("kernelCreate");
111 
112  if ((kel = (L_KERNEL *)LEPT_CALLOC(1, sizeof(L_KERNEL))) == NULL)
113  return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
114  kel->sy = height;
115  kel->sx = width;
116  if ((kel->data = create2dFloatArray(height, width)) == NULL) {
117  LEPT_FREE(kel);
118  return (L_KERNEL *)ERROR_PTR("data not allocated", procName, NULL);
119  }
120 
121  return kel;
122 }
123 
124 
131 void
133 {
134 l_int32 i;
135 L_KERNEL *kel;
136 
137  PROCNAME("kernelDestroy");
138 
139  if (pkel == NULL) {
140  L_WARNING("ptr address is NULL!\n", procName);
141  return;
142  }
143  if ((kel = *pkel) == NULL)
144  return;
145 
146  for (i = 0; i < kel->sy; i++)
147  LEPT_FREE(kel->data[i]);
148  LEPT_FREE(kel->data);
149  LEPT_FREE(kel);
150 
151  *pkel = NULL;
152  return;
153 }
154 
155 
162 L_KERNEL *
164 {
165 l_int32 i, j, sx, sy, cx, cy;
166 L_KERNEL *keld;
167 
168  PROCNAME("kernelCopy");
169 
170  if (!kels)
171  return (L_KERNEL *)ERROR_PTR("kels not defined", procName, NULL);
172 
173  kernelGetParameters(kels, &sy, &sx, &cy, &cx);
174  if ((keld = kernelCreate(sy, sx)) == NULL)
175  return (L_KERNEL *)ERROR_PTR("keld not made", procName, NULL);
176  keld->cy = cy;
177  keld->cx = cx;
178  for (i = 0; i < sy; i++)
179  for (j = 0; j < sx; j++)
180  keld->data[i][j] = kels->data[i][j];
181 
182  return keld;
183 }
184 
185 
186 /*----------------------------------------------------------------------*
187  * Accessors *
188  *----------------------------------------------------------------------*/
198 l_int32
200  l_int32 row,
201  l_int32 col,
202  l_float32 *pval)
203 {
204  PROCNAME("kernelGetElement");
205 
206  if (!pval)
207  return ERROR_INT("&val not defined", procName, 1);
208  *pval = 0;
209  if (!kel)
210  return ERROR_INT("kernel not defined", procName, 1);
211  if (row < 0 || row >= kel->sy)
212  return ERROR_INT("kernel row out of bounds", procName, 1);
213  if (col < 0 || col >= kel->sx)
214  return ERROR_INT("kernel col out of bounds", procName, 1);
215 
216  *pval = kel->data[row][col];
217  return 0;
218 }
219 
220 
230 l_int32
232  l_int32 row,
233  l_int32 col,
234  l_float32 val)
235 {
236  PROCNAME("kernelSetElement");
237 
238  if (!kel)
239  return ERROR_INT("kel not defined", procName, 1);
240  if (row < 0 || row >= kel->sy)
241  return ERROR_INT("kernel row out of bounds", procName, 1);
242  if (col < 0 || col >= kel->sx)
243  return ERROR_INT("kernel col out of bounds", procName, 1);
244 
245  kel->data[row][col] = val;
246  return 0;
247 }
248 
249 
257 l_int32
259  l_int32 *psy,
260  l_int32 *psx,
261  l_int32 *pcy,
262  l_int32 *pcx)
263 {
264  PROCNAME("kernelGetParameters");
265 
266  if (psy) *psy = 0;
267  if (psx) *psx = 0;
268  if (pcy) *pcy = 0;
269  if (pcx) *pcx = 0;
270  if (!kel)
271  return ERROR_INT("kernel not defined", procName, 1);
272  if (psy) *psy = kel->sy;
273  if (psx) *psx = kel->sx;
274  if (pcy) *pcy = kel->cy;
275  if (pcx) *pcx = kel->cx;
276  return 0;
277 }
278 
279 
287 l_int32
289  l_int32 cy,
290  l_int32 cx)
291 {
292  PROCNAME("kernelSetOrigin");
293 
294  if (!kel)
295  return ERROR_INT("kel not defined", procName, 1);
296  kel->cy = cy;
297  kel->cx = cx;
298  return 0;
299 }
300 
301 
309 l_int32
311  l_float32 *psum)
312 {
313 l_int32 sx, sy, i, j;
314 
315  PROCNAME("kernelGetSum");
316 
317  if (!psum)
318  return ERROR_INT("&sum not defined", procName, 1);
319  *psum = 0.0;
320  if (!kel)
321  return ERROR_INT("kernel not defined", procName, 1);
322 
323  kernelGetParameters(kel, &sy, &sx, NULL, NULL);
324  for (i = 0; i < sy; i++) {
325  for (j = 0; j < sx; j++) {
326  *psum += kel->data[i][j];
327  }
328  }
329  return 0;
330 }
331 
332 
341 l_int32
343  l_float32 *pmin,
344  l_float32 *pmax)
345 {
346 l_int32 sx, sy, i, j;
347 l_float32 val, minval, maxval;
348 
349  PROCNAME("kernelGetMinmax");
350 
351  if (!pmin && !pmax)
352  return ERROR_INT("neither &min nor &max defined", procName, 1);
353  if (pmin) *pmin = 0.0;
354  if (pmax) *pmax = 0.0;
355  if (!kel)
356  return ERROR_INT("kernel not defined", procName, 1);
357 
358  kernelGetParameters(kel, &sy, &sx, NULL, NULL);
359  minval = 10000000.0;
360  maxval = -10000000.0;
361  for (i = 0; i < sy; i++) {
362  for (j = 0; j < sx; j++) {
363  val = kel->data[i][j];
364  if (val < minval)
365  minval = val;
366  if (val > maxval)
367  maxval = val;
368  }
369  }
370  if (pmin)
371  *pmin = minval;
372  if (pmax)
373  *pmax = maxval;
374 
375  return 0;
376 }
377 
378 
379 /*----------------------------------------------------------------------*
380  * Normalize/Invert *
381  *----------------------------------------------------------------------*/
397 L_KERNEL *
399  l_float32 normsum)
400 {
401 l_int32 i, j, sx, sy, cx, cy;
402 l_float32 sum, factor;
403 L_KERNEL *keld;
404 
405  PROCNAME("kernelNormalize");
406 
407  if (!kels)
408  return (L_KERNEL *)ERROR_PTR("kels not defined", procName, NULL);
409 
410  kernelGetSum(kels, &sum);
411  if (L_ABS(sum) < 0.00001) {
412  L_WARNING("null sum; not normalizing; returning a copy\n", procName);
413  return kernelCopy(kels);
414  }
415 
416  kernelGetParameters(kels, &sy, &sx, &cy, &cx);
417  if ((keld = kernelCreate(sy, sx)) == NULL)
418  return (L_KERNEL *)ERROR_PTR("keld not made", procName, NULL);
419  keld->cy = cy;
420  keld->cx = cx;
421 
422  factor = normsum / sum;
423  for (i = 0; i < sy; i++)
424  for (j = 0; j < sx; j++)
425  keld->data[i][j] = factor * kels->data[i][j];
426 
427  return keld;
428 }
429 
430 
443 L_KERNEL *
445 {
446 l_int32 i, j, sx, sy, cx, cy;
447 L_KERNEL *keld;
448 
449  PROCNAME("kernelInvert");
450 
451  if (!kels)
452  return (L_KERNEL *)ERROR_PTR("kels not defined", procName, NULL);
453 
454  kernelGetParameters(kels, &sy, &sx, &cy, &cx);
455  if ((keld = kernelCreate(sy, sx)) == NULL)
456  return (L_KERNEL *)ERROR_PTR("keld not made", procName, NULL);
457  keld->cy = sy - 1 - cy;
458  keld->cx = sx - 1 - cx;
459 
460  for (i = 0; i < sy; i++)
461  for (j = 0; j < sx; j++)
462  keld->data[i][j] = kels->data[sy - 1 - i][sx - 1 - j];
463 
464  return keld;
465 }
466 
467 
468 /*----------------------------------------------------------------------*
469  * Helper function *
470  *----------------------------------------------------------------------*/
485 l_float32 **
487  l_int32 sx)
488 {
489 l_int32 i;
490 l_float32 **array;
491 
492  PROCNAME("create2dFloatArray");
493 
494  if ((array = (l_float32 **)LEPT_CALLOC(sy, sizeof(l_float32 *))) == NULL)
495  return (l_float32 **)ERROR_PTR("ptr array not made", procName, NULL);
496 
497  for (i = 0; i < sy; i++)
498  array[i] = (l_float32 *)LEPT_CALLOC(sx, sizeof(l_float32));
499  return array;
500 }
501 
502 
503 /*----------------------------------------------------------------------*
504  * Kernel serialized I/O *
505  *----------------------------------------------------------------------*/
512 L_KERNEL *
513 kernelRead(const char *fname)
514 {
515 FILE *fp;
516 L_KERNEL *kel;
517 
518  PROCNAME("kernelRead");
519 
520  if (!fname)
521  return (L_KERNEL *)ERROR_PTR("fname not defined", procName, NULL);
522 
523  if ((fp = fopenReadStream(fname)) == NULL)
524  return (L_KERNEL *)ERROR_PTR("stream not opened", procName, NULL);
525  if ((kel = kernelReadStream(fp)) == NULL) {
526  fclose(fp);
527  return (L_KERNEL *)ERROR_PTR("kel not returned", procName, NULL);
528  }
529  fclose(fp);
530 
531  return kel;
532 }
533 
534 
541 L_KERNEL *
543 {
544 l_int32 sy, sx, cy, cx, i, j, ret, version, ignore;
545 L_KERNEL *kel;
546 
547  PROCNAME("kernelReadStream");
548 
549  if (!fp)
550  return (L_KERNEL *)ERROR_PTR("stream not defined", procName, NULL);
551 
552  ret = fscanf(fp, " Kernel Version %d\n", &version);
553  if (ret != 1)
554  return (L_KERNEL *)ERROR_PTR("not a kernel file", procName, NULL);
555  if (version != KERNEL_VERSION_NUMBER)
556  return (L_KERNEL *)ERROR_PTR("invalid kernel version", procName, NULL);
557 
558  if (fscanf(fp, " sy = %d, sx = %d, cy = %d, cx = %d\n",
559  &sy, &sx, &cy, &cx) != 4)
560  return (L_KERNEL *)ERROR_PTR("dimensions not read", procName, NULL);
561 
562  if ((kel = kernelCreate(sy, sx)) == NULL)
563  return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
564  kernelSetOrigin(kel, cy, cx);
565 
566  for (i = 0; i < sy; i++) {
567  for (j = 0; j < sx; j++)
568  ignore = fscanf(fp, "%15f", &kel->data[i][j]);
569  ignore = fscanf(fp, "\n");
570  }
571  ignore = fscanf(fp, "\n");
572 
573  return kel;
574 }
575 
576 
584 l_int32
585 kernelWrite(const char *fname,
586  L_KERNEL *kel)
587 {
588 FILE *fp;
589 
590  PROCNAME("kernelWrite");
591 
592  if (!fname)
593  return ERROR_INT("fname not defined", procName, 1);
594  if (!kel)
595  return ERROR_INT("kel not defined", procName, 1);
596 
597  if ((fp = fopenWriteStream(fname, "wb")) == NULL)
598  return ERROR_INT("stream not opened", procName, 1);
599  kernelWriteStream(fp, kel);
600  fclose(fp);
601 
602  return 0;
603 }
604 
605 
613 l_int32
615  L_KERNEL *kel)
616 {
617 l_int32 sx, sy, cx, cy, i, j;
618 
619  PROCNAME("kernelWriteStream");
620 
621  if (!fp)
622  return ERROR_INT("stream not defined", procName, 1);
623  if (!kel)
624  return ERROR_INT("kel not defined", procName, 1);
625  kernelGetParameters(kel, &sy, &sx, &cy, &cx);
626 
627  fprintf(fp, " Kernel Version %d\n", KERNEL_VERSION_NUMBER);
628  fprintf(fp, " sy = %d, sx = %d, cy = %d, cx = %d\n", sy, sx, cy, cx);
629  for (i = 0; i < sy; i++) {
630  for (j = 0; j < sx; j++)
631  fprintf(fp, "%15.4f", kel->data[i][j]);
632  fprintf(fp, "\n");
633  }
634  fprintf(fp, "\n");
635 
636  return 0;
637 }
638 
639 
640 /*----------------------------------------------------------------------*
641  * Making a kernel from a compiled string *
642  *----------------------------------------------------------------------*/
665 L_KERNEL *
667  l_int32 w,
668  l_int32 cy,
669  l_int32 cx,
670  const char *kdata)
671 {
672 l_int32 n, i, j, index;
673 l_float32 val;
674 L_KERNEL *kel;
675 NUMA *na;
676 
677  PROCNAME("kernelCreateFromString");
678 
679  if (h < 1)
680  return (L_KERNEL *)ERROR_PTR("height must be > 0", procName, NULL);
681  if (w < 1)
682  return (L_KERNEL *)ERROR_PTR("width must be > 0", procName, NULL);
683  if (cy < 0 || cy >= h)
684  return (L_KERNEL *)ERROR_PTR("cy invalid", procName, NULL);
685  if (cx < 0 || cx >= w)
686  return (L_KERNEL *)ERROR_PTR("cx invalid", procName, NULL);
687 
688  kel = kernelCreate(h, w);
689  kernelSetOrigin(kel, cy, cx);
690  na = parseStringForNumbers(kdata, " \t\n");
691  n = numaGetCount(na);
692  if (n != w * h) {
693  kernelDestroy(&kel);
694  numaDestroy(&na);
695  fprintf(stderr, "w = %d, h = %d, num ints = %d\n", w, h, n);
696  return (L_KERNEL *)ERROR_PTR("invalid integer data", procName, NULL);
697  }
698 
699  index = 0;
700  for (i = 0; i < h; i++) {
701  for (j = 0; j < w; j++) {
702  numaGetFValue(na, index, &val);
703  kernelSetElement(kel, i, j, val);
704  index++;
705  }
706  }
707 
708  numaDestroy(&na);
709  return kel;
710 }
711 
712 
713 /*----------------------------------------------------------------------*
714  * Making a kernel from a simple file format *
715  *----------------------------------------------------------------------*/
751 L_KERNEL *
752 kernelCreateFromFile(const char *filename)
753 {
754 char *filestr, *line;
755 l_int32 nlines, i, j, first, index, w, h, cx, cy, n;
756 l_float32 val;
757 size_t size;
758 NUMA *na, *nat;
759 SARRAY *sa;
760 L_KERNEL *kel;
761 
762  PROCNAME("kernelCreateFromFile");
763 
764  if (!filename)
765  return (L_KERNEL *)ERROR_PTR("filename not defined", procName, NULL);
766 
767  if ((filestr = (char *)l_binaryRead(filename, &size)) == NULL)
768  return (L_KERNEL *)ERROR_PTR("file not found", procName, NULL);
769  if (size == 0) {
770  LEPT_FREE(filestr);
771  return (L_KERNEL *)ERROR_PTR("file is empty", procName, NULL);
772  }
773 
774  sa = sarrayCreateLinesFromString(filestr, 1);
775  LEPT_FREE(filestr);
776  nlines = sarrayGetCount(sa);
777 
778  /* Find the first data line. */
779  for (i = 0, first = 0; i < nlines; i++) {
780  line = sarrayGetString(sa, i, L_NOCOPY);
781  if (line[0] != '#') {
782  first = i;
783  break;
784  }
785  }
786 
787  /* Find the kernel dimensions and origin location. */
788  line = sarrayGetString(sa, first, L_NOCOPY);
789  if (sscanf(line, "%d %d", &h, &w) != 2) {
790  sarrayDestroy(&sa);
791  return (L_KERNEL *)ERROR_PTR("error reading h,w", procName, NULL);
792  }
793  line = sarrayGetString(sa, first + 1, L_NOCOPY);
794  if (sscanf(line, "%d %d", &cy, &cx) != 2) {
795  sarrayDestroy(&sa);
796  return (L_KERNEL *)ERROR_PTR("error reading cy,cx", procName, NULL);
797  }
798 
799  /* Extract the data. This ends when we reach eof, or when we
800  * encounter a line of data that is either a null string or
801  * contains just a newline. */
802  na = numaCreate(0);
803  for (i = first + 2; i < nlines; i++) {
804  line = sarrayGetString(sa, i, L_NOCOPY);
805  if (line[0] == '\0' || line[0] == '\n' || line[0] == '#')
806  break;
807  nat = parseStringForNumbers(line, " \t\n");
808  numaJoin(na, nat, 0, -1);
809  numaDestroy(&nat);
810  }
811  sarrayDestroy(&sa);
812 
813  n = numaGetCount(na);
814  if (n != w * h) {
815  numaDestroy(&na);
816  fprintf(stderr, "w = %d, h = %d, num ints = %d\n", w, h, n);
817  return (L_KERNEL *)ERROR_PTR("invalid integer data", procName, NULL);
818  }
819 
820  kel = kernelCreate(h, w);
821  kernelSetOrigin(kel, cy, cx);
822  index = 0;
823  for (i = 0; i < h; i++) {
824  for (j = 0; j < w; j++) {
825  numaGetFValue(na, index, &val);
826  kernelSetElement(kel, i, j, val);
827  index++;
828  }
829  }
830 
831  numaDestroy(&na);
832  return kel;
833 }
834 
835 
836 /*----------------------------------------------------------------------*
837  * Making a kernel from a Pix *
838  *----------------------------------------------------------------------*/
851 L_KERNEL *
853  l_int32 cy,
854  l_int32 cx)
855 {
856 l_int32 i, j, w, h, d;
857 l_uint32 val;
858 L_KERNEL *kel;
859 
860  PROCNAME("kernelCreateFromPix");
861 
862  if (!pix)
863  return (L_KERNEL *)ERROR_PTR("pix not defined", procName, NULL);
864  pixGetDimensions(pix, &w, &h, &d);
865  if (d != 8)
866  return (L_KERNEL *)ERROR_PTR("pix not 8 bpp", procName, NULL);
867  if (cy < 0 || cx < 0 || cy >= h || cx >= w)
868  return (L_KERNEL *)ERROR_PTR("(cy, cx) invalid", procName, NULL);
869 
870  kel = kernelCreate(h, w);
871  kernelSetOrigin(kel, cy, cx);
872  for (i = 0; i < h; i++) {
873  for (j = 0; j < w; j++) {
874  pixGetPixel(pix, j, i, &val);
875  kernelSetElement(kel, i, j, (l_float32)val);
876  }
877  }
878 
879  return kel;
880 }
881 
882 
883 /*----------------------------------------------------------------------*
884  * Display a kernel in a pix *
885  *----------------------------------------------------------------------*/
912 PIX *
914  l_int32 size,
915  l_int32 gthick)
916 {
917 l_int32 i, j, w, h, sx, sy, cx, cy, width, x0, y0;
918 l_int32 normval;
919 l_float32 minval, maxval, max, val, norm;
920 PIX *pixd, *pixt0, *pixt1;
921 
922  PROCNAME("kernelDisplayInPix");
923 
924  if (!kel)
925  return (PIX *)ERROR_PTR("kernel not defined", procName, NULL);
926 
927  /* Normalize the max value to be 255 for display */
928  kernelGetParameters(kel, &sy, &sx, &cy, &cx);
929  kernelGetMinMax(kel, &minval, &maxval);
930  max = L_MAX(maxval, -minval);
931  if (max == 0.0)
932  return (PIX *)ERROR_PTR("kernel elements all 0.0", procName, NULL);
933  norm = 255. / (l_float32)max;
934 
935  /* Handle the 1 element/pixel case; typically with large kernels */
936  if (size == 1 && gthick == 0) {
937  pixd = pixCreate(sx, sy, 8);
938  for (i = 0; i < sy; i++) {
939  for (j = 0; j < sx; j++) {
940  kernelGetElement(kel, i, j, &val);
941  normval = (l_int32)(norm * L_ABS(val));
942  pixSetPixel(pixd, j, i, normval);
943  }
944  }
945  return pixd;
946  }
947 
948  /* Enforce the constraints for the grid line version */
949  if (size < 17) {
950  L_WARNING("size < 17; setting to 17\n", procName);
951  size = 17;
952  }
953  if (size % 2 == 0)
954  size++;
955  if (gthick < 2) {
956  L_WARNING("grid thickness < 2; setting to 2\n", procName);
957  gthick = 2;
958  }
959 
960  w = size * sx + gthick * (sx + 1);
961  h = size * sy + gthick * (sy + 1);
962  pixd = pixCreate(w, h, 8);
963 
964  /* Generate grid lines */
965  for (i = 0; i <= sy; i++)
966  pixRenderLine(pixd, 0, gthick / 2 + i * (size + gthick),
967  w - 1, gthick / 2 + i * (size + gthick),
968  gthick, L_SET_PIXELS);
969  for (j = 0; j <= sx; j++)
970  pixRenderLine(pixd, gthick / 2 + j * (size + gthick), 0,
971  gthick / 2 + j * (size + gthick), h - 1,
972  gthick, L_SET_PIXELS);
973 
974  /* Generate mask for each element */
975  pixt0 = pixCreate(size, size, 1);
976  pixSetAll(pixt0);
977 
978  /* Generate crossed lines for origin pattern */
979  pixt1 = pixCreate(size, size, 1);
980  width = size / 8;
981  pixRenderLine(pixt1, size / 2, (l_int32)(0.12 * size),
982  size / 2, (l_int32)(0.88 * size),
983  width, L_SET_PIXELS);
984  pixRenderLine(pixt1, (l_int32)(0.15 * size), size / 2,
985  (l_int32)(0.85 * size), size / 2,
986  width, L_FLIP_PIXELS);
987  pixRasterop(pixt1, size / 2 - width, size / 2 - width,
988  2 * width, 2 * width, PIX_NOT(PIX_DST), NULL, 0, 0);
989 
990  /* Paste the patterns in */
991  y0 = gthick;
992  for (i = 0; i < sy; i++) {
993  x0 = gthick;
994  for (j = 0; j < sx; j++) {
995  kernelGetElement(kel, i, j, &val);
996  normval = (l_int32)(norm * L_ABS(val));
997  pixSetMaskedGeneral(pixd, pixt0, normval, x0, y0);
998  if (i == cy && j == cx)
999  pixPaintThroughMask(pixd, pixt1, x0, y0, 255 - normval);
1000  x0 += size + gthick;
1001  }
1002  y0 += size + gthick;
1003  }
1004 
1005  pixDestroy(&pixt0);
1006  pixDestroy(&pixt1);
1007  return pixd;
1008 }
1009 
1010 
1011 /*------------------------------------------------------------------------*
1012  * Parse string to extract numbers *
1013  *------------------------------------------------------------------------*/
1026 NUMA *
1027 parseStringForNumbers(const char *str,
1028  const char *seps)
1029 {
1030 char *newstr, *head;
1031 char *tail = NULL;
1032 l_float32 val;
1033 NUMA *na;
1034 
1035  PROCNAME("parseStringForNumbers");
1036 
1037  if (!str)
1038  return (NUMA *)ERROR_PTR("str not defined", procName, NULL);
1039 
1040  newstr = stringNew(str); /* to enforce const-ness of str */
1041  na = numaCreate(0);
1042  head = strtokSafe(newstr, seps, &tail);
1043  val = atof(head);
1044  numaAddNumber(na, val);
1045  LEPT_FREE(head);
1046  while ((head = strtokSafe(NULL, seps, &tail)) != NULL) {
1047  val = atof(head);
1048  numaAddNumber(na, val);
1049  LEPT_FREE(head);
1050  }
1051 
1052  LEPT_FREE(newstr);
1053  return na;
1054 }
1055 
1056 
1057 /*------------------------------------------------------------------------*
1058  * Simple parametric kernels *
1059  *------------------------------------------------------------------------*/
1078 L_KERNEL *
1079 makeFlatKernel(l_int32 height,
1080  l_int32 width,
1081  l_int32 cy,
1082  l_int32 cx)
1083 {
1084 l_int32 i, j;
1085 l_float32 normval;
1086 L_KERNEL *kel;
1087 
1088  PROCNAME("makeFlatKernel");
1089 
1090  if ((kel = kernelCreate(height, width)) == NULL)
1091  return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
1092  kernelSetOrigin(kel, cy, cx);
1093  normval = 1.0 / (l_float32)(height * width);
1094  for (i = 0; i < height; i++) {
1095  for (j = 0; j < width; j++) {
1096  kernelSetElement(kel, i, j, normval);
1097  }
1098  }
1099 
1100  return kel;
1101 }
1102 
1103 
1123 L_KERNEL *
1124 makeGaussianKernel(l_int32 halfheight,
1125  l_int32 halfwidth,
1126  l_float32 stdev,
1127  l_float32 max)
1128 {
1129 l_int32 sx, sy, i, j;
1130 l_float32 val;
1131 L_KERNEL *kel;
1132 
1133  PROCNAME("makeGaussianKernel");
1134 
1135  sx = 2 * halfwidth + 1;
1136  sy = 2 * halfheight + 1;
1137  if ((kel = kernelCreate(sy, sx)) == NULL)
1138  return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
1139  kernelSetOrigin(kel, halfheight, halfwidth);
1140  for (i = 0; i < sy; i++) {
1141  for (j = 0; j < sx; j++) {
1142  val = expf(-(l_float32)((i - halfheight) * (i - halfheight) +
1143  (j - halfwidth) * (j - halfwidth)) /
1144  (2. * stdev * stdev));
1145  kernelSetElement(kel, i, j, max * val);
1146  }
1147  }
1148 
1149  return kel;
1150 }
1151 
1152 
1177 l_int32
1178 makeGaussianKernelSep(l_int32 halfheight,
1179  l_int32 halfwidth,
1180  l_float32 stdev,
1181  l_float32 max,
1182  L_KERNEL **pkelx,
1183  L_KERNEL **pkely)
1184 {
1185  PROCNAME("makeGaussianKernelSep");
1186 
1187  if (!pkelx || !pkely)
1188  return ERROR_INT("&kelx and &kely not defined", procName, 1);
1189 
1190  *pkelx = makeGaussianKernel(0, halfwidth, stdev, max);
1191  *pkely = makeGaussianKernel(halfheight, 0, stdev, 1.0);
1192  return 0;
1193 }
1194 
1195 
1222 L_KERNEL *
1223 makeDoGKernel(l_int32 halfheight,
1224  l_int32 halfwidth,
1225  l_float32 stdev,
1226  l_float32 ratio)
1227 {
1228 l_int32 sx, sy, i, j;
1229 l_float32 pi, squaredist, highnorm, lownorm, val;
1230 L_KERNEL *kel;
1231 
1232  PROCNAME("makeDoGKernel");
1233 
1234  sx = 2 * halfwidth + 1;
1235  sy = 2 * halfheight + 1;
1236  if ((kel = kernelCreate(sy, sx)) == NULL)
1237  return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
1238  kernelSetOrigin(kel, halfheight, halfwidth);
1239 
1240  pi = 3.1415926535;
1241  for (i = 0; i < sy; i++) {
1242  for (j = 0; j < sx; j++) {
1243  squaredist = (l_float32)((i - halfheight) * (i - halfheight) +
1244  (j - halfwidth) * (j - halfwidth));
1245  highnorm = 1. / (2 * stdev * stdev);
1246  lownorm = highnorm / (ratio * ratio);
1247  val = (highnorm / pi) * expf(-(highnorm * squaredist))
1248  - (lownorm / pi) * expf(-(lownorm * squaredist));
1249  kernelSetElement(kel, i, j, val);
1250  }
1251  }
1252 
1253  return kel;
1254 }
l_int32 kernelWriteStream(FILE *fp, L_KERNEL *kel)
kernelWriteStream()
Definition: kernel.c:614
PIX * kernelDisplayInPix(L_KERNEL *kel, l_int32 size, l_int32 gthick)
kernelDisplayInPix()
Definition: kernel.c:913
l_int32 pixSetMaskedGeneral(PIX *pixd, PIX *pixm, l_uint32 val, l_int32 x, l_int32 y)
pixSetMaskedGeneral()
Definition: pix3.c:294
l_int32 numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:472
l_int32 makeGaussianKernelSep(l_int32 halfheight, l_int32 halfwidth, l_float32 stdev, l_float32 max, L_KERNEL **pkelx, L_KERNEL **pkely)
makeGaussianKernelSep()
Definition: kernel.c:1178
L_KERNEL * makeGaussianKernel(l_int32 halfheight, l_int32 halfwidth, l_float32 stdev, l_float32 max)
makeGaussianKernel()
Definition: kernel.c:1124
NUMA * parseStringForNumbers(const char *str, const char *seps)
parseStringForNumbers()
Definition: kernel.c:1027
l_float32 ** data
Definition: morph.h:95
l_int32 pixRenderLine(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width, l_int32 op)
pixRenderLine()
Definition: graphics.c:1482
l_int32 pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:180
Definition: pix.h:704
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:202
l_int32 kernelGetSum(L_KERNEL *kel, l_float32 *psum)
kernelGetSum()
Definition: kernel.c:310
L_KERNEL * kernelCreateFromPix(PIX *pix, l_int32 cy, l_int32 cx)
kernelCreateFromPix()
Definition: kernel.c:852
l_int32 numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:691
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
l_int32 numaJoin(NUMA *nad, NUMA *nas, l_int32 istart, l_int32 iend)
numaJoin()
Definition: numafunc1.c:3319
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:186
l_int32 kernelGetElement(L_KERNEL *kel, l_int32 row, l_int32 col, l_float32 *pval)
kernelGetElement()
Definition: kernel.c:199
Definition: array.h:116
l_int32 pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
Definition: rop.c:193
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1154
l_int32 sy
Definition: morph.h:91
Definition: array.h:59
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_int32 kernelSetElement(L_KERNEL *kel, l_int32 row, l_int32 col, l_float32 val)
kernelSetElement()
Definition: kernel.c:231
L_KERNEL * kernelCopy(L_KERNEL *kels)
kernelCopy()
Definition: kernel.c:163
l_int32 kernelGetMinMax(L_KERNEL *kel, l_float32 *pmin, l_float32 *pmax)
kernelGetMinMax()
Definition: kernel.c:342
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:675
l_int32 cx
Definition: morph.h:94
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:545
L_KERNEL * kernelReadStream(FILE *fp)
kernelReadStream()
Definition: kernel.c:542
L_KERNEL * kernelNormalize(L_KERNEL *kels, l_float32 normsum)
kernelNormalize()
Definition: kernel.c:398
SARRAY * sarrayCreateLinesFromString(const char *string, l_int32 blankflag)
sarrayCreateLinesFromString()
Definition: sarray1.c:270
l_int32 pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:618
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:359
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1636
L_KERNEL * kernelInvert(L_KERNEL *kels)
kernelInvert()
Definition: kernel.c:444
void kernelDestroy(L_KERNEL **pkel)
kernelDestroy()
Definition: kernel.c:132
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1593
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:615
l_int32 pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:251
l_int32 kernelGetParameters(L_KERNEL *kel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
kernelGetParameters()
Definition: kernel.c:258
#define PIX_NOT(op)
Definition: pix.h:329
L_KERNEL * kernelCreateFromString(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, const char *kdata)
kernelCreateFromString()
Definition: kernel.c:666
Definition: morph.h:89
Definition: pix.h:134
L_KERNEL * makeFlatKernel(l_int32 height, l_int32 width, l_int32 cy, l_int32 cx)
makeFlatKernel()
Definition: kernel.c:1079
L_KERNEL * kernelRead(const char *fname)
kernelRead()
Definition: kernel.c:513
l_int32 cy
Definition: morph.h:93
char * strtokSafe(char *cstr, const char *seps, char **psaveptr)
strtokSafe()
Definition: utils2.c:582
L_KERNEL * kernelCreateFromFile(const char *filename)
kernelCreateFromFile()
Definition: kernel.c:752
l_int32 pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:729
l_int32 kernelSetOrigin(L_KERNEL *kel, l_int32 cy, l_int32 cx)
kernelSetOrigin()
Definition: kernel.c:288
l_int32 pixGetDimensions(PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1052
l_int32 kernelWrite(const char *fname, L_KERNEL *kel)
kernelWrite()
Definition: kernel.c:585
l_int32 sx
Definition: morph.h:92
L_KERNEL * makeDoGKernel(l_int32 halfheight, l_int32 halfwidth, l_float32 stdev, l_float32 ratio)
makeDoGKernel()
Definition: kernel.c:1223
l_float32 ** create2dFloatArray(l_int32 sy, l_int32 sx)
create2dFloatArray()
Definition: kernel.c:486
#define PIX_DST
Definition: pix.h:328
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:349
L_KERNEL * kernelCreate(l_int32 height, l_int32 width)
kernelCreate()
Definition: kernel.c:105