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

The extracted table box coordinates do not correspond to the images converted from the PDF #486

Open
SWHL opened this issue Jun 15, 2022 · 8 comments

Comments

@SWHL
Copy link

SWHL commented Jun 15, 2022

Checklist

  1. I have searched related issues but cannot get the expected help.
  2. The bug has not been fixed in the latest version.

Describe the bug

  • The extracted table box coordinates do not correspond to the images converted from the PDF.

Environment

  • OS: CentOS 7
  • Python: 3.7.11
  • camelot-py: 0.10.1

Reproduction

  • Run the following code: (foo.pdf)
    import camelot
    import copy
    import cv2
    
    
    def draw_bbox(img, start_point, end_point, ratio=1):
        start_point = tuple(map(lambda x: round(x * ratio), start_point))
        end_point = tuple(map(lambda x: round(x * ratio), end_point))
        cv2.rectangle(img, start_point, end_point, (0, 255, 0), 2)
    
    
    pdf_path = 'foo.pdf'
    tables = camelot.read_pdf(pdf_path, flavor='lattice', backend="poppler")
    table = tables[0]
    
    table_x0, table_y0, table_x1, table_y1 = table._bbox
    img = table._image[0]
    
    tmp_img = copy.deepcopy(img)
    draw_bbox(tmp_img,
              start_point=(table_x0, table_y0),
              end_point=(table_x1, table_y1),
              ratio=1)
    cv2.imwrite('foo.jpg', tmp_img)
  • The code runs as follows, the green rectangle box indicates the position of the extracted table coordinates in the extracted image from the PDF. Meanwhile, the red rectangle box at the bottom of the image is the correct desired box.

t1

Bug fix

import camelot
import copy
import cv2


def draw_bbox(img, start_point, end_point, ratio=1):
    start_point = tuple(map(lambda x: round(x * ratio), start_point))
    end_point = tuple(map(lambda x: round(x * ratio), end_point))
    cv2.rectangle(img, start_point, end_point, (0, 255, 0), 2)


pdf_path = 'foo.pdf'
tables = camelot.read_pdf(pdf_path, flavor='lattice', backend="poppler")
table = tables[0]

table_x0, table_y0, table_x1, table_y1 = table._bbox
img = table._image[0]

ratio = 300 / 72
new_tmp_img = copy.deepcopy(img)
pdf_height = img.shape[0] / ratio
draw_bbox(new_tmp_img,
          start_point=(table_x0, pdf_height - table_y0),
          end_point=(table_x1, pdf_height - table_y1),
          ratio=ratio)
cv2.imwrite('foo_right.jpg', new_tmp_img)

t2

@LxYuan0420
Copy link

Curious to know how you get this exact value of ratio = 300 / 72 and does it work for another pdf?

@SWHL
Copy link
Author

SWHL commented Jul 12, 2022

Answer the question 1:

When the camelot package obtains the box coordinates by the pdfminer package, whose resolution's default value is 72 (I fogot to where I saw it), but when the camelot obtains the image by the read_pdf function, whose resolution's default value is 300.

resolution* : int, optional (default: 300)

Answer the question 2:

You can try others.

@baleris
Copy link

baleris commented May 17, 2023

@SWHL Tis really helped me to understand the conversion. However i have a similar problem in which i have a coordinates of an object got it from a page image(pdf page have been converted into page image). Now i want to convert these coordinates into camelot pdf level coordinates. I tried to follow above logic in reverse order which is not successful.
I am new to this, any leads can give some hints/logic for page image co-ordinates conversion to pdf level co-ordinates ?
i have object coordinates - x0,y0,x1,y1 (from page image), also have page image width and height. Also holding target pdf height n width.
Ex: (x0,y0,x1,y1) = 188, 393, 1576, 1498
pageImage height,width = (3300, 2550)
pdf height,width = (792, 612)

@SWHL
Copy link
Author

SWHL commented May 18, 2023

@baleris You can try it by this:

$$\frac{2550}{612} = \frac{188}{x} \rightarrow x?$$ $$\frac{3300}{792} = \frac{393}{y} \rightarrow y?$$

@baleris
Copy link

baleris commented May 18, 2023

@SWHL, this has not worked, when i checked camelot detected table coordinates they are totally different. For example for the above mentioned coordinates, camelot's relevant coordinates are (72.0, 295.2, 563.04, 648.72)

@baleris
Copy link

baleris commented May 29, 2023

@SWHL i see in your above solution you are getting a page image from img = table._image[0] if i have a borderless table and i would like to pass flavor = ''stream' : camelot.read_pdf(src,flavor = 'stream') in tis case how could i get image ? If i try to do same like table._image[0] i get an error message.

Any suggestions to get image for "stream" parameter/borderless tables ?

@SWHL
Copy link
Author

SWHL commented May 30, 2023

You can refer this:

def test_stream():
df = pd.DataFrame(data_stream)
filename = os.path.join(testdir, "health.pdf")
tables = camelot.read_pdf(filename, flavor="stream")
assert df.equals(tables[0].df)

The current issue is beyond the scope of this issue. Suggest opening a new issue to discuss.

@baleris
Copy link

baleris commented May 30, 2023

@SWHL as suggested i have raised new issue #497

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

3 participants