|
@@ -0,0 +1,206 @@
|
|
|
|
|
+正在收集工作区信息正在筛选到最相关的信息根据代码分析,我来详细说明文字PDF的判断和处理流程:
|
|
|
|
|
+
|
|
|
|
|
+## 文字PDF判断和处理详细说明
|
|
|
|
|
+
|
|
|
|
|
+### 1. **文字PDF判断机制**
|
|
|
|
|
+
|
|
|
|
|
+MinerU通过以下方式判断PDF类型:
|
|
|
|
|
+
|
|
|
|
|
+```python
|
|
|
|
|
+# 在 pipeline_doc_analyze 中
|
|
|
|
|
+classify_result = classify(images) # 使用分类模型判断
|
|
|
|
|
+if classify_result == "txt":
|
|
|
|
|
+ parse_method = "txt" # 文字PDF
|
|
|
|
|
+else:
|
|
|
|
|
+ parse_method = "ocr" # 图片PDF/扫描件
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**判断依据**:
|
|
|
|
|
+- 使用 **classify 模型**(基于图像特征)判断PDF页面是否包含可提取的文本层
|
|
|
|
|
+- 检查PDF页面的文本提取率
|
|
|
|
|
+- 分析文本的连续性和完整性
|
|
|
|
|
+
|
|
|
|
|
+### 2. **文字PDF处理流程**
|
|
|
|
|
+
|
|
|
|
|
+```mermaid
|
|
|
|
|
+graph TB
|
|
|
|
|
+ Start([PDF输入]) --> LoadPDF[加载PDF文档<br/>PyPDF2/pypdfium2]
|
|
|
|
|
+ LoadPDF --> RenderImage[渲染PDF页面为图像<br/>DPI=200]
|
|
|
|
|
+
|
|
|
|
|
+ RenderImage --> ClassifyModel{Classify分类模型<br/>判断PDF类型}
|
|
|
|
|
+ ClassifyModel -->|文字PDF| TxtMode[parse_method=txt]
|
|
|
|
|
+ ClassifyModel -->|图片PDF| OcrMode[parse_method=ocr]
|
|
|
|
|
+
|
|
|
|
|
+ TxtMode --> LayoutDetection[布局检测模型<br/>DocLayout-YOLO<br/>检测文本/表格/图片/公式区域]
|
|
|
|
|
+
|
|
|
|
|
+ LayoutDetection --> ExtractRegions[提取各区域bbox坐标]
|
|
|
|
|
+
|
|
|
|
|
+ ExtractRegions --> ProcessText{处理文本区域}
|
|
|
|
|
+ ExtractRegions --> ProcessTable{处理表格区域}
|
|
|
|
|
+ ExtractRegions --> ProcessFormula{处理公式区域}
|
|
|
|
|
+ ExtractRegions --> ProcessImage{处理图像区域}
|
|
|
|
|
+
|
|
|
|
|
+ %% 文本处理分支
|
|
|
|
|
+ ProcessText --> ExtractPDFText[提取PDF嵌入文本<br/>pdf_doc.get_text]
|
|
|
|
|
+ ExtractPDFText --> TextMapping[根据bbox映射文本内容]
|
|
|
|
|
+ TextMapping --> TextResult[文本块结果<br/>type: text<br/>content: 原生文本]
|
|
|
|
|
+
|
|
|
|
|
+ %% 表格处理分支
|
|
|
|
|
+ ProcessTable --> CropTable[裁剪表格区域图像]
|
|
|
|
|
+ CropTable --> TableDetect[表格结构检测<br/>RapidTable/StructEqTable]
|
|
|
|
|
+ TableDetect --> TableCells[识别单元格位置]
|
|
|
|
|
+ TableCells --> CellTextExtract{单元格文本提取}
|
|
|
|
|
+
|
|
|
|
|
+ CellTextExtract -->|文字PDF模式| ExtractCellPDFText[提取PDF文本<br/>根据单元格bbox]
|
|
|
|
|
+ CellTextExtract -->|需要OCR| TableOCR[OCR识别<br/>PaddleOCR]
|
|
|
|
|
+
|
|
|
|
|
+ ExtractCellPDFText --> TableHTML[生成HTML表格<br/>type: table<br/>content: HTML]
|
|
|
|
|
+ TableOCR --> TableHTML
|
|
|
|
|
+
|
|
|
|
|
+ %% 公式处理分支
|
|
|
|
|
+ ProcessFormula --> FormulaClassify{公式类型检测}
|
|
|
|
|
+ FormulaClassify -->|行内公式| InlineFormula[inline_equation]
|
|
|
|
|
+ FormulaClassify -->|独立公式| DisplayFormula[interline_equation]
|
|
|
|
|
+
|
|
|
|
|
+ InlineFormula --> CropFormula1[裁剪公式区域]
|
|
|
|
|
+ DisplayFormula --> CropFormula2[裁剪公式区域]
|
|
|
|
|
+
|
|
|
|
|
+ CropFormula1 --> FormulaDetect[公式检测模型<br/>YOLOv8-MFD]
|
|
|
|
|
+ CropFormula2 --> FormulaDetect
|
|
|
|
|
+
|
|
|
|
|
+ FormulaDetect --> FormulaRecog[公式识别模型<br/>UniMERNet]
|
|
|
|
|
+ FormulaRecog --> FormulaLatex[生成LaTeX<br/>type: equation<br/>content: LaTeX]
|
|
|
|
|
+
|
|
|
|
|
+ %% 图像处理分支
|
|
|
|
|
+ ProcessImage --> SaveImage[保存图像文件<br/>.png]
|
|
|
|
|
+ SaveImage --> ImageResult[图像引用<br/>type: image<br/>path: xxx.png]
|
|
|
|
|
+
|
|
|
|
|
+ %% 合并结果
|
|
|
|
|
+ TextResult --> MergeResults[合并所有元素]
|
|
|
|
|
+ TableHTML --> MergeResults
|
|
|
|
|
+ FormulaLatex --> MergeResults
|
|
|
|
|
+ ImageResult --> MergeResults
|
|
|
|
|
+
|
|
|
|
|
+ MergeResults --> SortByLayout[按布局顺序排序]
|
|
|
|
|
+ SortByLayout --> MiddleJSON[生成middle.json<br/>包含所有结构化内容]
|
|
|
|
|
+
|
|
|
|
|
+ MiddleJSON --> GenerateMarkdown[生成Markdown<br/>pipeline_union_make]
|
|
|
|
|
+ GenerateMarkdown --> FinalMD([输出: xxx.md])
|
|
|
|
|
+
|
|
|
|
|
+ %% OCR模式分支
|
|
|
|
|
+ OcrMode --> OcrLayout[布局检测<br/>DocLayout-YOLO]
|
|
|
|
|
+ OcrLayout --> OcrProcess[OCR识别所有文本<br/>PaddleOCR]
|
|
|
|
|
+ OcrProcess --> OcrTable[表格OCR]
|
|
|
|
|
+ OcrProcess --> OcrFormula[公式识别]
|
|
|
|
|
+ OcrTable --> MergeResults
|
|
|
|
|
+ OcrFormula --> MergeResults
|
|
|
|
|
+
|
|
|
|
|
+ %% 样式定义
|
|
|
|
|
+ classDef modelClass fill:#e1f5ff,stroke:#01579b,stroke-width:2px
|
|
|
|
|
+ classDef dataClass fill:#fff3e0,stroke:#e65100,stroke-width:2px
|
|
|
|
|
+ classDef processClass fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
|
|
|
|
|
+ classDef decisionClass fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px
|
|
|
|
|
+
|
|
|
|
|
+ class ClassifyModel,LayoutDetection,TableDetect,FormulaDetect,FormulaRecog modelClass
|
|
|
|
|
+ class TextResult,TableHTML,FormulaLatex,ImageResult,MiddleJSON dataClass
|
|
|
|
|
+ class ExtractPDFText,CropTable,CropFormula1,CropFormula2,MergeResults processClass
|
|
|
|
|
+ class ProcessText,ProcessTable,ProcessFormula,ProcessImage,CellTextExtract,FormulaClassify decisionClass
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## 详细说明
|
|
|
|
|
+
|
|
|
|
|
+### **步骤1: PDF分类**
|
|
|
|
|
+```python
|
|
|
|
|
+# 在 mineru/backend/pipeline/pipeline_analyze.py
|
|
|
|
|
+classify_result = classify(images_list) # 返回 "txt" 或 "ocr"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### **步骤2: 布局检测**
|
|
|
|
|
+```python
|
|
|
|
|
+# DocLayout-YOLO 检测各类元素
|
|
|
|
|
+layout_det_results = layout_model.predict(image)
|
|
|
|
|
+# 返回: text, title, table, figure, equation等区域的bbox
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### **步骤3: 文字PDF文本提取**
|
|
|
|
|
+```python
|
|
|
|
|
+# 文字PDF模式: 直接提取文本
|
|
|
|
|
+text_blocks = pdf_page.get_text("blocks")
|
|
|
|
|
+for bbox in text_bboxes:
|
|
|
|
|
+ text = extract_text_from_bbox(pdf_page, bbox)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### **步骤4: 表格处理(文字PDF)**
|
|
|
|
|
+```python
|
|
|
|
|
+# 1. 裁剪表格区域图像
|
|
|
|
|
+table_image = crop_image(page_image, table_bbox)
|
|
|
|
|
+
|
|
|
|
|
+# 2. 表格结构检测
|
|
|
|
|
+table_structure = rapidtable_model.predict(table_image)
|
|
|
|
|
+# 返回: cells的bbox和行列信息
|
|
|
|
|
+
|
|
|
|
|
+# 3. 提取单元格文本
|
|
|
|
|
+for cell_bbox in table_structure.cells:
|
|
|
|
|
+ # 文字PDF: 提取PDF文本
|
|
|
|
|
+ cell_text = extract_text_from_bbox(pdf_page, cell_bbox)
|
|
|
|
|
+
|
|
|
|
|
+ # 如果提取失败,使用OCR
|
|
|
|
|
+ if not cell_text:
|
|
|
|
|
+ cell_text = ocr_model.recognize(cell_image)
|
|
|
|
|
+
|
|
|
|
|
+# 4. 生成HTML
|
|
|
|
|
+table_html = generate_html_table(table_structure, cell_texts)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### **步骤5: 公式处理**
|
|
|
|
|
+```python
|
|
|
|
|
+# 1. 裁剪公式区域
|
|
|
|
|
+formula_image = crop_image(page_image, formula_bbox)
|
|
|
|
|
+
|
|
|
|
|
+# 2. 公式检测(可选)
|
|
|
|
|
+formula_regions = mfd_model.predict(formula_image)
|
|
|
|
|
+
|
|
|
|
|
+# 3. 公式识别
|
|
|
|
|
+latex_code = unimernet_model.recognize(formula_image)
|
|
|
|
|
+# 输出: $E = mc^2$ 或 $$\int_{0}^{\infty} e^{-x^2} dx$$
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### **步骤6: 结果合并**
|
|
|
|
|
+```python
|
|
|
|
|
+# 按阅读顺序排序
|
|
|
|
|
+sorted_blocks = sort_blocks_by_reading_order(all_blocks)
|
|
|
|
|
+
|
|
|
|
|
+# 生成middle.json
|
|
|
|
|
+middle_json = {
|
|
|
|
|
+ "pdf_info": [{
|
|
|
|
|
+ "page_idx": 0,
|
|
|
|
|
+ "para_blocks": [
|
|
|
|
|
+ {"type": "text", "content": "..."},
|
|
|
|
|
+ {"type": "table", "content": "<table>...</table>"},
|
|
|
|
|
+ {"type": "equation", "content": "$E=mc^2$"},
|
|
|
|
|
+ {"type": "image", "path": "images/image_0.png"}
|
|
|
|
|
+ ]
|
|
|
|
|
+ }]
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## 关键差异对比
|
|
|
|
|
+
|
|
|
|
|
+| 特性 | 文字PDF (txt模式) | 图片PDF (ocr模式) |
|
|
|
|
|
+|------|------------------|------------------|
|
|
|
|
|
+| **文本提取** | 直接读取PDF文本层 | OCR识别 |
|
|
|
|
|
+| **表格单元格** | 优先提取PDF文本,失败才OCR | 全部OCR |
|
|
|
|
|
+| **公式识别** | UniMERNet(图像→LaTeX) | 同左 |
|
|
|
|
|
+| **处理速度** | 快(跳过大部分OCR) | 慢(全页OCR) |
|
|
|
|
|
+| **准确性** | 文本100%准确 | 依赖OCR质量 |
|
|
|
|
|
+
|
|
|
|
|
+## 使用的模型清单
|
|
|
|
|
+
|
|
|
|
|
+1. **Classify模型**: PDF类型分类(txt/ocr)
|
|
|
|
|
+2. **DocLayout-YOLO**: 布局检测(文本/表格/图片/公式区域)
|
|
|
|
|
+3. **RapidTable/StructEqTable**: 表格结构识别
|
|
|
|
|
+4. **PaddleOCR**: OCR文字识别(作为fallback)
|
|
|
|
|
+5. **YOLOv8-MFD**: 公式区域检测
|
|
|
|
|
+6. **UniMERNet**: 公式识别(图像→LaTeX)
|
|
|
|
|
+
|
|
|
|
|
+这个流程确保了文字PDF能够最大化利用原生文本层,同时对表格和公式使用专用的识别模型来保证质量。
|