158 l_float32 spatial_stdev,
159 l_float32 range_stdev,
163l_int32 w, h, d, filtersize;
165PIX *pixt, *pixr, *pixg, *pixb, *pixd;
167 if (!pixs || pixGetColormap(pixs))
168 return (
PIX *)ERROR_PTR(
"pixs not defined or cmapped", __func__, NULL);
169 pixGetDimensions(pixs, &w, &h, &d);
170 if (d != 8 && d != 32)
171 return (
PIX *)ERROR_PTR(
"pixs not 8 or 32 bpp", __func__, NULL);
172 if (reduction != 1 && reduction != 2 && reduction != 4)
173 return (
PIX *)ERROR_PTR(
"reduction invalid", __func__, NULL);
174 filtersize = (l_int32)(2.0 * spatial_stdev + 1.0 + 0.5);
175 if (w < 2 * filtersize || h < 2 * filtersize) {
176 L_WARNING(
"w = %d, h = %d; w or h < 2 * filtersize = %d; "
177 "returning copy\n", __func__, w, h, 2 * filtersize);
178 return pixCopy(NULL, pixs);
180 sstdev = spatial_stdev / (l_float32)reduction;
182 return (
PIX *)ERROR_PTR(
"sstdev < 0.5", __func__, NULL);
183 if (range_stdev <= 5.0)
184 return (
PIX *)ERROR_PTR(
"range_stdev <= 5.0", __func__, NULL);
185 if (ncomps < 4 || ncomps > 30)
186 return (
PIX *)ERROR_PTR(
"ncomps not in [4 ... 30]", __func__, NULL);
187 if (ncomps * range_stdev < 100.0)
188 return (
PIX *)ERROR_PTR(
"ncomps * range_stdev < 100.0", __func__, NULL);
194 pixt = pixGetRGBComponent(pixs,
COLOR_RED);
206 pixd = pixCreateRGBImage(pixr, pixg, pixb);
292 l_float32 spatial_stdev,
293 l_float32 range_stdev,
297l_int32 w, ws, wd, h, hs, hd, i, j, k, index;
298l_int32 border, minval, maxval, spatial_size;
299l_int32 halfwidth, wpls, wplt, wpld, kval, nval, dval;
300l_float32 sstdev, fval1, fval2, denom, sum, norm, kern;
302l_float32 *kfract, *range, *spatial;
303l_uint32 *datas, *datat, *datad, *lines, *linet, *lined;
305PIX *pix1, *pix2, *pixt, *pixsc, *pixd;
308 if (reduction == 1) {
309 pix1 = pixClone(pixs);
310 }
else if (reduction == 2) {
311 pix1 = pixScaleAreaMap2(pixs);
313 pix2 = pixScaleAreaMap2(pixs);
314 pix1 = pixScaleAreaMap2(pix2);
318 return (
L_BILATERAL *)ERROR_PTR(
"pix1 not made", __func__, NULL);
320 sstdev = spatial_stdev / (l_float32)reduction;
321 border = (l_int32)(2 * sstdev + 1);
322 pixsc = pixAddMirroredBorder(pix1, border, border, border, border);
323 pixGetExtremeValue(pix1, 1,
L_SELECT_MIN, NULL, NULL, NULL, &minval);
324 pixGetExtremeValue(pix1, 1,
L_SELECT_MAX, NULL, NULL, NULL, &maxval);
327 return (
L_BILATERAL *)ERROR_PTR(
"pixsc not made", __func__, NULL);
337 bil->
pixs = pixClone(pixs);
346 nc = (l_int32 *)LEPT_CALLOC(ncomps,
sizeof(l_int32));
347 for (i = 0; i < ncomps; i++)
348 nc[i] = minval + i * (maxval - minval) / (ncomps - 1);
352 kindex = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
353 for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
360 kindex[maxval] = ncomps - 2;
364 kfract = (l_float32 *)LEPT_CALLOC(256,
sizeof(l_float32));
365 for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
369 kfract[i] = (l_float32)(i - fval1) / (l_float32)(fval2 - fval1);
373 kfract[maxval] = 1.0;
377 for (i = minval; i <= maxval; i++)
378 lept_stderr(
"kindex[%d] = %d; kfract[%d] = %5.3f\n",
379 i, kindex[i], i, kfract[i]);
380 for (i = 0; i < ncomps; i++)
381 lept_stderr(
"nc[%d] = %d\n", i, nc[i]);
387 spatial_size = 2 * sstdev + 1;
388 spatial = (l_float32 *)LEPT_CALLOC(spatial_size,
sizeof(l_float32));
389 denom = 2. * sstdev * sstdev;
390 for (i = 0; i < spatial_size; i++)
391 spatial[i] = expf(-(l_float32)(i * i) / denom);
394 range = (l_float32 *)LEPT_CALLOC(256,
sizeof(l_float32));
395 denom = 2. * range_stdev * range_stdev;
396 for (i = 0; i < 256; i++)
397 range[i] = expf(-(l_float32)(i * i) / denom);
403 pixac = pixaCreate(ncomps);
404 pixGetDimensions(pixsc, &ws, &hs, NULL);
405 datas = pixGetData(pixsc);
406 wpls = pixGetWpl(pixsc);
407 pixGetDimensions(pixs, &w, &h, NULL);
408 wd = (w + reduction - 1) / reduction;
409 hd = (h + reduction - 1) / reduction;
410 halfwidth = (l_int32)(2.0 * sstdev);
411 for (index = 0; index < ncomps; index++) {
412 pixt = pixCopy(NULL, pixsc);
413 datat = pixGetData(pixt);
414 wplt = pixGetWpl(pixt);
417 for (i = 0; i < hd; i++) {
418 lines = datas + (border + i) * wpls;
419 linet = datat + (border + i) * wplt;
420 for (j = 0; j < wd; j++) {
423 for (k = -halfwidth; k <= halfwidth; k++) {
425 kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
430 dval = (l_int32)((sum / norm) + 0.5);
436 pixd = pixCreate(wd, hd, 8);
437 datad = pixGetData(pixd);
438 wpld = pixGetWpl(pixd);
439 for (i = 0; i < hd; i++) {
440 linet = datat + (border + i) * wplt;
441 lined = datad + i * wpld;
442 for (j = 0; j < wd; j++) {
445 for (k = -halfwidth; k <= halfwidth; k++) {
447 kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
452 dval = (l_int32)((sum / norm) + 0.5);
462 bil->
lineset = (l_uint32 ***)pixaGetLinePtrs(pixac, NULL);
476l_int32 i, j, k, ired, jred, w, h, wpls, wpld, ncomps, reduction;
477l_int32 vals, vald, lowval, hival;
481l_uint32 *lines, *lined, *datas, *datad;
482l_uint32 ***lineset = NULL;
487 return (
PIX *)ERROR_PTR(
"bil not defined", __func__, NULL);
495 if (pixaGetCount(pixac) != ncomps)
496 return (
PIX *)ERROR_PTR(
"PBC images do not exist", __func__, NULL);
498 if ((pixd = pixCreateTemplate(pixs)) == NULL)
499 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
500 datas = pixGetData(pixs);
501 wpls = pixGetWpl(pixs);
502 datad = pixGetData(pixd);
503 wpld = pixGetWpl(pixd);
504 pixGetDimensions(pixs, &w, &h, NULL);
505 for (i = 0; i < h; i++) {
506 lines = datas + i * wpls;
507 lined = datad + i * wpld;
508 ired = i / reduction;
509 for (j = 0; j < w; j++) {
510 jred = j / reduction;
515 fract = kfract[vals];
516 vald = (l_int32)((1.0 - fract) * lowval + fract * hival + 0.5);
592PIX *pixt, *pixr, *pixg, *pixb, *pixd;
595 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
596 if (pixGetColormap(pixs) != NULL)
597 return (
PIX *)ERROR_PTR(
"pixs is cmapped", __func__, NULL);
598 d = pixGetDepth(pixs);
599 if (d != 8 && d != 32)
600 return (
PIX *)ERROR_PTR(
"pixs not 8 or 32 bpp", __func__, NULL);
602 return (
PIX *)ERROR_PTR(
"spatial_ke not defined", __func__, NULL);
607 pixt = pixGetRGBComponent(pixs,
COLOR_RED);
616 pixd = pixCreateRGBImage(pixr, pixg, pixb);
644l_int32 i, j, id, jd, k, m, w, h, d, sx, sy, cx, cy, wplt, wpld;
645l_int32 val, center_val;
646l_uint32 *datat, *datad, *linet, *lined;
647l_float32 sum, weight_sum, weight;
652 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
653 if (pixGetDepth(pixs) != 8)
654 return (
PIX *)ERROR_PTR(
"pixs must be gray", __func__, NULL);
655 pixGetDimensions(pixs, &w, &h, &d);
657 return (
PIX *)ERROR_PTR(
"spatial kel not defined", __func__, NULL);
658 kernelGetParameters(spatial_kel, &sy, &sx, NULL, NULL);
659 if (w < 2 * sx + 1 || h < 2 * sy + 1) {
660 L_WARNING(
"w = %d < 2 * sx + 1 = %d, or h = %d < 2 * sy + 1 = %d; "
661 "returning copy\n", __func__, w, 2 * sx + 1, h, 2 * sy + 1);
662 return pixCopy(NULL, pixs);
665 return pixConvolve(pixs, spatial_kel, 8, 1);
666 if (range_kel->
sx != 256 || range_kel->
sy != 1)
667 return (
PIX *)ERROR_PTR(
"range kel not {256 x 1", __func__, NULL);
669 keli = kernelInvert(spatial_kel);
670 kernelGetParameters(keli, &sy, &sx, &cy, &cx);
671 if ((pixt = pixAddMirroredBorder(pixs, cx, sx - cx, cy, sy - cy)) == NULL) {
672 kernelDestroy(&keli);
673 return (
PIX *)ERROR_PTR(
"pixt not made", __func__, NULL);
676 pixd = pixCreate(w, h, 8);
677 datat = pixGetData(pixt);
678 datad = pixGetData(pixd);
679 wplt = pixGetWpl(pixt);
680 wpld = pixGetWpl(pixd);
681 for (i = 0,
id = 0;
id < h; i++,
id++) {
682 lined = datad +
id * wpld;
683 for (j = 0, jd = 0; jd < w; j++, jd++) {
687 for (k = 0; k < sy; k++) {
688 linet = datat + (i + k) * wplt;
689 for (m = 0; m < sx; m++) {
691 weight = keli->
data[k][m] *
692 range_kel->
data[0][L_ABS(center_val - val)];
693 weight_sum += weight;
701 kernelDestroy(&keli);