必须提取ocr坐标才能还原空间结构:paddleocr需启用box输出,按y轴分组生成逻辑行,再通过网格线检测或坐标聚类还原表格,最后按像素间距插入空格拼接成结构化文本。

你需要把OCR识别出的多段文字按原始图片中的位置关系拼成逻辑通顺的文本,比如表格行列对齐、段落缩进还原、标题与正文层级匹配。直接concat字符串会丢掉空间结构,导致“姓名年龄性别”连成一串而无法区分字段。
提取OCR原始坐标与文本
调用Tesseract或PaddleOCR时必须启用box输出模式,否则后续无法定位。以PaddleOCR为例:初始化Predictor时传入use_angle_cls=False, det=True, rec=True, cls=False,并确保return_ocr_result=True返回包含boxes和texts的二维数组。
每条识别结果形如['text' => '张三', 'box' => [[120,45],[200,45],[200,68],[120,68]],box是左上→右上→右下→左下四个顶点坐标(单位像素)。
这一步不能跳过坐标提取——没有box就无法判断“张三”在“年龄”左边还是右边,所有拼接都会失效。
按Y轴分组生成逻辑行
第一步:遍历所有识别项,用其box左上角y坐标(即$item['box'][0][1])除以字体高度估算行号。字体高度取所有box高度中位数:array_map(fn($b) => $b[2][1] - $b[0][1], $boxes) → array_median(...)。
第二步:将每个文本项归入对应行号的桶中,桶内按x坐标升序排列。注意:同一行内若两个box水平重叠度>30%(重叠宽度/较小box宽度),则判定为同一字段多行(如长地址换行),需合并而非并列。
第三步:对每一行桶内的文本执行左对齐校验——计算各box左上角x坐标的众数,偏离该值±15px的视为缩进或悬挂,保留空格前缀;偏离>50px的单独成子行(如项目符号列表)。
还原表格结构
方法一:基于网格线检测。先用OpenCV二值化+霍夫线变换提取横纵线,交点构成网格顶点;再将每个OCR文本框中心点落入的单元格坐标(r,c)记录下来;最后按(r,c)二维索引填充二维数组,空单元格填空字符串。
方法二:纯坐标聚类(无表格线时)。统计所有box的x方向端点(左/右边界),用DBSCAN聚类出列候选位置;同理聚类y方向端点得行候选位置;再用最近邻分配每个文本到最近列+最近行交叉区域。
【列边界聚类时eps参数必须设为图片宽度的1.5%~3%,过大导致列合并,过小产生虚假列】
生成最终结构化文本
将分好行的数据逐行拼接,行间用\n;同一行内文本间插入空格数 = (后一项左x - 前一项右x) ÷ 平均字符宽度(取字体大小×0.6);结果四舍五入取整,最小为1。
表格数据转CSV:遍历二维数组,每行用fputcsv()写入临时文件,最后读取返回字符串。
这一步操作起来很简单,直接把处理好的二维数组传给array_map('implode', $table_rows)就能得到带制表符的文本流。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











