Skip to content

Commit 4bb6008

Browse files
committed
2.1: threshold: EdgePlus
1 parent 9521314 commit 4bb6008

File tree

6 files changed

+103
-33
lines changed

6 files changed

+103
-33
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#MFBdjvu-1.0
1+
#MFBdjvu
22
#
33
#Based on djvulibre (http://djvu.sourceforge.net/)
44
#Based on monday2000 (http://djvu-soft.narod.ru/)

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ where options =
5353

5454
**-slices_fg n1,n2,...** {100} Use *n1,n2,...* as number of slices for c44 for foreground {== -quality 75}.
5555

56-
**-threshold str** {djvul} threshold: djvul, bimod, sauvola, blur
56+
**-threshold str** {djvul} threshold: djvul, bimod, sauvola, blur, edgeplus
5757

5858
**-levels n** {0} Level DjVuL block, 0 - auto.
5959

@@ -95,3 +95,4 @@ The new algorithm allowed not only to obtain a much more adequate result, but al
9595
* [hocr-tools](https://github.com/ocropus/hocr-tools)
9696
* [imthreshold](https://github.com/ImageProcessing-ElectronicPublications/imthreshold)
9797
* [aithreshold](https://github.com/ImageProcessing-ElectronicPublications/aithreshold)
98+
* [EdgePlus](https://github.com/ScanTailor-Advanced/scantailor-advanced/pull/48)

man/man1/mfbdjvu.1

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.TH "MFBdjuu" 1 2.0 "26 Jan 2023" "User Manual"
1+
.TH "MFBdjuu" 1 2.1 "08 Jun 2023" "User Manual"
22

33
.SH NAME
44
mfbdjvu
@@ -34,7 +34,7 @@ mfbdjvu [options] input.pnm output.djvu
3434
{100} Use n1,n2,... as number of slices for c44 for foreground {== -quality 75}.
3535
.TP
3636
--threshold str
37-
{djvul} threshold: djvul, bimod, sauvola, blur
37+
{djvul} threshold: djvul, bimod, sauvola, blur, edgeplus
3838
.TP
3939
-levels n
4040
{0} Level DjVuL block, 0 - auto.
@@ -106,3 +106,4 @@ Website: https://github.com/ImageProcessing-ElectronicPublications/mfbdjvu
106106
[hocr-tools](https://github.com/ocropus/hocr-tools)
107107
[imthreshold](https://github.com/ImageProcessing-ElectronicPublications/imthreshold)
108108
[aithreshold](https://github.com/ImageProcessing-ElectronicPublications/aithreshold)
109+
[EdgePlus](https://github.com/ScanTailor-Advanced/scantailor-advanced/pull/48)

src/djvul.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#ifndef DJVUL_H_
66
#define DJVUL_H_
7-
#define DJVUL_VERSION "3.0"
7+
#define DJVUL_VERSION "3.1"
88

99
#include <stdbool.h>
1010
#include <math.h>
@@ -34,6 +34,7 @@ DJVULAPI int ImageDjvulSelect(unsigned char* buf, bool* bufmask, unsigned char*
3434
#define TBIMOD 1
3535
#define TSAUVOLA 2
3636
#define TBLUR 3
37+
#define TEDGEPLUS 4
3738

3839
#ifdef DJVUL_IMPLEMENTATION
3940

@@ -115,7 +116,7 @@ DJVULAPI int ImageDjvulThreshold(unsigned char* buf, bool* bufmask, unsigned cha
115116
{
116117
doverlay = 0.0f;
117118
}
118-
kover = doverlay + 1.0;
119+
kover = doverlay + 1.0f;
119120

120121
// w/b mode {1/-1}
121122
if (wbmode < 0)
@@ -278,7 +279,7 @@ DJVULAPI int ImageDjvulThreshold(unsigned char* buf, bool* bufmask, unsigned cha
278279
{
279280
fgk = (bgdist - fgdist) / fgk;
280281
fgk *= anisotropic;
281-
fgk = exp(fgk);
282+
fgk = (float)(exp(fgk));
282283
}
283284
else
284285
{
@@ -527,7 +528,7 @@ DJVULAPI int ImageDjvulGround(unsigned char* buf, bool* bufmask, unsigned char*
527528
{
528529
doverlay = 0.0f;
529530
}
530-
kover = doverlay + 1.0;
531+
kover = doverlay + 1.0f;
531532

532533
fgbase = 127;
533534
bgbase = 127;
@@ -996,6 +997,10 @@ DJVULAPI int ImageDjvulSelect(unsigned char* buf, bool* bufmask, unsigned char*
996997
(void)ImageThresholdBlur(buf, bufmask, width, height, channels, radius, fbscale, delta, sensitivity);
997998
return ImageDjvulGround(buf, bufmask, bufbg, buffg, width, height, channels, bgs, level, doverlay);
998999
break;
1000+
case TEDGEPLUS:
1001+
(void)ImageThresholdEdgePlus(buf, bufmask, width, height, channels, radius, fbscale, delta, sensitivity);
1002+
return ImageDjvulGround(buf, bufmask, bufbg, buffg, width, height, channels, bgs, level, doverlay);
1003+
break;
9991004
default:
10001005
return ImageDjvulThreshold(buf, bufmask, bufbg, buffg, width, height, channels, bgs, level, wbmode, doverlay, anisotropic, contrast, fbscale, delta);
10011006
break;

src/mfbdjvu.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/*
2-
* MFBdjvu-1.6
2+
* MFBdjvu
33
* Based on simpledjvu, djvul and djvulibre (http://djvu.sourceforge.net/)
44
*
55
*/
66

7-
#define MFBDJVU_VERSION "2.0"
7+
#define MFBDJVU_VERSION "2.1"
88

99
#include <iostream>
1010
#include <cstdlib>
@@ -107,7 +107,7 @@ void print_help()
107107
<< "\t-quality n {75}\n"
108108
<< "\t-slices_bg n1,n2,.. {74,84,88,97}\n"
109109
<< "\t-slices_fg n1,n2,...{100}\n"
110-
<< "\t-threshold str {djvul}\n"
110+
<< "\t-threshold str {djvul}: djvul, bimod, sauvola, blur, edgeplus\n"
111111
<< "\t-levels n {0}\n"
112112
<< "\t-bgs n {3}\n"
113113
<< "\t-fgs n {2}\n"
@@ -247,6 +247,8 @@ bool parse_keys(int argc, char *argv[], Keys *keys, char **input, char **output)
247247
keys->threshold = TSAUVOLA;
248248
else if (strcmp(nptr, "blur") == 0)
249249
keys->threshold = TBLUR;
250+
else if (strcmp(nptr, "edgeplus") == 0)
251+
keys->threshold = TEDGEPLUS;
250252
}
251253
else if (arg == "-mask")
252254
{

src/threshold.h

Lines changed: 83 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#ifndef THRESHOLD_H_
66
#define THRESHOLD_H_
7-
#define THRESHOLD_VERSION "3.0"
7+
#define THRESHOLD_VERSION "3.1"
88

99
#include <stdbool.h>
1010
#include <math.h>
@@ -23,6 +23,7 @@ THRESHOLDAPI int ImageThreshold(unsigned char* buf, bool* bufmask, unsigned int
2323
THRESHOLDAPI int ImageThresholdBimod(unsigned char* buf, bool* bufmask, unsigned int width, unsigned int height, unsigned int channels, float part, float delta);
2424
THRESHOLDAPI int ImageThresholdSauvola(unsigned char* buf, bool* bufmask, unsigned int width, unsigned int height, unsigned int channels, int radius, float sensitivity, float part, int lower_bound, int upper_bound, float delta);
2525
THRESHOLDAPI int ImageThresholdBlur(unsigned char* buf, bool* bufmask, unsigned int width, unsigned int height, unsigned int channels, float raduis, float part, float delta, float sensitivity);
26+
THRESHOLDAPI int ImageThresholdEdgePlus(unsigned char* buf, bool* bufmask, unsigned int width, unsigned int height, unsigned int channels, float raduis, float part, float delta, float sensitivity);
2627

2728
#ifdef __cplusplus
2829
}
@@ -150,7 +151,7 @@ static void GaussLineMatrix (float *cmatrix, float radius)
150151
t -= 0.5f;
151152
t += step * j;
152153
tt = -(t * t) / (2.0f * std_dev);
153-
sum += exp (tt);
154+
sum += (float)(exp(tt));
154155
}
155156
cmatrix[i] = sum * step;
156157
}
@@ -170,7 +171,7 @@ static void GaussLineMatrix (float *cmatrix, float radius)
170171
}
171172
}
172173

173-
static float GaussBlurFilterY (unsigned char *src, int height, int width, int channels, float radius)
174+
static float GaussBlurFilterY (unsigned char *src, unsigned int height, unsigned int width, unsigned int channels, float radius)
174175
{
175176
int iradius, y, x, yp, yn, i, dval;
176177
unsigned long int k, kp, kn, line = width * channels;
@@ -199,9 +200,9 @@ static float GaussBlurFilterY (unsigned char *src, int height, int width, int ch
199200
if (iradius > 1)
200201
{
201202
k = 0;
202-
for (y = 0; y < height; y++)
203+
for (y = 0; y < (int)height; y++)
203204
{
204-
for (x = 0; x < width; x++)
205+
for (x = 0; x < (int)width; x++)
205206
{
206207
for (d = 0; d < channels; d++)
207208
{
@@ -221,7 +222,7 @@ static float GaussBlurFilterY (unsigned char *src, int height, int width, int ch
221222
kp -= line;
222223
}
223224
yn = y + i;
224-
if (yn < height)
225+
if (yn < (int)height)
225226
{
226227
kn += line;
227228
}
@@ -242,9 +243,9 @@ static float GaussBlurFilterY (unsigned char *src, int height, int width, int ch
242243
}
243244
}
244245
k = 0;
245-
for (y = 0; y < height; y++)
246+
for (y = 0; y < (int)height; y++)
246247
{
247-
for (x = 0; x < width; x++)
248+
for (x = 0; x < (int)width; x++)
248249
{
249250
for (d = 0; d < channels; d++)
250251
{
@@ -264,7 +265,7 @@ static float GaussBlurFilterY (unsigned char *src, int height, int width, int ch
264265
return gaussval;
265266
}
266267

267-
static float GaussBlurFilterX (unsigned char *src, int height, int width, int channels, float radius)
268+
static float GaussBlurFilterX (unsigned char *src, unsigned int height, unsigned int width, unsigned int channels, float radius)
268269
{
269270
int iradius, y, x, xp, xn, i, dval;
270271
unsigned long int k, kp, kn;
@@ -293,9 +294,9 @@ static float GaussBlurFilterX (unsigned char *src, int height, int width, int ch
293294
if (iradius > 1)
294295
{
295296
k = 0;
296-
for (y = 0; y < height; y++)
297+
for (y = 0; y < (int)height; y++)
297298
{
298-
for (x = 0; x < width; x++)
299+
for (x = 0; x < (int)width; x++)
299300
{
300301
for (d = 0; d < channels; d++)
301302
{
@@ -315,7 +316,7 @@ static float GaussBlurFilterX (unsigned char *src, int height, int width, int ch
315316
kp -= channels;
316317
}
317318
xn = x + i;
318-
if (xn < width)
319+
if (xn < (int)width)
319320
{
320321
kn += channels;
321322
}
@@ -336,9 +337,9 @@ static float GaussBlurFilterX (unsigned char *src, int height, int width, int ch
336337
}
337338
}
338339
k = 0;
339-
for (y = 0; y < height; y++)
340+
for (y = 0; y < (int)height; y++)
340341
{
341-
for (x = 0; x < width; x++)
342+
for (x = 0; x < (int)width; x++)
342343
{
343344
for (d = 0; d < channels; d++)
344345
{
@@ -464,7 +465,7 @@ THRESHOLDAPI int ImageThresholdBimod(unsigned char* buf, bool* bufmask, unsigned
464465
ImageHist(buf, histogram, width, height, channels, Tmax);
465466
part *= 0.5f;
466467
threshold = HistBiMod (histogram, Tmax, part);
467-
threshold += delta;
468+
threshold += (int)delta;
468469
threshold = ImageThreshold(buf, bufmask, width, height, channels, threshold);
469470

470471
return threshold;
@@ -517,11 +518,11 @@ THRESHOLDAPI int ImageThresholdSauvola(unsigned char* buf, bool* bufmask, unsign
517518
km = 0;
518519
for (y = 0; y < height; y++)
519520
{
520-
y1 = (y < radius) ? 0 : (y - radius);
521+
y1 = (y < (unsigned int)radius) ? 0 : (y - (unsigned int)radius);
521522
y2 = (y + radius + 1 < height) ? (y + radius + 1) : height;
522523
for (x = 0; x < width; x++)
523524
{
524-
x1 = (x < radius) ? 0 : (x - radius);
525+
x1 = (x < (unsigned int)radius) ? 0 : (x - (unsigned int)radius);
525526
x2 = (x + radius + 1 < width) ? (x + radius + 1) : width;
526527
imm = 0;
527528
imv = 0;
@@ -546,8 +547,8 @@ THRESHOLDAPI int ImageThresholdSauvola(unsigned char* buf, bool* bufmask, unsign
546547
imv /= n;
547548
imv -= (imm * imm);
548549
imv = (imv < 0) ? -imv : imv;
549-
imv = sqrt(imv);
550-
ima = 1.0 - imv / dynamic_range;
550+
imv = (float)(sqrt(imv));
551+
ima = 1.0f - imv / dynamic_range;
551552
imx = 0.0f;
552553
for (d = 0; d < channels; d++)
553554
{
@@ -564,7 +565,7 @@ THRESHOLDAPI int ImageThresholdSauvola(unsigned char* buf, bool* bufmask, unsign
564565
}
565566
else
566567
{
567-
t = imm * (1.0 - sensitivity * ima) + delta;
568+
t = imm * (1.0f - sensitivity * ima) + delta;
568569
}
569570
bufmask[km] = (imx < t);
570571
km++;
@@ -627,11 +628,71 @@ THRESHOLDAPI int ImageThresholdBlur(unsigned char* buf, bool* bufmask, unsigned
627628
}
628629
}
629630
ImageMathDivide(buf, bufb, bufb, width, height, channels, -127.0f);
631+
threshold = ImageThresholdBimod(bufb, bufmask, width, height, channels, part, delta);
632+
free(bufb);
633+
}
634+
else
635+
{
636+
threshold = ImageThresholdBimod(buf, bufmask, width, height, channels, part, delta);
630637
}
631638

632-
threshold = ImageThresholdBimod(bufb, bufmask, width, height, channels, part, delta);
633-
if (bufb)
639+
return threshold;
640+
}
641+
642+
/*
643+
ImageThresholdEdgePlus()
644+
645+
input:
646+
buf - unsigned char* image (height * width * channels)
647+
part = 1.0f [1:1]
648+
delta = 0.0f [off, regulator]
649+
sensitivity = 0.2;
650+
651+
output:
652+
bufmask - bool* image mask (height * width)
653+
threshold - threshold value
654+
655+
Use:
656+
int threshold = ImageThresholdEdgePlus(buf, bufmask, width, height, channels, raduis, part, delta, sensitivity);
657+
*/
658+
659+
THRESHOLDAPI int ImageThresholdEdgePlus(unsigned char* buf, bool* bufmask, unsigned int width, unsigned int height, unsigned int channels, float raduis, float part, float delta, float sensitivity)
660+
{
661+
int threshold = 0;
662+
unsigned int y, x, d;
663+
float imo, imx, edge, edgeplus;
664+
unsigned long int k;
665+
unsigned char *bufb = NULL;
666+
667+
if ((bufb = (unsigned char*)malloc(height * width * channels * sizeof(unsigned char))))
668+
{
669+
ImageCopy(buf, bufb, width, height, channels);
670+
(void)GaussBlurFilter(bufb, width, height, channels, raduis, raduis);
671+
k = 0;
672+
for (y = 0; y < height; y++)
673+
{
674+
for (x = 0; x < width; x++)
675+
{
676+
for (d = 0; d < channels; d++)
677+
{
678+
imo = (float)buf[k];
679+
imx = (float)bufb[k];
680+
edge = (imo + 1.0f) / (imx + 1.0f) - 0.5f;
681+
edgeplus = imo * edge;
682+
imx = sensitivity * edgeplus + (1.0f - sensitivity) * imo;
683+
imx = (imx < 0.0f) ? 0.0f : (imx < 255.0f) ? imx : 255.0f;
684+
bufb[k] = (unsigned char)imx;
685+
k++;
686+
}
687+
}
688+
}
689+
threshold = ImageThresholdBimod(bufb, bufmask, width, height, channels, part, delta);
634690
free(bufb);
691+
}
692+
else
693+
{
694+
threshold = ImageThresholdBimod(buf, bufmask, width, height, channels, part, delta);
695+
}
635696

636697
return threshold;
637698
}

0 commit comments

Comments
 (0)