Leptonica  1.77.0
Image processing and image analysis suite
bilateral.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 
76 #include <math.h>
77 #include "allheaders.h"
78 #include "bilateral.h"
79 
80 static L_BILATERAL *bilateralCreate(PIX *pixs, l_float32 spatial_stdev,
81  l_float32 range_stdev, l_int32 ncomps,
82  l_int32 reduction);
83 static PIX *bilateralApply(L_BILATERAL *bil);
84 static void bilateralDestroy(L_BILATERAL **pbil);
85 
86 
87 #ifndef NO_CONSOLE_IO
88 #define DEBUG_BILATERAL 0
89 #endif /* ~NO_CONSOLE_IO */
90 
91 
92 /*--------------------------------------------------------------------------*
93  * Top level approximate separable grayscale or color bilateral filtering *
94  *--------------------------------------------------------------------------*/
149 PIX *
151  l_float32 spatial_stdev,
152  l_float32 range_stdev,
153  l_int32 ncomps,
154  l_int32 reduction)
155 {
156 l_int32 d;
157 l_float32 sstdev; /* scaled spatial stdev */
158 PIX *pixt, *pixr, *pixg, *pixb, *pixd;
159 
160  PROCNAME("pixBilateral");
161 
162  if (!pixs || pixGetColormap(pixs))
163  return (PIX *)ERROR_PTR("pixs not defined or cmapped", procName, NULL);
164  d = pixGetDepth(pixs);
165  if (d != 8 && d != 32)
166  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
167  if (reduction != 1 && reduction != 2 && reduction != 4)
168  return (PIX *)ERROR_PTR("reduction invalid", procName, NULL);
169  sstdev = spatial_stdev / (l_float32)reduction; /* reduced spat. stdev */
170  if (sstdev < 0.5)
171  return (PIX *)ERROR_PTR("sstdev < 0.5", procName, NULL);
172  if (range_stdev <= 5.0)
173  return (PIX *)ERROR_PTR("range_stdev <= 5.0", procName, NULL);
174  if (ncomps < 4 || ncomps > 30)
175  return (PIX *)ERROR_PTR("ncomps not in [4 ... 30]", procName, NULL);
176  if (ncomps * range_stdev < 100.0)
177  return (PIX *)ERROR_PTR("ncomps * range_stdev < 100.0", procName, NULL);
178 
179  if (d == 8)
180  return pixBilateralGray(pixs, spatial_stdev, range_stdev,
181  ncomps, reduction);
182 
183  pixt = pixGetRGBComponent(pixs, COLOR_RED);
184  pixr = pixBilateralGray(pixt, spatial_stdev, range_stdev, ncomps,
185  reduction);
186  pixDestroy(&pixt);
187  pixt = pixGetRGBComponent(pixs, COLOR_GREEN);
188  pixg = pixBilateralGray(pixt, spatial_stdev, range_stdev, ncomps,
189  reduction);
190  pixDestroy(&pixt);
191  pixt = pixGetRGBComponent(pixs, COLOR_BLUE);
192  pixb = pixBilateralGray(pixt, spatial_stdev, range_stdev, ncomps,
193  reduction);
194  pixDestroy(&pixt);
195  pixd = pixCreateRGBImage(pixr, pixg, pixb);
196  pixDestroy(&pixr);
197  pixDestroy(&pixg);
198  pixDestroy(&pixb);
199  return pixd;
200 }
201 
202 
219 PIX *
221  l_float32 spatial_stdev,
222  l_float32 range_stdev,
223  l_int32 ncomps,
224  l_int32 reduction)
225 {
226 l_float32 sstdev; /* scaled spatial stdev */
227 PIX *pixd;
228 L_BILATERAL *bil;
229 
230  PROCNAME("pixBilateralGray");
231 
232  if (!pixs || pixGetColormap(pixs))
233  return (PIX *)ERROR_PTR("pixs not defined or cmapped", procName, NULL);
234  if (pixGetDepth(pixs) != 8)
235  return (PIX *)ERROR_PTR("pixs not 8 bpp gray", procName, NULL);
236  if (reduction != 1 && reduction != 2 && reduction != 4)
237  return (PIX *)ERROR_PTR("reduction invalid", procName, NULL);
238  sstdev = spatial_stdev / (l_float32)reduction; /* reduced spat. stdev */
239  if (sstdev < 0.5)
240  return (PIX *)ERROR_PTR("sstdev < 0.5", procName, NULL);
241  if (range_stdev <= 5.0)
242  return (PIX *)ERROR_PTR("range_stdev <= 5.0", procName, NULL);
243  if (ncomps < 4 || ncomps > 30)
244  return (PIX *)ERROR_PTR("ncomps not in [4 ... 30]", procName, NULL);
245  if (ncomps * range_stdev < 100.0)
246  return (PIX *)ERROR_PTR("ncomps * range_stdev < 100.0", procName, NULL);
247 
248  bil = bilateralCreate(pixs, spatial_stdev, range_stdev, ncomps, reduction);
249  if (!bil) return (PIX *)ERROR_PTR("bil not made", procName, NULL);
250  pixd = bilateralApply(bil);
251  bilateralDestroy(&bil);
252  return pixd;
253 }
254 
255 
256 /*----------------------------------------------------------------------*
257  * Implementation of approximate separable bilateral filter *
258  *----------------------------------------------------------------------*/
279 static L_BILATERAL *
281  l_float32 spatial_stdev,
282  l_float32 range_stdev,
283  l_int32 ncomps,
284  l_int32 reduction)
285 {
286 l_int32 w, ws, wd, h, hs, hd, i, j, k, index;
287 l_int32 border, minval, maxval, spatial_size;
288 l_int32 halfwidth, wpls, wplt, wpld, kval, nval, dval;
289 l_float32 sstdev, fval1, fval2, denom, sum, norm, kern;
290 l_int32 *nc, *kindex;
291 l_float32 *kfract, *range, *spatial;
292 l_uint32 *datas, *datat, *datad, *lines, *linet, *lined;
293 L_BILATERAL *bil;
294 PIX *pixt, *pixt2, *pixsc, *pixd;
295 PIXA *pixac;
296 
297  PROCNAME("bilateralCreate");
298 
299  sstdev = spatial_stdev / (l_float32)reduction; /* reduced spat. stdev */
300  if ((bil = (L_BILATERAL *)LEPT_CALLOC(1, sizeof(L_BILATERAL))) == NULL)
301  return (L_BILATERAL *)ERROR_PTR("bil not made", procName, NULL);
302  bil->spatial_stdev = sstdev;
303  bil->range_stdev = range_stdev;
304  bil->reduction = reduction;
305  bil->ncomps = ncomps;
306 
307  if (reduction == 1) {
308  pixt = pixClone(pixs);
309  } else if (reduction == 2) {
310  pixt = pixScaleAreaMap2(pixs);
311  } else { /* reduction == 4) */
312  pixt2 = pixScaleAreaMap2(pixs);
313  pixt = pixScaleAreaMap2(pixt2);
314  pixDestroy(&pixt2);
315  }
316 
317  pixGetExtremeValue(pixt, 1, L_SELECT_MIN, NULL, NULL, NULL, &minval);
318  pixGetExtremeValue(pixt, 1, L_SELECT_MAX, NULL, NULL, NULL, &maxval);
319  bil->minval = minval;
320  bil->maxval = maxval;
321 
322  border = (l_int32)(2 * sstdev + 1);
323  pixsc = pixAddMirroredBorder(pixt, border, border, border, border);
324  bil->pixsc = pixsc;
325  pixDestroy(&pixt);
326  bil->pixs = pixClone(pixs);
327 
328 
329  /* -------------------------------------------------------------------- *
330  * Generate arrays for interpolation of J(k,x):
331  * (1.0 - kfract[.]) * J(kindex[.], x) + kfract[.] * J(kindex[.] + 1, x),
332  * where I(x) is the index into kfract[] and kindex[],
333  * and x is an index into the 2D image array.
334  * -------------------------------------------------------------------- */
335  /* nc is the set of k values to be used in J(k,x) */
336  nc = (l_int32 *)LEPT_CALLOC(ncomps, sizeof(l_int32));
337  for (i = 0; i < ncomps; i++)
338  nc[i] = minval + i * (maxval - minval) / (ncomps - 1);
339  bil->nc = nc;
340 
341  /* kindex maps from intensity I(x) to the lower k index for J(k,x) */
342  kindex = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
343  for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
344  fval2 = nc[k + 1];
345  while (i < fval2) {
346  kindex[i] = k;
347  i++;
348  }
349  }
350  kindex[maxval] = ncomps - 2;
351  bil->kindex = kindex;
352 
353  /* kfract maps from intensity I(x) to the fraction of J(k+1,x) used */
354  kfract = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32)); /* from lower */
355  for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
356  fval1 = nc[k];
357  fval2 = nc[k + 1];
358  while (i < fval2) {
359  kfract[i] = (l_float32)(i - fval1) / (l_float32)(fval2 - fval1);
360  i++;
361  }
362  }
363  kfract[maxval] = 1.0;
364  bil->kfract = kfract;
365 
366 #if DEBUG_BILATERAL
367  for (i = minval; i <= maxval; i++)
368  fprintf(stderr, "kindex[%d] = %d; kfract[%d] = %5.3f\n",
369  i, kindex[i], i, kfract[i]);
370  for (i = 0; i < ncomps; i++)
371  fprintf(stderr, "nc[%d] = %d\n", i, nc[i]);
372 #endif /* DEBUG_BILATERAL */
373 
374 
375  /* -------------------------------------------------------------------- *
376  * Generate 1-D kernel arrays (spatial and range) *
377  * -------------------------------------------------------------------- */
378  spatial_size = 2 * sstdev + 1;
379  spatial = (l_float32 *)LEPT_CALLOC(spatial_size, sizeof(l_float32));
380  denom = 2. * sstdev * sstdev;
381  for (i = 0; i < spatial_size; i++)
382  spatial[i] = expf(-(l_float32)(i * i) / denom);
383  bil->spatial = spatial;
384 
385  range = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32));
386  denom = 2. * range_stdev * range_stdev;
387  for (i = 0; i < 256; i++)
388  range[i] = expf(-(l_float32)(i * i) / denom);
389  bil->range = range;
390 
391 
392  /* -------------------------------------------------------------------- *
393  * Generate principal bilateral component images *
394  * -------------------------------------------------------------------- */
395  pixac = pixaCreate(ncomps);
396  pixGetDimensions(pixsc, &ws, &hs, NULL);
397  datas = pixGetData(pixsc);
398  wpls = pixGetWpl(pixsc);
399  pixGetDimensions(pixs, &w, &h, NULL);
400  wd = (w + reduction - 1) / reduction;
401  hd = (h + reduction - 1) / reduction;
402  halfwidth = (l_int32)(2.0 * sstdev);
403  for (index = 0; index < ncomps; index++) {
404  pixt = pixCopy(NULL, pixsc);
405  datat = pixGetData(pixt);
406  wplt = pixGetWpl(pixt);
407  kval = nc[index];
408  /* Separable convolutions: horizontal first */
409  for (i = 0; i < hd; i++) {
410  lines = datas + (border + i) * wpls;
411  linet = datat + (border + i) * wplt;
412  for (j = 0; j < wd; j++) {
413  sum = 0.0;
414  norm = 0.0;
415  for (k = -halfwidth; k <= halfwidth; k++) {
416  nval = GET_DATA_BYTE(lines, border + j + k);
417  kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
418  sum += kern * nval;
419  norm += kern;
420  }
421  dval = (l_int32)((sum / norm) + 0.5);
422  SET_DATA_BYTE(linet, border + j, dval);
423  }
424  }
425  /* Vertical convolution */
426  pixd = pixCreate(wd, hd, 8);
427  datad = pixGetData(pixd);
428  wpld = pixGetWpl(pixd);
429  for (i = 0; i < hd; i++) {
430  linet = datat + (border + i) * wplt;
431  lined = datad + i * wpld;
432  for (j = 0; j < wd; j++) {
433  sum = 0.0;
434  norm = 0.0;
435  for (k = -halfwidth; k <= halfwidth; k++) {
436  nval = GET_DATA_BYTE(linet + k * wplt, border + j);
437  kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
438  sum += kern * nval;
439  norm += kern;
440  }
441  dval = (l_int32)((sum / norm) + 0.5);
442  SET_DATA_BYTE(lined, j, dval);
443  }
444  }
445  pixDestroy(&pixt);
446  pixaAddPix(pixac, pixd, L_INSERT);
447  }
448  bil->pixac = pixac;
449  bil->lineset = (l_uint32 ***)pixaGetLinePtrs(pixac, NULL);
450 
451  return bil;
452 }
453 
454 
461 static PIX *
463 {
464 l_int32 i, j, k, ired, jred, w, h, wpls, wpld, ncomps, reduction;
465 l_int32 vals, vald, lowval, hival;
466 l_int32 *kindex;
467 l_float32 fract;
468 l_float32 *kfract;
469 l_uint32 *lines, *lined, *datas, *datad;
470 l_uint32 ***lineset = NULL; /* for set of PBC */
471 PIX *pixs, *pixd;
472 PIXA *pixac;
473 
474  PROCNAME("bilateralApply");
475 
476  if (!bil)
477  return (PIX *)ERROR_PTR("bil not defined", procName, NULL);
478  pixs = bil->pixs;
479  ncomps = bil->ncomps;
480  kindex = bil->kindex;
481  kfract = bil->kfract;
482  reduction = bil->reduction;
483  pixac = bil->pixac;
484  lineset = bil->lineset;
485  if (pixaGetCount(pixac) != ncomps)
486  return (PIX *)ERROR_PTR("PBC images do not exist", procName, NULL);
487 
488  if ((pixd = pixCreateTemplate(pixs)) == NULL)
489  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
490  datas = pixGetData(pixs);
491  wpls = pixGetWpl(pixs);
492  datad = pixGetData(pixd);
493  wpld = pixGetWpl(pixd);
494  pixGetDimensions(pixs, &w, &h, NULL);
495  for (i = 0; i < h; i++) {
496  lines = datas + i * wpls;
497  lined = datad + i * wpld;
498  ired = i / reduction;
499  for (j = 0; j < w; j++) {
500  jred = j / reduction;
501  vals = GET_DATA_BYTE(lines, j);
502  k = kindex[vals];
503  lowval = GET_DATA_BYTE(lineset[k][ired], jred);
504  hival = GET_DATA_BYTE(lineset[k + 1][ired], jred);
505  fract = kfract[vals];
506  vald = (l_int32)((1.0 - fract) * lowval + fract * hival + 0.5);
507  SET_DATA_BYTE(lined, j, vald);
508  }
509  }
510 
511  return pixd;
512 }
513 
514 
520 static void
522 {
523 l_int32 i;
524 L_BILATERAL *bil;
525 
526  PROCNAME("bilateralDestroy");
527 
528  if (pbil == NULL) {
529  L_WARNING("ptr address is null!\n", procName);
530  return;
531  }
532 
533  if ((bil = *pbil) == NULL)
534  return;
535 
536  pixDestroy(&bil->pixs);
537  pixDestroy(&bil->pixsc);
538  pixaDestroy(&bil->pixac);
539  LEPT_FREE(bil->spatial);
540  LEPT_FREE(bil->range);
541  LEPT_FREE(bil->nc);
542  LEPT_FREE(bil->kindex);
543  LEPT_FREE(bil->kfract);
544  for (i = 0; i < bil->ncomps; i++)
545  LEPT_FREE(bil->lineset[i]);
546  LEPT_FREE(bil->lineset);
547  LEPT_FREE(bil);
548  *pbil = NULL;
549  return;
550 }
551 
552 
553 /*----------------------------------------------------------------------*
554  * Exact implementation of grayscale or color bilateral filtering *
555  *----------------------------------------------------------------------*/
579 PIX *
581  L_KERNEL *spatial_kel,
582  L_KERNEL *range_kel)
583 {
584 l_int32 d;
585 PIX *pixt, *pixr, *pixg, *pixb, *pixd;
586 
587  PROCNAME("pixBilateralExact");
588  if (!pixs)
589  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
590  if (pixGetColormap(pixs) != NULL)
591  return (PIX *)ERROR_PTR("pixs is cmapped", procName, NULL);
592  d = pixGetDepth(pixs);
593  if (d != 8 && d != 32)
594  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
595  if (!spatial_kel)
596  return (PIX *)ERROR_PTR("spatial_ke not defined", procName, NULL);
597 
598  if (d == 8) {
599  return pixBilateralGrayExact(pixs, spatial_kel, range_kel);
600  } else { /* d == 32 */
601  pixt = pixGetRGBComponent(pixs, COLOR_RED);
602  pixr = pixBilateralGrayExact(pixt, spatial_kel, range_kel);
603  pixDestroy(&pixt);
604  pixt = pixGetRGBComponent(pixs, COLOR_GREEN);
605  pixg = pixBilateralGrayExact(pixt, spatial_kel, range_kel);
606  pixDestroy(&pixt);
607  pixt = pixGetRGBComponent(pixs, COLOR_BLUE);
608  pixb = pixBilateralGrayExact(pixt, spatial_kel, range_kel);
609  pixDestroy(&pixt);
610  pixd = pixCreateRGBImage(pixr, pixg, pixb);
611 
612  pixDestroy(&pixr);
613  pixDestroy(&pixg);
614  pixDestroy(&pixb);
615  return pixd;
616  }
617 }
618 
619 
633 PIX *
635  L_KERNEL *spatial_kel,
636  L_KERNEL *range_kel)
637 {
638 l_int32 i, j, id, jd, k, m, w, h, d, sx, sy, cx, cy, wplt, wpld;
639 l_int32 val, center_val;
640 l_uint32 *datat, *datad, *linet, *lined;
641 l_float32 sum, weight_sum, weight;
642 L_KERNEL *keli;
643 PIX *pixt, *pixd;
644 
645  PROCNAME("pixBilateralGrayExact");
646 
647  if (!pixs)
648  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
649  if (pixGetDepth(pixs) != 8)
650  return (PIX *)ERROR_PTR("pixs must be gray", procName, NULL);
651  pixGetDimensions(pixs, &w, &h, &d);
652  if (!spatial_kel)
653  return (PIX *)ERROR_PTR("spatial kel not defined", procName, NULL);
654 
655  if (!range_kel)
656  return pixConvolve(pixs, spatial_kel, 8, 1);
657  if (range_kel->sx != 256 || range_kel->sy != 1)
658  return (PIX *)ERROR_PTR("range kel not {256 x 1", procName, NULL);
659 
660  keli = kernelInvert(spatial_kel);
661  kernelGetParameters(keli, &sy, &sx, &cy, &cx);
662  if ((pixt = pixAddMirroredBorder(pixs, cx, sx - cx, cy, sy - cy)) == NULL) {
663  kernelDestroy(&keli);
664  return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
665  }
666 
667  pixd = pixCreate(w, h, 8);
668  datat = pixGetData(pixt);
669  datad = pixGetData(pixd);
670  wplt = pixGetWpl(pixt);
671  wpld = pixGetWpl(pixd);
672  for (i = 0, id = 0; id < h; i++, id++) {
673  lined = datad + id * wpld;
674  for (j = 0, jd = 0; jd < w; j++, jd++) {
675  center_val = GET_DATA_BYTE(datat + (i + cy) * wplt, j + cx);
676  weight_sum = 0.0;
677  sum = 0.0;
678  for (k = 0; k < sy; k++) {
679  linet = datat + (i + k) * wplt;
680  for (m = 0; m < sx; m++) {
681  val = GET_DATA_BYTE(linet, j + m);
682  weight = keli->data[k][m] *
683  range_kel->data[0][L_ABS(center_val - val)];
684  weight_sum += weight;
685  sum += val * weight;
686  }
687  }
688  SET_DATA_BYTE(lined, jd, (l_int32)(sum / weight_sum + 0.5));
689  }
690  }
691 
692  kernelDestroy(&keli);
693  pixDestroy(&pixt);
694  return pixd;
695 }
696 
697 
734 PIX*
736  l_float32 spatial_stdev,
737  l_float32 range_stdev)
738 {
739 l_int32 d, halfwidth;
740 L_KERNEL *spatial_kel, *range_kel;
741 PIX *pixd;
742 
743  PROCNAME("pixBlockBilateralExact");
744 
745  if (!pixs)
746  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
747  d = pixGetDepth(pixs);
748  if (d != 8 && d != 32)
749  return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
750  if (pixGetColormap(pixs) != NULL)
751  return (PIX *)ERROR_PTR("pixs is cmapped", procName, NULL);
752  if (spatial_stdev <= 0.0)
753  return (PIX *)ERROR_PTR("invalid spatial stdev", procName, NULL);
754  if (range_stdev <= 0.0)
755  return (PIX *)ERROR_PTR("invalid range stdev", procName, NULL);
756 
757  halfwidth = 2 * spatial_stdev;
758  spatial_kel = makeGaussianKernel(halfwidth, halfwidth, spatial_stdev, 1.0);
759  range_kel = makeRangeKernel(range_stdev);
760  pixd = pixBilateralExact(pixs, spatial_kel, range_kel);
761  kernelDestroy(&spatial_kel);
762  kernelDestroy(&range_kel);
763  return pixd;
764 }
765 
766 
767 /*----------------------------------------------------------------------*
768  * Kernel helper function *
769  *----------------------------------------------------------------------*/
786 L_KERNEL *
787 makeRangeKernel(l_float32 range_stdev)
788 {
789 l_int32 x;
790 l_float32 val, denom;
791 L_KERNEL *kel;
792 
793  PROCNAME("makeRangeKernel");
794 
795  if (range_stdev <= 0.0)
796  return (L_KERNEL *)ERROR_PTR("invalid stdev <= 0", procName, NULL);
797 
798  denom = 2. * range_stdev * range_stdev;
799  if ((kel = kernelCreate(1, 256)) == NULL)
800  return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
801  kernelSetOrigin(kel, 0, 0);
802  for (x = 0; x < 256; x++) {
803  val = expf(-(l_float32)(x * x) / denom);
804  kernelSetElement(kel, 0, x, val);
805  }
806  return kel;
807 }
struct Pix * pixsc
Definition: bilateral.h:118
l_int32 reduction
Definition: bilateral.h:119
PIX * pixBilateral(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
pixBilateral()
Definition: bilateral.c:150
Definition: pix.h:717
L_KERNEL * makeGaussianKernel(l_int32 halfheight, l_int32 halfwidth, l_float32 stdev, l_float32 max)
makeGaussianKernel()
Definition: kernel.c:1137
l_float32 * spatial
Definition: bilateral.h:122
l_float32 ** data
Definition: morph.h:95
l_ok kernelGetParameters(L_KERNEL *kel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
kernelGetParameters()
Definition: kernel.c:270
l_float32 * kfract
Definition: bilateral.h:129
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
static PIX * bilateralApply(L_BILATERAL *bil)
bilateralApply()
Definition: bilateral.c:462
struct Pixa * pixac
Definition: bilateral.h:130
l_int32 * nc
Definition: bilateral.h:127
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
struct Pix * pixs
Definition: bilateral.h:117
PIX * pixAddMirroredBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixAddMirroredBorder()
Definition: pix2.c:2026
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
l_float32 * range
Definition: bilateral.h:123
PIX * pixConvolve(PIX *pixs, L_KERNEL *kel, l_int32 outdepth, l_int32 normflag)
pixConvolve()
Definition: convolve.c:1872
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:367
l_float32 range_stdev
Definition: bilateral.h:121
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2404
l_int32 sy
Definition: morph.h:91
l_ok kernelSetOrigin(L_KERNEL *kel, l_int32 cy, l_int32 cx)
kernelSetOrigin()
Definition: kernel.c:300
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
l_ok pixGetExtremeValue(PIX *pixs, l_int32 factor, l_int32 type, l_int32 *prval, l_int32 *pgval, l_int32 *pbval, l_int32 *pgrayval)
pixGetExtremeValue()
Definition: pix4.c:2141
l_int32 * kindex
Definition: bilateral.h:128
L_KERNEL * makeRangeKernel(l_float32 range_stdev)
makeRangeKernel()
Definition: bilateral.c:787
static L_BILATERAL * bilateralCreate(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
bilateralCreate()
Definition: bilateral.c:280
l_int32 maxval
Definition: bilateral.h:125
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
Definition: pix2.c:2348
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
l_uint32 *** lineset
Definition: bilateral.h:131
void *** pixaGetLinePtrs(PIXA *pixa, l_int32 *psize)
pixaGetLinePtrs()
Definition: pixabasic.c:1193
Definition: pix.h:454
PIX * pixScaleAreaMap2(PIX *pix)
pixScaleAreaMap2()
Definition: scale1.c:2032
PIX * pixBilateralGrayExact(PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel)
pixBilateralGrayExact()
Definition: bilateral.c:634
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
L_KERNEL * kernelInvert(L_KERNEL *kels)
kernelInvert()
Definition: kernel.c:456
void kernelDestroy(L_KERNEL **pkel)
kernelDestroy()
Definition: kernel.c:144
PIX * pixBlockBilateralExact(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev)
pixBlockBilateralExact()
Definition: bilateral.c:735
l_ok kernelSetElement(L_KERNEL *kel, l_int32 row, l_int32 col, l_float32 val)
kernelSetElement()
Definition: kernel.c:243
PIX * pixBilateralGray(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
pixBilateralGray()
Definition: bilateral.c:220
l_int32 ncomps
Definition: bilateral.h:126
PIX * pixBilateralExact(PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel)
pixBilateralExact()
Definition: bilateral.c:580
Definition: morph.h:89
Definition: pix.h:134
static void bilateralDestroy(L_BILATERAL **pbil)
bilateralDestroy()
Definition: bilateral.c:521
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
Definition: pix.h:201
l_float32 spatial_stdev
Definition: bilateral.h:120
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
l_int32 sx
Definition: morph.h:92
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:631
l_int32 minval
Definition: bilateral.h:124
L_KERNEL * kernelCreate(l_int32 height, l_int32 width)
kernelCreate()
Definition: kernel.c:106