You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用pdfPlumber与OpenCV筛选指定区域文本及解决坐标不匹配问题

问题描述

我有一批会议论文集PDF文件,每个文件的结构如下:

大字号粗体标题
    Author1                Author2                 AuthorN
所属机构1          所属机构2            所属机构N
Email1                  Email2                   Email3

我已经用pdfPlumber选取字号最大的字符作为标题,这个方法可行。现在想要提取作者-所属机构-邮箱信息,尝试用OpenCV识别文本块,再筛选每个OpenCV框内的字符,但无法成功,原因是OpenCV生成的框坐标x/y与pdfPlumber生成的x0/x1/top/bottom不匹配。以下是我的实现代码:

def getCharsInBox(box):
    left_point_x=np.min(box[:,0])
    right_point_x=np.max(box[:,0])
    top_point_y=np.min(box[:,1])
    bottom_point_y=np.max(box[:,1])
    return lambda x:((x.get("x0",0)>=left_point_x &\
                      x.get("x0",0)<=right_point_x &\
                      x.get("top",0)>=top_point_x &\
                      x.get("bottom",0)<=bottom_point_y))


for box in region:
    filtered=page.filter(getCharsInBox(box))
    pdfAAE=filtered.extract_text()
解决建议

1. 先统一坐标系统

pdfPlumber用PDF原生**点(pt)作为单位,OpenCV处理的是图片像素(px)**坐标,两者缩放比例完全不同,必须先做转换:

  • 用pdfPlumber导出页面为图片,记录pt到px的缩放比例:
    # 导出页面为图片,dpi和OpenCV处理时保持一致
    img = page.to_image(resolution=300)
    scale_x = img.width / page.width
    scale_y = img.height / page.height
    
  • 将OpenCV的像素框转换为pdfPlumber的点坐标:
    def box_px_to_pt(box, scale_x, scale_y):
        left_x = np.min(box[:,0]) / scale_x
        right_x = np.max(box[:,0]) / scale_x
        top_y = np.min(box[:,1]) / scale_y
        bottom_y = np.max(box[:,1]) / scale_y
        return left_x, right_x, top_y, bottom_y
    

2. 修正筛选函数的逻辑错误

原代码误用了按位与&,Python逻辑判断要用and;同时优化筛选条件,判断字符区域与框是否重叠,而非仅匹配单个坐标:

def getCharsInBox(box_pt):
    left_x, right_x, top_y, bottom_y = box_pt
    def filter_func(char):
        char_x0 = char.get("x0", 0)
        char_x1 = char.get("x1", 0)
        char_top = char.get("top", 0)
        char_bottom = char.get("bottom", 0)
        # 判断字符区域和框是否存在重叠
        overlap = not (char_x1 < left_x or char_x0 > right_x or char_bottom < top_y or char_top > bottom_y)
        return overlap
    return filter_func

3. 更高效的替代方案:纯用pdfPlumber提取

无需依赖OpenCV,直接利用pdfPlumber的文本分析能力:

  • 提取所有带位置、字体信息的文本块,按行分组
  • 根据字体特征、文本内容区分作者、机构、邮箱行(作者行常为粗体,邮箱行含@符号)
# 提取带字体、大小、位置的文本块
words = page.extract_words(extra_attrs=["fontname", "size"])
# 按行分组(用top值整数部分避免微小坐标误差)
rows = {}
for word in words:
    row_key = int(word["top"])
    rows[row_key] = rows.get(row_key, []) + [word]

# 按行从上到下排序
sorted_rows = sorted(rows.values(), key=lambda x: x[0]["top"])

# 筛选作者、机构、邮箱行
author_row = affiliation_row = email_row = None
for row in sorted_rows:
    row_text = " ".join([w["text"] for w in row])
    if "@" in row_text:
        email_row = row_text
    elif any("bold" in w["fontname"].lower() for w in row):
        author_row = row_text
    else:
        affiliation_row = row_text

print("作者:", author_row)
print("所属机构:", affiliation_row)
print("邮箱:", email_row)

内容的提问来源于stack exchange,提问作者Valuex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 02:06:34