Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in foreground/background separator choosing massive block instead of character outline. #52

Open
rmast opened this issue Jun 25, 2022 · 14 comments

Comments

@rmast
Copy link

rmast commented Jun 25, 2022

Partly anonymized replay of my previous finding on compressing the bankstatement with downsampling the foreground, revealing a bug in the foreground-binarizer/separator.

image

Add fg_downsample=12 in compress-pdf-images:

    mrc_gen = create_mrc_hocr_components(pil_image, hocr_word_data,
    #mrc_gen = create_mrc_hocr_components(pil_image, [],
            denoise_mask=DENOISE_FAST,
            bg_downsample=3,
            fg_downsample=12
            )

bankstatementgeknipt8noalphag.zip

ocrmypdf --pdfa-image-compression lossless -O0 --image-dpi 600 bankstatementgeknipt8noalphag.tiff outgeknipt8g.pdf
pdfcomp outgeknipt8g.pdf outgeknipt8-12g.pdf
outgeknipt8-12g.pdf
outgeknipt8g.pdf

@rmast
Copy link
Author

rmast commented Jun 25, 2022

I just looked up the issue myself. There's something wrong with the ratio-determination:
image

The image size for determining the amount of 0's is done with the complete image instead of the text-box.
If you correct that the issue is gone:
image

@rmast
Copy link
Author

rmast commented Jun 25, 2022

By the way, nice tool, PyCharm. It looks somewhat like Intellij that I tried before.

@rmast
Copy link
Author

rmast commented Jun 25, 2022

I created a pull-request for the solution. You might be tempted to even merge it in master .

@MerlijnWajer
Copy link
Collaborator

MerlijnWajer commented Jun 28, 2022

I just looked up the issue myself. There's something wrong with the ratio-determination: ![image](https://user-

Thanks for finding this, this is indeed a real problem. I will take a look and see if this fix is ok, but will need to do some local testing on my test images to make sure everything looks ok.

@MerlijnWajer
Copy link
Collaborator

So with the change from your pull request, there are some regressions for some of my tests, for example

Before:

burn-care-inverted

After:

burn-care-inverted

@MerlijnWajer
Copy link
Collaborator

Removing the *100 makes it better, but some other images still regress, so I will need to spend a bit more time on this later. Thanks for noticing, I also found another typo -- it writes - ones instead of - ones_i.

@rmast
Copy link
Author

rmast commented Jun 28, 2022 via email

@MerlijnWajer
Copy link
Collaborator

I don't remember exactly what I toyed with, but I definitely tried to do something like that: trying to rely on what makes a character vs noise in the bounding box. I think my idea was to use the "ratio", characters usually don't fill up most of the pixels in the bounding box, and if you apply that for an entirely word or even line, then any outliners (e.g. 'w') will be filtered out. That's what the original code was designed to do. On top of that, I then added some simple noise estimation to filter out noise.

I think I locally have some changes that improve somewhat over the current code in my test cases and don't have the bug you found, but I'll need to do further evaluation.

@rmast
Copy link
Author

rmast commented Jun 29, 2022

Continuing on your thought I would expect an if-construction like this:

diff --git a/internetarchivepdf/mrc.py b/internetarchivepdf/mrc.py
index f6290db..e2bb6c0 100644
--- a/internetarchivepdf/mrc.py
+++ b/internetarchivepdf/mrc.py
@@ -237,12 +237,11 @@ def create_hocr_mask(img, mask_arr, hocr_word_data, downsample=None, dpi=None, t
             zero_i = thres_invert[np.where(thres_invert == 0)].size
             inv_ratio = (ones_i/(zero_i+ones_i))*100

+
+
             if ratio < 0.3 or inv_ratio < 0.3:
                 th = None

-                perc_larger = 0.
-                if inv_ratio != 0.0:
-                    perc_larger = (ratio / inv_ratio) * 100

                 if inv_ratio > 0.2 and ratio < 0.2:
                     th = thres
@@ -261,9 +260,16 @@ def create_hocr_mask(img, mask_arr, hocr_word_data, downsample=None, dpi=None, t
                         th = thres_invert
                     elif ratio < 0.2:
                         th = thres
-
-                if th is not None:
-                    mask_arr[top:bottom, left:right] = th
+            else:
+                perc_larger = 0.
+                if inv_ratio != 0.0:
+                    perc_larger = (ratio / inv_ratio) * 100
+                if perc_larger < 50:
+                    th = thres
+                else:
+                    th = thres_invert
+            if th is not None:
+                mask_arr[top:bottom, left:right] = th


     if timing_data is not None:


@rmast
Copy link
Author

rmast commented Jun 29, 2022

By the way, DjVu has an expired patented algorithm for foreground/background separation: https://patents.google.com/patent/US6901169
However it performs less when there's noise in the scan that looks like holes in the mask:
jwilk/didjvu#21

MerlijnWajer added a commit that referenced this issue Aug 1, 2022
This was found by rmast in Github issue #52:

    #52
MerlijnWajer added a commit that referenced this issue Aug 1, 2022
This was found by rmast in Github issue #52:

    #52
@MerlijnWajer
Copy link
Collaborator

MerlijnWajer commented Aug 1, 2022

Just a heads up, I'm branching the current code to a 1.4.x branch so that I can build future archive.org releases based on that, which allows for master to have more "compression" breaking changes.

We performed a lot of QA on the output on current parameters/code, so I don't feel confident just rolling out changes, however minor, so this should set us up to make some more breaking changes in master.

@rmast
Copy link
Author

rmast commented Aug 2, 2022 via email

@MerlijnWajer
Copy link
Collaborator

If you're looking to fix deskew issues mostly automatically, for text content, we use this: https://git.archive.org/archivecd/tesserotate/

It's only applied to our books and microfilm, but it works wonders, in my experience. It's based on Tesseract. It's combined with some heuristics, but by itself it works pretty decently. (Better than leptonica's deskew imho)

@MerlijnWajer
Copy link
Collaborator

In the past I decided not to include deskew and such in archive-pdf-tools, as such preprocessing could be done by another tool, prior to invoking recode_pdf, that's why stuff like this is not included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants