GLM-OCR识别结果后处理技巧:基于规则与NLP纠错提升准确率

GLM-OCR识别结果后处理技巧:基于规则与NLP纠错提升准确率 GLM-OCR识别结果后处理技巧基于规则与NLP纠错提升准确率直接使用GLM-OCR这类工具识别图片文字拿到手的文本有时候会让人哭笑不得。你可能遇到过“北京”被识别成“北就”“有限公司”变成“有限公可”或者一整段话被拆得七零八落标点符号也乱飞。这些错误虽然不大但足以让后续的分析、存档或搜索变得困难重重。其实OCR识别出来的“生文本”就像一块未经雕琢的玉石直接使用价值有限。但只要我们掌握一些后处理的技巧就能把它打磨成一块美玉让文本的准确性和可用性大大提升。今天我就来跟你聊聊怎么给GLM-OCR的识别结果“美颜”和“纠错”结合简单的规则和一点NLP自然语言处理的小魔法把准确率再往上提一个档次。1. 为什么OCR识别结果需要后处理在你开始动手写代码之前我们先得搞清楚为什么要多这一步。OCR引擎包括GLM-OCR本质上是在做“看图猜字”。这个过程会受到很多干扰图片质量本身模糊、倾斜、光照不均、背景复杂都会让引擎看走眼。字体和排版生僻字体、艺术字、密集排版或手写体对引擎是巨大挑战。语言模型局限引擎内置的语言模型可能无法完美理解所有上下文导致它选了一个字形相似但语义错误的字。所以原始识别文本里常见的“病症”主要有这几类字符级错误形近字错误如“未”和“末”、音近字错误在中文里较少英文常见如“their”和“there”、漏字或多字。格式混乱不该换行的地方换行了段落粘连空格缺失或多余标点符号识别错误如句号“。”被识别成小数点“.”。领域特定错误在专业文档中比如医学报告里的专业术语、法律文书里的固定表述更容易被识别成常见词。后处理的目的就是当个“校对老师”用一系列自动化的方法尽可能地修正这些错误让文本变得干净、准确、可用。2. 环境准备与工具选择我们今天的操作主要以Python为例因为它有丰富的库来支持我们的后处理流水线。你不需要是Python专家跟着步骤走就行。首先确保你安装了Python建议3.7及以上版本。然后我们通过pip安装几个核心的“武器库”pip install pypinyin # 用于中文拼音处理在某些纠错场景有用 pip install jieba # 中文分词工具理解文本结构的基础 # 语言模型工具我们稍后根据方案选择这里没有强制安装某个NLP大框架因为我们会从简到繁你可以根据需求灵活选用。你的“工具箱”里可能还会用到Python自带的re正则表达式库它是处理格式问题的瑞士军刀。3. 基础清洁用规则处理格式问题第一步我们先处理那些显而易见的、有固定模式的格式错误。这就像打扫房间先把大块的垃圾清出去。3.1 清理多余的空白符和换行OCR经常会产生不规则的空格和换行。比如它可能把词语内部的间隔也当成空格或者在一个句子中间插入不必要的换行。import re def basic_clean(text): 基础文本清洁函数 # 1. 将多个连续换行符包括\r\n, \n, \r统一为一个换行符 # 这有助于保留真正的段落分隔但合并多余的空白行 text re.sub(r\r\n|\r|\n, \n, text) # 2. 移除行首行尾的空白字符空格、制表符 lines [line.strip() for line in text.split(\n)] # 3. 移除因上述操作产生的空行 lines [line for line in lines if line ! ] # 4. 将处理后的行重新连接用单个换行符分隔 cleaned_text \n.join(lines) # 5. 将文本内部的多个连续空格包括全角空格合并为一个空格 # \u3000是全角空格的Unicode cleaned_text re.sub(r[ \u3000], , cleaned_text) return cleaned_text # 示例 dirty_text 这是一段 识别结果。\n\n\n中间有很多 不必要的空格 和换行。 clean_text basic_clean(dirty_text) print(清理前, repr(dirty_text)) print(清理后, repr(clean_text)) # 输出 # 清理前 这是一段 识别结果。\n\n\n中间有很多 不必要的空格 和换行。 # 清理后 这是一段 识别结果。\n中间有很多 不必要的空格 和换行。3.2 纠正常见的标点符号错误OCR可能把中文句号“。”识别为英文句点“.”或者把引号弄混。我们可以用映射关系来批量替换。def correct_punctuation(text): 纠正常见的标点符号错误 # 定义一个常见的错误到正确的映射字典 punctuation_map { .: 。, # 英文句点空格 - 中文句号 . : 。, # 另一种常见情况 ,: , # 英文逗号空格 - 中文逗号 , : , ;: , # 英文分号 - 中文分号 ; : , :: , # 英文冒号 - 中文冒号 : : , ?: , # 英文问号 - 中文问号 ? : , !: , # 英文叹号 - 中文叹号 ! : , “: “, # 确保引号方向这里示例实际可能更复杂 ”: ”, # 可以添加更多映射 } for wrong, right in punctuation_map.items(): text text.replace(wrong, right) # 更通用的将行尾的英文句点替换为中文句号需谨慎可能误伤英文文本 # 这里我们使用一个更安全的模式仅当句点前是中文或数字时替换 # 这是一个简化示例实际应用可能需要更复杂的规则 lines text.split(\n) corrected_lines [] for line in lines: # 匹配以中文/数字结尾后跟英文句点和行尾的情况 if re.search(r[\u4e00-\u9fa50-9]\.$, line): line line[:-1] 。 corrected_lines.append(line) return \n.join(corrected_lines)4. 基于词典与规则的拼写检查格式弄干净了接下来对付错别字。对于有固定词汇表的场景比如公司名称、产品列表、专业术语基于词典的检查非常有效。4.1 构建领域词典假设你经常处理包含“科技有限公司”、“设计工作室”等固定后缀的文本。我们可以创建一个自定义词典来保护这些词不被错误拆分或修改。import jieba # 1. 加载自定义词典 # 你可以创建一个文本文件 custom_dict.txt每行一个词格式词语 词频 词性可选 # 例如 # 星图科技 100 n # GLM-OCR 100 nz # 后处理 100 n jieba.load_userdict(custom_dict.txt) # 如果文件存在 # 或者直接在代码中添加 user_words [星图科技, 深度学习框架, 自然语言处理, 有限公司] for word in user_words: jieba.add_word(word, freq1000) # 设置一个高词频确保它能被正确切分 def detect_unknown_words(text, known_word_setNone): 检测文本中可能不在标准词典中的词潜在错误或专业词。 这是一个简单的示例实际应用中需要更复杂的逻辑。 if known_word_set is None: # 一个示例性的已知词汇集合实际应从更大语料库加载 known_word_set set([我们, 可以, 处理, 文本, 识别, 结果, 准确, 提升, 公司, 科技]) # 合并自定义词 known_word_set.update(user_words) words jieba.lcut(text) unknown_words [word for word in words if word not in known_word_set and len(word) 1] # 过滤掉单字和已知词 return unknown_words # 示例 sample_text 星图科技是一家专注于人工智能的公司。 print(分词结果, jieba.lcut(sample_text)) # 输出[星图科技, 是, 一家, 专注于, 人工智能, 的, 公司, 。] # 如果没有加载自定义词典“星图科技”可能会被切成[星图, 科技]4.2 形近字替换规则对于一些高频的形近字错误我们可以建立一张“纠错映射表”。这招对于特定场景下的系统性错误特别管用。common_typos { 帐号: 账号, 登陆: 登录, 部份: 部分, 影象: 影像, 北就: 北京, 工司: 公司, 有限公可: 有限公司, # ... 可以根据你的OCR错误日志不断补充这个列表 } def correct_by_rules(text, correction_map): 根据预定义的映射表进行替换 for wrong, right in correction_map.items(): text text.replace(wrong, right) return text # 示例 text_with_typo 请使用您的帐号登陆系统查看影象资料。 corrected_text correct_by_rules(text_with_typo, common_typos) print(corrected_text) # 输出请使用您的账号登录系统查看影像资料。5. 引入上下文用N-gram进行智能纠错规则词典很好但它无法理解上下文。比如“北京”被识别成“北就”词典能改过来。但如果一个词本身是合法的只是在这个句子里不合适呢这时候就需要语言模型来帮忙看看这个词在上下文中出现的可能性有多大。N-gram是一种简单的语言模型它通过计算一个词序列出现的概率来判断文本是否“通顺”。我们这里用一个非常简单的思路对于句子中每个位置如果发现一个不常见的词或字我们就看看把它换成形近字后整个片段的“通顺度”会不会提高。由于从头训练一个中文N-gram模型比较麻烦我们可以用一个取巧的办法结合jieba的分词和词频信息来模拟这种“通顺度”检查。import itertools def get_character_ngram_score(segment, n2): 一个非常简化的评估函数计算文本片段中常见二元字组bigram的占比。 实际应用中应使用在大规模语料上训练好的语言模型概率。 # 这是一个示例性的“好”二元字组集合实际应从大规模语料统计获得 good_bigrams set([我们, 可以, 处理, 文本, 识别, 结果, 准确, 提升, 公司, 科技, 是一, 一家, 专注, 于人, 人工, 智能, 的企, 企业]) score 0 for i in range(len(segment) - n 1): bigram segment[i:in] if bigram in good_bigrams: score 1 return score / max(1, len(segment) - n 1) def simple_context_correction(word, context, candidate_chars): 简单的上下文纠错示例。 word: 待纠错的词字符串 context: 该词所在的上下文字符串 candidate_chars: 一个字典key为原字value为可能的正确字列表形近字 返回修正后的词 # 找到word在context中的位置简化处理假设第一次出现 idx context.find(word) if idx -1: return word best_word word best_score -1 # 为word中每个可能出错的字生成候选组合 char_positions [] for i, char in enumerate(word): if char in candidate_chars: char_positions.append((i, candidate_chars[char])) if not char_positions: return word # 生成所有可能的候选词这里只考虑一个位置出错的情况避免组合爆炸 for pos, candidates in char_positions: for cand_char in candidates: candidate_word word[:pos] cand_char word[pos1:] # 构造一个包含该候选词的文本片段用于评估 # 这里简单地用候选词替换原词并取前后各2个字作为上下文 start max(0, idx - 2) end min(len(context), idx len(word) 2) segment context[start:end].replace(word, candidate_word) score get_character_ngram_score(segment) if score best_score: best_score score best_word candidate_word return best_word # 示例形近字候选集 shape_similar_chars { 未: [末, 未], 末: [未, 末], 已: [己, 已], 己: [已, 己], 人: [入, 人], 入: [人, 入], } text 这项技术末来有广阔前景。 # “未”被识别成了“末” word_to_correct 末来 corrected_word simple_context_correction(word_to_correct, text, shape_similar_chars) corrected_text text.replace(word_to_correct, corrected_word) print(f原句{text}) print(f纠错后{corrected_text}) # 输出这项技术未来有广阔前景。请注意上面的get_character_ngram_score函数和simple_context_correction是一个极度简化的示例旨在说明原理。在实际生产环境中你需要使用一个在大规模中文语料如新闻、网页文本上训练好的、真正的N-gram模型可以通过kenlm等库训练或加载预训练模型。设计更高效的候选词生成和搜索算法例如使用困惑度perplexity作为评分标准。考虑更丰富的上下文窗口。6. 搭建一个简单的后处理流水线现在我们把上面的步骤串起来形成一个简单的自动化流程。这个流程可以根据你的需求调整顺序或增删模块。class OCRPostProcessor: def __init__(self, custom_dict_pathNone, common_typos_mapNone, char_candidate_mapNone): self.common_typos common_typos_map or {} self.char_candidates char_candidate_map or {} if custom_dict_path: jieba.load_userdict(custom_dict_path) def clean_format(self, text): 步骤1: 基础格式清洁 text basic_clean(text) text correct_punctuation(text) return text def correct_with_dict(self, text): 步骤2: 基于词典和规则的纠错 text correct_by_rules(text, self.common_typos) # 这里可以加入更复杂的词典匹配逻辑 return text def correct_with_context(self, text): 步骤3: 基于上下文的纠错简化版 # 这是一个示意性的实现。实际应用中这里应调用一个更完善的语言模型纠错函数。 # 我们可以先按句分割然后对每句话进行处理。 sentences re.split(r[。\.!?;], text) corrected_sentences [] for sent in sentences: if not sent.strip(): corrected_sentences.append(sent) continue # 假设我们有一个函数 advanced_context_correction 来实现第5节的方法 # corrected_sent advanced_context_correction(sent, self.char_candidates) # 此处为简化暂不实现 corrected_sentences.append(sent) # 暂时原样返回 # 重新组合句子这里简单用句号连接。实际应保留原标点。 return 。.join(corrected_sentences) ( if text.endswith(tuple(。.!?;)) else 。) def process(self, raw_ocr_text): 主处理流程 print( 开始后处理 ) print(f原始文本:\n{raw_ocr_text}\n) step1_text self.clean_format(raw_ocr_text) print(f1. 格式清洁后:\n{step1_text}\n) step2_text self.correct_with_dict(step1_text) print(f2. 规则纠错后:\n{step2_text}\n) # step3_text self.correct_with_context(step2_text) # print(f3. 上下文纠错后:\n{step3_text}\n) # 由于上下文纠错示例较复杂此处注释掉最终结果用step2_text final_text step2_text print(f 最终处理结果 \n{final_text}) return final_text # 使用示例 processor OCRPostProcessor( common_typos_mapcommon_typos, # char_candidate_mapshape_similar_chars, # 可传入形近字映射 ) raw_text 这是一段GLM-OCR的识别结果。\n\n\n 中间有, 很多 不必要的空格 和换行。 并且存在一些常见错别字例如帐号、登陆等。星图科技是一家优秀的工司。 final_result processor.process(raw_text)运行这个流水线你会看到文本一步步变得干净、规范。从杂乱无章的原始输出到格式规整、错误修正的可用文本。7. 总结与建议给GLM-OCR的识别结果做后处理其实是一个从“粗糙”到“精细”的打磨过程。我们聊的方法从简单的正则表达式清洗格式到用自定义词典修正固定错误再到尝试利用语言模型理解上下文算是一个由易到难的入门路径。实际用起来你会发现规则正则和词典能解决大部分有规律的、高频的错误见效快维护也直观。而引入N-gram或更高级的模型比如BERT来做上下文纠错则是为了对付那些“看起来都对但组合起来不对”的疑难杂症这部分需要更多的数据和调优。给你的建议是先从规则入手把那些明显的格式问题和你知道的常见错别字搞定。收集一批你们业务中典型的OCR错误案例不断丰富你的纠错规则库。当规则遇到瓶颈比如纠错准确率上不去了再考虑引入语言模型。一开始可以用开源的预训练模型试试水如果效果不错且确有需要再考虑收集领域数据做微调。记住没有一劳永逸的银弹。最好的后处理系统往往是规则和模型结合并且能随着新错误样本不断进化的。动手试试看从清理一段脏文本开始你会慢慢找到最适合自己那个场景的“打磨”工序。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。