77 #include <config_auto.h> 81 #include "allheaders.h" 85 l_float32 range_stdev, l_int32 ncomps,
92 #define DEBUG_BILATERAL 0 158 l_float32 spatial_stdev,
159 l_float32 range_stdev,
163 l_int32 w, h, d, filtersize;
165 PIX *pixt, *pixr, *pixg, *pixb, *pixd;
167 PROCNAME(
"pixBilateral");
169 if (!pixs || pixGetColormap(pixs))
170 return (
PIX *)ERROR_PTR(
"pixs not defined or cmapped", procName, NULL);
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);
182 sstdev = spatial_stdev / (l_float32)reduction;
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);
235 l_float32 spatial_stdev,
236 l_float32 range_stdev,
244 PROCNAME(
"pixBilateralGray");
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;
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);
262 bil =
bilateralCreate(pixs, spatial_stdev, range_stdev, ncomps, reduction);
263 if (!bil)
return (
PIX *)ERROR_PTR(
"bil not made", procName, NULL);
296 l_float32 spatial_stdev,
297 l_float32 range_stdev,
301 l_int32 w, ws, wd, h, hs, hd, i, j, k, index;
302 l_int32 border, minval, maxval, spatial_size;
303 l_int32 halfwidth, wpls, wplt, wpld, kval, nval, dval;
304 l_float32 sstdev, fval1, fval2, denom, sum, norm, kern;
305 l_int32 *nc, *kindex;
306 l_float32 *kfract, *range, *spatial;
307 l_uint32 *datas, *datat, *datad, *lines, *linet, *lined;
309 PIX *pix1, *pix2, *pixt, *pixsc, *pixd;
312 PROCNAME(
"bilateralCreate");
314 if (reduction == 1) {
316 }
else if (reduction == 2) {
324 return (
L_BILATERAL *)ERROR_PTR(
"pix1 not made", procName, NULL);
326 sstdev = spatial_stdev / (l_float32)reduction;
327 border = (l_int32)(2 * sstdev + 1);
333 return (
L_BILATERAL *)ERROR_PTR(
"pixsc not made", procName, NULL);
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);
358 kindex = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
359 for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
366 kindex[maxval] = ncomps - 2;
370 kfract = (l_float32 *)LEPT_CALLOC(256,
sizeof(l_float32));
371 for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
375 kfract[i] = (l_float32)(i - fval1) / (l_float32)(fval2 - fval1);
379 kfract[maxval] = 1.0;
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++)
393 spatial_size = 2 * sstdev + 1;
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);
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);
412 wpls = pixGetWpl(pixsc);
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++) {
420 wplt = pixGetWpl(pixt);
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++) {
429 for (k = -halfwidth; k <= halfwidth; k++) {
431 kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
436 dval = (l_int32)((sum / norm) + 0.5);
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++) {
451 for (k = -halfwidth; k <= halfwidth; k++) {
453 kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
458 dval = (l_int32)((sum / norm) + 0.5);
482 l_int32 i, j, k, ired, jred, w, h, wpls, wpld, ncomps, reduction;
483 l_int32 vals, vald, lowval, hival;
487 l_uint32 *lines, *lined, *datas, *datad;
488 l_uint32 ***lineset = NULL;
492 PROCNAME(
"bilateralApply");
495 return (
PIX *)ERROR_PTR(
"bil not defined", procName, NULL);
504 return (
PIX *)ERROR_PTR(
"PBC images do not exist", procName, NULL);
507 return (
PIX *)ERROR_PTR(
"pixd not made", procName, NULL);
509 wpls = pixGetWpl(pixs);
511 wpld = pixGetWpl(pixd);
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;
523 fract = kfract[vals];
524 vald = (l_int32)((1.0 - fract) * lowval + fract * hival + 0.5);
544 PROCNAME(
"bilateralDestroy");
547 L_WARNING(
"ptr address is null!\n", procName);
551 if ((bil = *pbil) == NULL)
558 LEPT_FREE(bil->
range);
562 for (i = 0; i < bil->
ncomps; i++)
602 PIX *pixt, *pixr, *pixg, *pixb, *pixd;
604 PROCNAME(
"pixBilateralExact");
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);
613 return (
PIX *)ERROR_PTR(
"spatial_ke not defined", procName, NULL);
655 l_int32 i, j, id, jd, k, m, w, h, d, sx, sy, cx, cy, wplt, wpld;
656 l_int32 val, center_val;
657 l_uint32 *datat, *datad, *linet, *lined;
658 l_float32 sum, weight_sum, weight;
662 PROCNAME(
"pixBilateralGrayExact");
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);
670 return (
PIX *)ERROR_PTR(
"spatial kel not defined", procName, 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);
679 if (range_kel->
sx != 256 || range_kel->
sy != 1)
680 return (
PIX *)ERROR_PTR(
"range kel not {256 x 1", procName, NULL);
686 return (
PIX *)ERROR_PTR(
"pixt not made", procName, NULL);
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++) {
700 for (k = 0; k < sy; k++) {
701 linet = datat + (i + k) * wplt;
702 for (m = 0; m < sx; m++) {
704 weight = keli->
data[k][m] *
705 range_kel->
data[0][L_ABS(center_val - val)];
706 weight_sum += weight;
758 l_float32 spatial_stdev,
759 l_float32 range_stdev)
761 l_int32 d, halfwidth;
765 PROCNAME(
"pixBlockBilateralExact");
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);
779 halfwidth = 2 * spatial_stdev;
812 l_float32 val, denom;
815 PROCNAME(
"makeRangeKernel");
817 if (range_stdev <= 0.0)
818 return (
L_KERNEL *)ERROR_PTR(
"invalid stdev <= 0", procName, NULL);
820 denom = 2. * range_stdev * range_stdev;
822 return (
L_KERNEL *)ERROR_PTR(
"kel not made", procName, NULL);
824 for (x = 0; x < 256; x++) {
825 val = expf(-(l_float32)(x * x) / denom);
PIX * pixBilateral(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
pixBilateral()
l_ok kernelGetParameters(L_KERNEL *kel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
kernelGetParameters()
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
PIXA * pixaCreate(l_int32 n)
pixaCreate()
static PIX * bilateralApply(L_BILATERAL *bil)
bilateralApply()
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
void lept_stderr(const char *fmt,...)
lept_stderr()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
PIX * pixAddMirroredBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixAddMirroredBorder()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
PIX * pixConvolve(PIX *pixs, L_KERNEL *kel, l_int32 outdepth, l_int32 normflag)
pixConvolve()
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
l_ok kernelSetOrigin(L_KERNEL *kel, l_int32 cy, l_int32 cx)
kernelSetOrigin()
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
l_ok pixGetExtremeValue(PIX *pixs, l_int32 factor, l_int32 type, l_int32 *prval, l_int32 *pgval, l_int32 *pbval, l_int32 *pgrayval)
pixGetExtremeValue()
L_KERNEL * makeRangeKernel(l_float32 range_stdev)
makeRangeKernel()
static L_BILATERAL * bilateralCreate(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
bilateralCreate()
#define SET_DATA_BYTE(pdata, n, val)
#define GET_DATA_BYTE(pdata, n)
L_KERNEL * makeGaussianKernel(l_int32 halfh, l_int32 halfw, l_float32 stdev, l_float32 max)
makeGaussianKernel()
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
PIX * pixClone(PIX *pixs)
pixClone()
void pixDestroy(PIX **ppix)
pixDestroy()
void *** pixaGetLinePtrs(PIXA *pixa, l_int32 *psize)
pixaGetLinePtrs()
PIX * pixScaleAreaMap2(PIX *pix)
pixScaleAreaMap2()
PIX * pixBilateralGrayExact(PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel)
pixBilateralGrayExact()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
L_KERNEL * kernelInvert(L_KERNEL *kels)
kernelInvert()
void kernelDestroy(L_KERNEL **pkel)
kernelDestroy()
PIX * pixBlockBilateralExact(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev)
pixBlockBilateralExact()
l_ok kernelSetElement(L_KERNEL *kel, l_int32 row, l_int32 col, l_float32 val)
kernelSetElement()
PIX * pixBilateralGray(PIX *pixs, l_float32 spatial_stdev, l_float32 range_stdev, l_int32 ncomps, l_int32 reduction)
pixBilateralGray()
PIX * pixBilateralExact(PIX *pixs, L_KERNEL *spatial_kel, L_KERNEL *range_kel)
pixBilateralExact()
static void bilateralDestroy(L_BILATERAL **pbil)
bilateralDestroy()
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
L_KERNEL * kernelCreate(l_int32 height, l_int32 width)
kernelCreate()