解析PDF时PyPDF2与fitz获取的坐标为何不一致?
问题
我正在用Python解析一个尺寸为30000x2000点的PDF文件,文件里包含表格、线条、文本、注释、图片等各类数据,目标是定位特定文本并获取其附近的注释。我用PyPDF2获取所有注释及其坐标,用fitz(PyMuPDF)查找文本字符串及其坐标。通过fitz搜索'A715_X1'得到X坐标为9076点;通过PyPDF2搜索注释'Some text here'得到X坐标为4280点。但根据PDFXchange的截图,'A715_X1'位于'Some text here'注释正下方,二者X坐标应大致相同(误差仅几个点),且9076符合标尺显示的真实数值。请问为何会出现两组不同的坐标?
用到的代码
fitz(PyMuPDF)代码
import fitz doc = fitz.open(path_pdf) for page in doc: coordinates_of_item_found_on_print = page.search_for('A715_X1')
PyPDF2代码
from PyPDF2 import PdfReader reader = PdfReader("sample.pdf") markup_loc = [] for page in reader.pages: if "/Annots" in page: for annot in page["/Annots"]: obj = annot.get_object() markup_coordinates = obj['/Rect'] if obj['/Subtype'] == '/FreeText': # 跳过Stamp、Popup、Square、PolyLine类型注释 if obj['/Contents'] == 'Some text here': try: markup_loc.append(str(round(markup_coordinates[0]))) print('Note: ' + obj['/Contents'] + ' X-coord: ' + str(round(markup_coordinates[0]))) except Exception as e: print(e)
解答
- 坐标变换处理逻辑不同:fitz会自动应用页面的当前变换矩阵(CTM),返回的是经过旋转、缩放等调整后的用户空间坐标,以页面左下角为原点,和PDFXchange阅读器的标尺显示逻辑一致,所以9076是真实显示的坐标;而PyPDF2直接读取注释的
/Rect原始字段,不会自动处理页面变换,得到的是未经过调整的原始坐标。 - 坐标系基准差异:PDF的注释
/Rect字段基于文件内部的媒体盒或裁剪盒定义,而fitz返回的坐标是统一适配后的用户空间坐标,两者的基准不一致,导致数值偏差。 - 注释坐标的原始性:部分PDF中注释的坐标是基于局部坐标系定义的,fitz会自动将其转换为全局页面坐标,而PyPDF2只会读取原始存储的数值,不会做全局转换,这也是坐标不一致的原因之一。
内容的提问来源于stack exchange,提问作者Yurii Gul
相关产品推荐
相关产品推荐

