SKILL.md
唯讀
名稱
layout-analyzer
描述
>
版本
1.0
版面分析技能
概述
本技能使用 surya(一個先進的文件理解系統)進行文件版面分析。可偵測文字區塊、表格、圖形、標題,並判斷複雜文件中的閱讀順序。
使用方式
- 提供文件圖片或 PDF
- 指定要偵測的版面元素
- 我將分析結構並回傳偵測到的區域
範例提示:
- "分析這份文件頁面的版面"
- "偵測這張圖片中的所有表格和文字區塊"
- "判斷這個 PDF 頁面的閱讀順序"
- "找出這份文件中的標題和段落"
領域知識
surya 基礎
from surya.detection import DetectionPredictor
from surya.layout import LayoutPredictor
from surya.reading_order import ReadingOrderPredictor
from PIL import Image
# 載入圖片
image = Image.open("document.png")
# 偵測版面元素
layout_predictor = LayoutPredictor()
layout_result = layout_predictor([image])
版面元素類型
| 元素 | 說明 |
|---|---|
| Text | 一般段落文字 |
| Title | 文件/章節標題 |
| Section-header | 章節標題 |
| List-item | 項目符號/編號項目 |
| Table | 表格資料 |
| Figure | 圖片/圖表 |
| Caption | 圖表說明 |
| Footnote | 註腳 |
| Formula | 數學公式 |
| Page-header | 頁首 |
| Page-footer | 頁尾 |
文字偵測
from surya.detection import DetectionPredictor
from PIL import Image
# 初始化偵測器
detector = DetectionPredictor()
# 載入圖片
image = Image.open("document.png")
# 偵測文字區域
results = detector([image])
# 存取結果
for page_result in results:
for bbox in page_result.bboxes:
print(f"文字區域:{bbox.bbox}")
print(f"信心度:{bbox.confidence}")
版面分析
from surya.layout import LayoutPredictor
from PIL import Image
# 初始化版面預測器
layout_predictor = LayoutPredictor()
# 分析版面
image = Image.open("document.png")
layout_results = layout_predictor([image])
# 處理結果
for page_result in layout_results:
for element in page_result.bboxes:
print(f"類型:{element.label}")
print(f"邊界框:{element.bbox}")
print(f"信心度:{element.confidence}")
閱讀順序偵測
from surya.reading_order import ReadingOrderPredictor
from surya.layout import LayoutPredictor
from PIL import Image
# 先取得版面
layout_predictor = LayoutPredictor()
image = Image.open("document.png")
layout_results = layout_predictor([image])
# 判斷閱讀順序
reading_order_predictor = ReadingOrderPredictor()
order_results = reading_order_predictor([image], layout_results)
# 存取排序後的元素
for page_result in order_results:
for i, element in enumerate(page_result.ordered_bboxes):
print(f"{i+1}. {element.label}:{element.bbox}")
結合版面的 OCR
from surya.ocr import OCRPredictor
from surya.layout import LayoutPredictor
from PIL import Image
# 初始化預測器
ocr_predictor = OCRPredictor()
layout_predictor = LayoutPredictor()
# 載入圖片
image = Image.open("document.png")
# 取得版面
layout_results = layout_predictor([image])
# 執行 OCR
ocr_results = ocr_predictor([image])
# 合併結果
for layout, ocr in zip(layout_results, ocr_results):
for layout_elem in layout.bboxes:
print(f"元素:{layout_elem.label}")
# 找出此版面元素內的 OCR 文字
for text_line in ocr.text_lines:
if boxes_overlap(layout_elem.bbox, text_line.bbox):
print(f" 文字:{text_line.text}")
處理 PDF
from surya.layout import LayoutPredictor
from pdf2image import convert_from_path
def analyze_pdf_layout(pdf_path):
"""分析 PDF 中所有頁面的版面。"""
# 將 PDF 轉換為圖片
images = convert_from_path(pdf_path)
# 初始化預測器
layout_predictor = LayoutPredictor()
# 分析所有頁面
results = layout_predictor(images)
document_structure = []
for page_num, page_result in enumerate(results):
page_elements = []
for element in page_result.bboxes:
page_elements.append({
'type': element.label,
'bbox': element.bbox,
'confidence': element.confidence
})
document_structure.append({
'page': page_num + 1,
'elements': page_elements
})
return document_structure
structure = analyze_pdf_layout("document.pdf")
視覺化
from surya.layout import LayoutPredictor
from PIL import Image, ImageDraw, ImageFont
def visualize_layout(image_path, output_path):
"""視覺化偵測到的版面元素。"""
image = Image.open(image_path)
layout_predictor = LayoutPredictor()
results = layout_predictor([image])
# 建立繪圖上下文
draw = ImageDraw.Draw(image)
# 元素類型的顏色對應
colors = {
'Text': 'blue',
'Title': 'red',
'Table': 'green',
'Figure': 'purple',
'Section-header': 'orange',
'List-item': 'cyan',
}
for element in results[0].bboxes:
bbox = element.bbox
color = colors.get(element.label, 'gray')
# 繪製矩形
draw.rectangle(bbox, outline=color, width=2)
# 加入標籤
draw.text((bbox[0], bbox[1] - 15),
f"{element.label} ({element.confidence:.2f})",
fill=color)
image.save(output_path)
return output_path
最佳實務
- 使用高品質圖片:建議 150 DPI 以上以獲得最佳結果
- 必要時進行前處理:矯正旋轉的文件
- 驗證結果:檢查信心度分數
- 處理多頁文件:逐頁處理
- 結合 OCR:取得偵測區域內的文字
常見模式
文件結構萃取
def extract_document_structure(image_path):
"""萃取階層式文件結構。"""
from surya.layout import LayoutPredictor
from surya.reading_order import ReadingOrderPredictor
image = Image.open(image_path)
# 取得版面
layout_predictor = LayoutPredictor()
layout_results = layout_predictor([image])
# 取得閱讀順序
order_predictor = ReadingOrderPredictor()
order_results = order_predictor([image], layout_results)
structure = {
'title': None,
'sections': [],
'tables': [],
'figures': []
}
current_section = None
for element in order_results[0].ordered_bboxes:
if element.label == 'Title':
structure['title'] = element
elif element.label == 'Section-header':
current_section = {'header': element, 'content': []}
structure['sections'].append(current_section)
elif element.label == 'Table':
structure['tables'].append(element)
elif element.label == 'Figure':
structure['figures'].append(element)
elif current_section and element.label in ['Text', 'List-item']:
current_section['content'].append(element)
return structure
表格區域萃取
def extract_table_regions(image_path):
"""從文件中萃取表格區域。"""
from surya.layout import LayoutPredictor
image = Image.open(image_path)
layout_predictor = LayoutPredictor()
results = layout_predictor([image])
tables = []
for element in results[0].bboxes:
if element.label == 'Table':
bbox = element.bbox
# 裁切表格區域
table_image = image.crop(bbox)
tables.append({
'bbox': bbox,
'image': table_image,
'confidence': element.confidence
})
return tables
範例
範例 1:學術論文分析
from surya.layout import LayoutPredictor
from surya.reading_order import ReadingOrderPredictor
from pdf2image import convert_from_path
def analyze_academic_paper(pdf_path):
"""分析學術論文的結構。"""
images = convert_from_path(pdf_path)
layout_predictor = LayoutPredictor()
order_predictor = ReadingOrderPredictor()
paper_structure = {
'pages': [],
'element_counts': {
'Title': 0,
'Section-header': 0,
'Text': 0,
'Table': 0,
'Figure': 0,
'Formula': 0,
'Footnote': 0
}
}
layout_results = layout_predictor(images)
order_results = order_predictor(images, layout_results)
for page_num, (layout, order) in enumerate(zip(layout_results, order_results)):
page_structure = {
'page': page_num + 1,
'elements': []
}
for element in order.ordered_bboxes:
page_structure['elements'].append({
'type': element.label,
'bbox': element.bbox,
'order': element.position
})
# 計算元素類型數量
if element.label in paper_structure['element_counts']:
paper_structure['element_counts'][element.label] += 1
paper_structure['pages'].append(page_structure)
return paper_structure
paper = analyze_academic_paper('research_paper.pdf')
print(f"表格總數:{paper['element_counts']['Table']}")
print(f"圖形總數:{paper['element_counts']['Figure']}")
範例 2:表單欄位偵測
from surya.layout import LayoutPredictor
from PIL import Image
def detect_form_fields(image_path):
"""偵測表單欄位與標籤。"""
image = Image.open(image_path)
layout_predictor = LayoutPredictor()
results = layout_predictor([image])
form_fields = []
for element in results[0].bboxes:
# 尋找可能是標籤的文字元素
if element.label == 'Text':
# 檢查附近是否有方框/線條(可能的輸入欄位)
form_fields.append({
'type': 'potential_label',
'bbox': element.bbox,
'confidence': element.confidence
})
return form_fields
fields = detect_form_fields('form.png')
print(f"找到 {len(fields)} 個潛在表單元素")
範例 3:多欄文章
from surya.layout import LayoutPredictor
from surya.reading_order import ReadingOrderPredictor
from PIL import Image
def process_multicolumn_article(image_path):
"""處理多欄文章版面。"""
image = Image.open(image_path)
layout_predictor = LayoutPredictor()
order_predictor = ReadingOrderPredictor()
layout_results = layout_predictor([image])
order_results = order_predictor([image], layout_results)
# 依欄位分組元素
image_width = image.width
column_threshold = image_width / 2
columns = {
'left': [],
'right': [],
'full_width': []
}
for element in order_results[0].ordered_bboxes:
bbox = element.bbox
element_center = (bbox[0] + bbox[2]) / 2
element_width = bbox[2] - bbox[0]
# 判斷欄位
if element_width > column_threshold * 1.5:
columns['full_width'].append(element)
elif element_center < column_threshold:
columns['left'].append(element)
else:
columns['right'].append(element)
return {
'layout': 'multi-column',
'columns': columns,
'reading_order': order_results[0].ordered_bboxes
}
article = process_multicolumn_article('newspaper_page.png')
print(f"左欄:{len(article['columns']['left'])} 個元素")
print(f"右欄:{len(article['columns']['right'])} 個元素")
限制
- 手寫版面的準確度可能較低
- 非常小的文字區域可能被遺漏
- 複雜的巢狀版面較具挑戰性
- 批次處理建議使用 GPU
- 多語言支援程度不一
安裝
pip install surya-ocr
# 用於 PDF 處理
pip install pdf2image






