Leptonica 1.82.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#ifdef HAVE_CONFIG_H
77#include <config_auto.h>
78#endif /* HAVE_CONFIG_H */
79
80#include <math.h>
81#include "allheaders.h"
82#include "bilateral.h"
83
84static L_BILATERAL *bilateralCreate(PIX *pixs, l_float32 spatial_stdev,
85 l_float32 range_stdev, l_int32 ncomps,
86 l_int32 reduction);
87static PIX *bilateralApply(L_BILATERAL *bil);
88static void bilateralDestroy(L_BILATERAL **pbil);
89
90
91#ifndef NO_CONSOLE_IO
92#define DEBUG_BILATERAL 0
93#endif /* ~NO_CONSOLE_IO */
94
95/*--------------------------------------------------------------------------*
96 * Top level approximate separable grayscale or color bilateral filtering *
97 *--------------------------------------------------------------------------*/
156PIX *
158 l_float32 spatial_stdev,
159 l_float32 range_stdev,
160 l_int32 ncomps,
161 l_int32 reduction)
162{
163l_int32 w, h, d, filtersize;
164l_float32 sstdev; /* scaled spatial stdev */
165PIX *pixt, *pixr, *pixg, *pixb, *pixd;
166
167 PROCNAME("pixBilateral");
168
169 if (!pixs || pixGetColormap(pixs))
170 return (PIX *)ERROR_PTR("pixs not defined or cmapped", procName, NULL);
171 pixGetDimensions(pixs, &w, &h, &d);
172 if (d != 8 && d != 32)
173 return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
174 if (reduction != 1 && reduction != 2 && reduction != 4)
175 return (PIX *)ERROR_PTR("reduction invalid", procName, NULL);
176 filtersize = (l_int32)(2.0 * spatial_stdev + 1.0 + 0.5);
177 if (w < 2 * filtersize || h < 2 * filtersize) {
178 L_WARNING("w = %d, h = %d; w or h < 2 * filtersize = %d; "
179 "returning copy\n", procName, w, h, 2 * filtersize);
180 return pixCopy(NULL, pixs);
181 }
182 sstdev = spatial_stdev / (l_float32)reduction; /* reduced spat. stdev */
183 if (sstdev < 0.5)
184 return (PIX *)ERROR_PTR("sstdev < 0.5", procName, NULL);
185 if (range_stdev <= 5.0)
186 return (PIX *)ERROR_PTR("range_stdev <= 5.0", procName, NULL);
187 if (ncomps < 4 || ncomps > 30)
188 return (PIX *)ERROR_PTR("ncomps not in [4 ... 30]", procName, NULL);
189 if (ncomps * range_stdev < 100.0)
190 return (PIX *)ERROR_PTR("ncomps * range_stdev < 100.0", procName, NULL);
191
192 if (d == 8)
193 return pixBilateralGray(pixs, spatial_stdev, range_stdev,
194 ncomps, reduction);
195
196 pixt = pixGetRGBComponent(pixs, COLOR_RED);
197 pixr = pixBilateralGray(pixt, spatial_stdev, range_stdev, ncomps,
198 reduction);
199 pixDestroy(&pixt);
200 pixt = pixGetRGBComponent(pixs, COLOR_GREEN);
201 pixg = pixBilateralGray(pixt, spatial_stdev, range_stdev, ncomps,
202 reduction);
203 pixDestroy(&pixt);
204 pixt = pixGetRGBComponent(pixs, COLOR_BLUE);
205 pixb = pixBilateralGray(pixt, spatial_stdev, range_stdev, ncomps,
206 reduction);
207 pixDestroy(&pixt);
208 pixd = pixCreateRGBImage(pixr, pixg, pixb);
209 pixDestroy(&pixr);
210 pixDestroy(&pixg);
211 pixDestroy(&pixb);
212 return pixd;
213}
214
215
233PIX *
235 l_float32 spatial_stdev,
236 l_float32 range_stdev,
237 l_int32 ncomps,
238 l_int32 reduction)
239{
240l_float32 sstdev; /* scaled spatial stdev */
241PIX *pixd;
242L_BILATERAL *bil;
243
244 PROCNAME("pixBilateralGray");
245
246 if (!pixs || pixGetColormap(pixs))
247 return (PIX *)ERROR_PTR("pixs not defined or cmapped", procName, NULL);
248 if (pixGetDepth(pixs) != 8)
249 return (PIX *)ERROR_PTR("pixs not 8 bpp gray", procName, NULL);
250 if (reduction != 1 && reduction != 2 && reduction != 4)
251 return (PIX *)ERROR_PTR("reduction invalid", procName, NULL);
252 sstdev = spatial_stdev / (l_float32)reduction; /* reduced spat. stdev */
253 if (sstdev < 0.5)
254 return (PIX *)ERROR_PTR("sstdev < 0.5", procName, NULL);
255 if (range_stdev <= 5.0)
256 return (PIX *)ERROR_PTR("range_stdev <= 5.0", procName, NULL);
257 if (ncomps < 4 || ncomps > 30)
258 return (PIX *)ERROR_PTR("ncomps not in [4 ... 30]", procName, NULL);
259 if (ncomps * range_stdev < 100.0)
260 return (PIX *)ERROR_PTR("ncomps * range_stdev < 100.0", procName, NULL);
261
262 bil = bilateralCreate(pixs, spatial_stdev, range_stdev, ncomps, reduction);
263 if (!bil) return (PIX *)ERROR_PTR("bil not made", procName, NULL);
264 pixd = bilateralApply(bil);
265 bilateralDestroy(&bil);
266 return pixd;
267}
268
269
270/*----------------------------------------------------------------------*
271 * Implementation of approximate separable bilateral filter *
272 *----------------------------------------------------------------------*/
294static L_BILATERAL *
296 l_float32 spatial_stdev,
297 l_float32 range_stdev,
298 l_int32 ncomps,
299 l_int32 reduction)
300{
301l_int32 w, ws, wd, h, hs, hd, i, j, k, index;
302l_int32 border, minval, maxval, spatial_size;
303l_int32 halfwidth, wpls, wplt, wpld, kval, nval, dval;
304l_float32 sstdev, fval1, fval2, denom, sum, norm, kern;
305l_int32 *nc, *kindex;
306l_float32 *kfract, *range, *spatial;
307l_uint32 *datas, *datat, *datad, *lines, *linet, *lined;
308L_BILATERAL *bil;
309PIX *pix1, *pix2, *pixt, *pixsc, *pixd;
310PIXA *pixac;
311
312 PROCNAME("bilateralCreate");
313
314 if (reduction == 1) {
315 pix1 = pixClone(pixs);
316 } else if (reduction == 2) {
317 pix1 = pixScaleAreaMap2(pixs);
318 } else { /* reduction == 4) */
319 pix2 = pixScaleAreaMap2(pixs);
320 pix1 = pixScaleAreaMap2(pix2);
321 pixDestroy(&pix2);
322 }
323 if (!pix1)
324 return (L_BILATERAL *)ERROR_PTR("pix1 not made", procName, NULL);
325
326 sstdev = spatial_stdev / (l_float32)reduction; /* reduced spat. stdev */
327 border = (l_int32)(2 * sstdev + 1);
328 pixsc = pixAddMirroredBorder(pix1, border, border, border, border);
329 pixGetExtremeValue(pix1, 1, L_SELECT_MIN, NULL, NULL, NULL, &minval);
330 pixGetExtremeValue(pix1, 1, L_SELECT_MAX, NULL, NULL, NULL, &maxval);
331 pixDestroy(&pix1);
332 if (!pixsc)
333 return (L_BILATERAL *)ERROR_PTR("pixsc not made", procName, NULL);
334
335 bil = (L_BILATERAL *)LEPT_CALLOC(1, sizeof(L_BILATERAL));
336 bil->spatial_stdev = sstdev;
337 bil->range_stdev = range_stdev;
338 bil->reduction = reduction;
339 bil->ncomps = ncomps;
340 bil->minval = minval;
341 bil->maxval = maxval;
342 bil->pixsc = pixsc;
343 bil->pixs = pixClone(pixs);
344
345 /* -------------------------------------------------------------------- *
346 * Generate arrays for interpolation of J(k,x):
347 * (1.0 - kfract[.]) * J(kindex[.], x) + kfract[.] * J(kindex[.] + 1, x),
348 * where I(x) is the index into kfract[] and kindex[],
349 * and x is an index into the 2D image array.
350 * -------------------------------------------------------------------- */
351 /* nc is the set of k values to be used in J(k,x) */
352 nc = (l_int32 *)LEPT_CALLOC(ncomps, sizeof(l_int32));
353 for (i = 0; i < ncomps; i++)
354 nc[i] = minval + i * (maxval - minval) / (ncomps - 1);
355 bil->nc = nc;
356
357 /* kindex maps from intensity I(x) to the lower k index for J(k,x) */
358 kindex = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
359 for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
360 fval2 = nc[k + 1];
361 while (i < fval2) {
362 kindex[i] = k;
363 i++;
364 }
365 }
366 kindex[maxval] = ncomps - 2;
367 bil->kindex = kindex;
368
369 /* kfract maps from intensity I(x) to the fraction of J(k+1,x) used */
370 kfract = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32)); /* from lower */
371 for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
372 fval1 = nc[k];
373 fval2 = nc[k + 1];
374 while (i < fval2) {
375 kfract[i] = (l_float32)(i - fval1) / (l_float32)(fval2 - fval1);
376 i++;
377 }
378 }
379 kfract[maxval] = 1.0;
380 bil->kfract = kfract;
381
382#if DEBUG_BILATERAL
383 for (i = minval; i <= maxval; i++)
384 lept_stderr("kindex[%d] = %d; kfract[%d] = %5.3f\n",
385 i, kindex[i], i, kfract[i]);
386 for (i = 0; i < ncomps; i++)
387 lept_stderr("nc[%d] = %d\n", i, nc[i]);
388#endif /* DEBUG_BILATERAL */
389
390 /* -------------------------------------------------------------------- *
391 * Generate 1-D kernel arrays (spatial and range) *
392 * -------------------------------------------------------------------- */
393 spatial_size = 2 * sstdev + 1; /* same as the added border */
394 spatial = (l_float32 *)LEPT_CALLOC(spatial_size, sizeof(l_float32));
395 denom = 2. * sstdev * sstdev;
396 for (i = 0; i < spatial_size; i++)
397 spatial[i] = expf(-(l_float32)(i * i) / denom);
398 bil->spatial = spatial;
399
400 range = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32));
401 denom = 2. * range_stdev * range_stdev;
402 for (i = 0; i < 256; i++)
403 range[i] = expf(-(l_float32)(i * i) / denom);
404 bil->range = range;
405
406 /* -------------------------------------------------------------------- *
407 * Generate principal bilateral component images *
408 * -------------------------------------------------------------------- */
409 pixac = pixaCreate(ncomps);
410 pixGetDimensions(pixsc, &ws, &hs, NULL);
411 datas = pixGetData(pixsc);
412 wpls = pixGetWpl(pixsc);
413 pixGetDimensions(pixs, &w, &h, NULL);
414 wd = (w + reduction - 1) / reduction;
415 hd = (h + reduction - 1) / reduction;
416 halfwidth = (l_int32)(2.0 * sstdev);
417 for (index = 0; index < ncomps; index++) {
418 pixt = pixCopy(NULL, pixsc);
419 datat = pixGetData(pixt);
420 wplt = pixGetWpl(pixt);
421 kval = nc[index];
422 /* Separable convolutions: horizontal first */
423 for (i = 0; i < hd; i++) {
424 lines = datas + (border + i) * wpls;
425 linet = datat + (border + i) * wplt;
426 for (j = 0; j < wd; j++) {
427 sum = 0.0;
428 norm = 0.0;
429 for (k = -halfwidth; k <= halfwidth; k++) {
430 nval = GET_DATA_BYTE(lines, border + j + k);
431 kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
432 sum += kern * nval;
433 norm += kern;
434 }
435 if (norm > 0.0) {
436 dval = (l_int32)((sum / norm) + 0.5);
437 SET_DATA_BYTE(linet, border + j, dval);
438 }
439 }
440 }
441 /* Vertical convolution */
442 pixd = pixCreate(wd, hd, 8);
443 datad = pixGetData(pixd);
444 wpld = pixGetWpl(pixd);
445 for (i = 0; i < hd; i++) {
446 linet = datat + (border + i) * wplt;
447 lined = datad + i * wpld;
448 for (j = 0; j < wd; j++) {
449 sum = 0.0;
450 norm = 0.0;
451 for (k = -halfwidth; k <= halfwidth; k++) {
452 nval = GET_DATA_BYTE(linet + k * wplt, border + j);
453 kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
454 sum += kern * nval;
455 norm += kern;
456 }
457 if (norm > 0.0)
458 dval = (l_int32)((sum / norm) + 0.5);
459 else
460 dval = GET_DATA_BYTE(linet, border + j);
461 SET_DATA_BYTE(lined, j, dval);
462 }
463 }
464 pixDestroy(&pixt);
465 pixaAddPix(pixac, pixd, L_INSERT);
466 }
467 bil->pixac = pixac;
468 bil->lineset = (l_uint32 ***)pixaGetLinePtrs(pixac, NULL);
469 return bil;
470}
471
472
479static PIX *
481{
482l_int32 i, j, k, ired, jred, w, h, wpls, wpld, ncomps, reduction;
483l_int32 vals, vald, lowval, hival;
484l_int32 *kindex;
485l_float32 fract;
486l_float32 *kfract;
487l_uint32 *lines, *lined, *datas, *datad;
488l_uint32 ***lineset = NULL; /* for set of PBC */
489PIX *pixs, *pixd;
490PIXA *pixac;
491
492 PROCNAME("bilateralApply");
493
494 if (!bil)
495 return (PIX *)ERROR_PTR("bil not defined", procName, NULL);
496 pixs = bil->pixs;
497 ncomps = bil->ncomps;
498 kindex = bil->kindex;
499 kfract = bil->kfract;
500 reduction = bil->reduction;
501 pixac = bil->pixac;
502 lineset = bil->lineset;
503 if (pixaGetCount(pixac) != ncomps)
504 return (PIX *)ERROR_PTR("PBC images do not exist", procName, NULL);
505
506 if ((pixd = pixCreateTemplate(pixs)) == NULL)
507 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
508 datas = pixGetData(pixs);
509 wpls = pixGetWpl(pixs);
510 datad = pixGetData(pixd);
511 wpld = pixGetWpl(pixd);
512 pixGetDimensions(pixs, &w, &h, NULL);
513 for (i = 0; i < h; i++) {
514 lines = datas + i * wpls;
515 lined = datad + i * wpld;
516 ired = i / reduction;
517 for (j = 0; j < w; j++) {
518 jred = j / reduction;
519 vals = GET_DATA_BYTE(lines, j);
520 k = kindex[vals];
521 lowval = GET_DATA_BYTE(lineset[k][ired], jred);
522 hival = GET_DATA_BYTE(lineset[k + 1][ired], jred);
523 fract = kfract[vals];
524 vald = (l_int32)((1.0 - fract) * lowval + fract * hival + 0.5);
525 SET_DATA_BYTE(lined, j, vald);
526 }
527 }
528
529 return pixd;
530}
531
532
538static void
540{
541l_int32 i;
542L_BILATERAL *bil;
543
544 PROCNAME("bilateralDestroy");
545
546 if (pbil == NULL) {
547 L_WARNING("ptr address is null!\n", procName);
548 return;
549 }
550
551 if ((bil = *pbil) == NULL)
552 return;
553
554 pixDestroy(&bil->pixs);
555 pixDestroy(&bil->pixsc);
556 pixaDestroy(&bil->pixac);
557 LEPT_FREE(bil->spatial);
558 LEPT_FREE(bil->range);
559 LEPT_FREE(bil->nc);
560 LEPT_FREE(bil->kindex);
561 LEPT_FREE(bil->kfract);
562 for (i = 0; i < bil->ncomps; i++)
563 LEPT_FREE(bil->lineset[i]);
564 LEPT_FREE(bil->lineset);
565 LEPT_FREE(bil);
566 *pbil = NULL;
567}
568
569
570/*----------------------------------------------------------------------*
571 * Exact implementation of grayscale or color bilateral filtering *
572 *----------------------------------------------------------------------*/
596PIX *
598 L_KERNEL *spatial_kel,
599 L_KERNEL *range_kel)
600{
601l_int32 d;
602PIX *pixt, *pixr, *pixg, *pixb, *pixd;
603
604 PROCNAME("pixBilateralExact");
605 if (!pixs)
606 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
607 if (pixGetColormap(pixs) != NULL)
608 return (PIX *)ERROR_PTR("pixs is cmapped", procName, NULL);
609 d = pixGetDepth(pixs);
610 if (d != 8 && d != 32)
611 return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
612 if (!spatial_kel)
613 return (PIX *)ERROR_PTR("spatial_ke not defined", procName, NULL);
614
615 if (d == 8) {
616 return pixBilateralGrayExact(pixs, spatial_kel, range_kel);
617 } else { /* d == 32 */
618 pixt = pixGetRGBComponent(pixs, COLOR_RED);
619 pixr = pixBilateralGrayExact(pixt, spatial_kel, range_kel);
620 pixDestroy(&pixt);
621 pixt = pixGetRGBComponent(pixs, COLOR_GREEN);
622 pixg = pixBilateralGrayExact(pixt, spatial_kel, range_kel);
623 pixDestroy(&pixt);
624 pixt = pixGetRGBComponent(pixs, COLOR_BLUE);
625 pixb = pixBilateralGrayExact(pixt, spatial_kel, range_kel);
626 pixDestroy(&pixt);
627 pixd = pixCreateRGBImage(pixr, pixg, pixb);
628
629 pixDestroy(&pixr);
630 pixDestroy(&pixg);
631 pixDestroy(&pixb);
632 return pixd;
633 }
634}
635
636
650PIX *
652 L_KERNEL *spatial_kel,
653 L_KERNEL *range_kel)
654{
655l_int32 i, j, id, jd, k, m, w, h, d, sx, sy, cx, cy, wplt, wpld;
656l_int32 val, center_val;
657l_uint32 *datat, *datad, *linet, *lined;
658l_float32 sum, weight_sum, weight;
659L_KERNEL *keli;
660PIX *pixt, *pixd;
661
662 PROCNAME("pixBilateralGrayExact");
663
664 if (!pixs)
665 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
666 if (pixGetDepth(pixs) != 8)
667 return (PIX *)ERROR_PTR("pixs must be gray", procName, NULL);
668 pixGetDimensions(pixs, &w, &h, &d);
669 if (!spatial_kel)
670 return (PIX *)ERROR_PTR("spatial kel not defined", procName, NULL);
671 kernelGetParameters(spatial_kel, &sy, &sx, NULL, NULL);
672 if (w < 2 * sx + 1 || h < 2 * sy + 1) {
673 L_WARNING("w = %d < 2 * sx + 1 = %d, or h = %d < 2 * sy + 1 = %d; "
674 "returning copy\n", procName, w, 2 * sx + 1, h, 2 * sy + 1);
675 return pixCopy(NULL, pixs);
676 }
677 if (!range_kel)
678 return pixConvolve(pixs, spatial_kel, 8, 1);
679 if (range_kel->sx != 256 || range_kel->sy != 1)
680 return (PIX *)ERROR_PTR("range kel not {256 x 1", procName, NULL);
681
682 keli = kernelInvert(spatial_kel);
683 kernelGetParameters(keli, &sy, &sx, &cy, &cx);
684 if ((pixt = pixAddMirroredBorder(pixs, cx, sx - cx, cy, sy - cy)) == NULL) {
685 kernelDestroy(&keli);
686 return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
687 }
688
689 pixd = pixCreate(w, h, 8);
690 datat = pixGetData(pixt);
691 datad = pixGetData(pixd);
692 wplt = pixGetWpl(pixt);
693 wpld = pixGetWpl(pixd);
694 for (i = 0, id = 0; id < h; i++, id++) {
695 lined = datad + id * wpld;
696 for (j = 0, jd = 0; jd < w; j++, jd++) {
697 center_val = GET_DATA_BYTE(datat + (i + cy) * wplt, j + cx);
698 weight_sum = 0.0;
699 sum = 0.0;
700 for (k = 0; k < sy; k++) {
701 linet = datat + (i + k) * wplt;
702 for (m = 0; m < sx; m++) {
703 val = GET_DATA_BYTE(linet, j + m);
704 weight = keli->data[k][m] *
705 range_kel->data[0][L_ABS(center_val - val)];
706 weight_sum += weight;
707 sum += val * weight;
708 }
709 }
710 SET_DATA_BYTE(lined, jd, (l_int32)(sum / weight_sum + 0.5));
711 }
712 }
713
714 kernelDestroy(&keli);
715 pixDestroy(&pixt);
716 return pixd;
717}
718
719
756PIX*
758 l_float32 spatial_stdev,
759 l_float32 range_stdev)
760{
761l_int32 d, halfwidth;
762L_KERNEL *spatial_kel, *range_kel;
763PIX *pixd;
764
765 PROCNAME("pixBlockBilateralExact");
766
767 if (!pixs)
768 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
769 d = pixGetDepth(pixs);
770 if (d != 8 && d != 32)
771 return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
772 if (pixGetColormap(pixs) != NULL)
773 return (PIX *)ERROR_PTR("pixs is cmapped", procName, NULL);
774 if (spatial_stdev <= 0.0)
775 return (PIX *)ERROR_PTR("invalid spatial stdev", procName, NULL);
776 if (range_stdev <= 0.0)
777 return (PIX *)ERROR_PTR("invalid range stdev", procName, NULL);
778
779 halfwidth = 2 * spatial_stdev;
780 spatial_kel = makeGaussianKernel(halfwidth, halfwidth, spatial_stdev, 1.0);
781 range_kel = makeRangeKernel(range_stdev);
782 pixd = pixBilateralExact(pixs, spatial_kel, range_kel);
783 kernelDestroy(&spatial_kel);
784 kernelDestroy(&range_kel);
785 return pixd;
786}
787
788
789/*----------------------------------------------------------------------*
790 * Kernel helper function *
791 *----------------------------------------------------------------------*/
808L_KERNEL *
809makeRangeKernel(l_float32 range_stdev)
810{
811l_int32 x;
812l_float32 val, denom;
813L_KERNEL *kel;
814
815 PROCNAME("makeRangeKernel");
816
817 if (range_stdev <= 0.0)
818 return (L_KERNEL *)ERROR_PTR("invalid stdev <= 0", procName, NULL);
819
820 denom = 2. * range_stdev * range_stdev;
821 if ((kel = kernelCreate(1, 256)) == NULL)
822 return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
823 kernelSetOrigin(kel, 0, 0);
824 for (x = 0; x < 256; x++) {
825 val = expf(-(l_float32)(x * x) / denom);
826 kernelSetElement(kel, 0, x, val);
827 }
828 return kel;
829}
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
static L_BILATERAL * bilateralCreate(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
bilateralCreate()
Definition: bilateral.c:295
static void bilateralDestroy(L_BILATERAL **pbil)
bilateralDestroy()
Definition: bilateral.c:539
PIX * pixBilateralGray(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
pixBilateralGray()
Definition: bilateral.c:234
PIX * pixBilateralGrayExact(PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel)
pixBilateralGrayExact()
Definition: bilateral.c:651
PIX * pixBilateralExact(PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel)
pixBilateralExact()
Definition: bilateral.c:597
PIX * pixBlockBilateralExact(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev)
pixBlockBilateralExact()
Definition: bilateral.c:757
static PIX * bilateralApply(L_BILATERAL *bil)
bilateralApply()
Definition: bilateral.c:480
PIX * pixBilateral(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
pixBilateral()
Definition: bilateral.c:157
L_KERNEL * makeRangeKernel(l_float32 range_stdev)
makeRangeKernel()
Definition: bilateral.c:809
PIX * pixConvolve(PIX *pixs, L_KERNEL *kel, l_int32 outdepth, l_int32 normflag)
pixConvolve()
Definition: convolve.c:1880
L_KERNEL * kernelCreate(l_int32 height, l_int32 width)
kernelCreate()
Definition: kernel.c:112
void kernelDestroy(L_KERNEL **pkel)
kernelDestroy()
Definition: kernel.c:150
l_ok kernelSetOrigin(L_KERNEL *kel, l_int32 cy, l_int32 cx)
kernelSetOrigin()
Definition: kernel.c:304
l_ok kernelGetParameters(L_KERNEL *kel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
kernelGetParameters()
Definition: kernel.c:274
L_KERNEL * makeGaussianKernel(l_int32 halfh, l_int32 halfw, l_float32 stdev, l_float32 max)
makeGaussianKernel()
Definition: kernel.c:1153
l_ok kernelSetElement(L_KERNEL *kel, l_int32 row, l_int32 col, l_float32 val)
kernelSetElement()
Definition: kernel.c:247
L_KERNEL * kernelInvert(L_KERNEL *kels)
kernelInvert()
Definition: kernel.c:460
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
PIX * pixAddMirroredBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixAddMirroredBorder()
Definition: pix2.c:2101
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
Definition: pix2.c:2423
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:2215
@ COLOR_BLUE
Definition: pix.h:206
@ COLOR_RED
Definition: pix.h:204
@ COLOR_GREEN
Definition: pix.h:205
@ L_SELECT_MAX
Definition: pix.h:826
@ L_SELECT_MIN
Definition: pix.h:825
@ L_INSERT
Definition: pix.h:711
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
void *** pixaGetLinePtrs(PIXA *pixa, l_int32 *psize)
pixaGetLinePtrs()
Definition: pixabasic.c:1214
PIX * pixScaleAreaMap2(PIX *pix)
pixScaleAreaMap2()
Definition: scale1.c:2047
l_int32 * nc
Definition: bilateral.h:127
l_float32 range_stdev
Definition: bilateral.h:121
l_uint32 *** lineset
Definition: bilateral.h:131
l_float32 * kfract
Definition: bilateral.h:129
l_int32 reduction
Definition: bilateral.h:119
l_float32 * range
Definition: bilateral.h:123
l_int32 ncomps
Definition: bilateral.h:126
struct Pix * pixs
Definition: bilateral.h:117
struct Pixa * pixac
Definition: bilateral.h:130
l_float32 spatial_stdev
Definition: bilateral.h:120
l_float32 * spatial
Definition: bilateral.h:122
l_int32 * kindex
Definition: bilateral.h:128
struct Pix * pixsc
Definition: bilateral.h:118
l_int32 minval
Definition: bilateral.h:124
l_int32 maxval
Definition: bilateral.h:125
Definition: morph.h:89
l_int32 sx
Definition: morph.h:91
l_float32 ** data
Definition: morph.h:94
l_int32 sy
Definition: morph.h:90
Definition: pix.h:139
Definition: pix.h:456
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306