Closed qwedc001 closed 10 months ago
在开始之前,请先更新一个Bug补丁:
将UmiOCR-data\qt_res\qml\Configs\Configs.qml
更新到这个版本。其它文件可以不用动。
目前没有专门的下拉复选框组件,你可以用“可折叠配置项组”+开关,来模拟一组复选框。
"language": {
"title": "语言",
"type": "group",
"enabledFold": True, # 启用折叠
"fold": False, # 默认非折叠状态。(折叠状态会保存)
"cn": {
"title": "中",
"default": True,
},
"en": {
"title": "English",
"default": True,
},
"jp": {
"title": "日",
"default": False,
},
"~enabledOther": {
"title": "启用自定义语言短码",
"default": False,
},
"~other": {
"title": "自定义语言短码",
"toolTip": “请查看tesseract官方文档”,
"default": "",
},
},
请注意:当在python定义配置字典时,配置项组group内元素是按key的字符进行排序,而不是你编写的顺序。为了指定排序(比如让“自定义语言”固定在最后),需要调整key的字符,上述例子中"~other"
的~
就是这个目的。
所有配置类型的定义可以在UmiOCR-data\qt_res\qml\Configs\Configs.qml
开头的注释中查看。Python中不支持定义热键和按钮组(只能在qml中定义)。
还有,tesseract应该是首次运行时下载模型库的。咱需要将常用模型库(中英日)预先放置在插件包中,以便开箱即用,避免用户打开还要等半天。
如果允许用户下载新模型的话,下载目录看看能不能也改为存到插件目录中(默认应该是下载到C盘吧)。
好的,已了解。 我在官网上找下的tesseract好像是自带模型的,全部语言模型加起来约为300M,中英日约17M,我并不能确认该模型的版本是tesseract-best还是tesseract-fast,但是目前来看识别简中准确度有点低,我调试一下
按照上述方法处理数据以后,获取到的传参dict非常的 难以使用非硬编码形式处理。
还有其他传参的可能方式吗,要是没有的话我就硬编码了( 问了一下,朋友说Qt里面用QCheckbox来搞复选框,但具体怎么实现我就没接触过了。
动态解析示例:
# 解析参数字典argd,返回语言码列表
def get_select_languages(argd):
selects = [] # 存储当前选出的语言码
for k,flag in argd.items():
if k.startswith("language."):
language = k[9:] # 删除"language."
if language is tesseract的合法语言码:
if flag: # 传入True
selects.append(language)
return selects
另外,本项目用的是Qt Qml,跟传统的Qt QWidget不同。界面上几乎所有的组件,按钮啥的,都是我自己手写的。我暂时没写复选框(觉得没必要用这组件,懒得写)😂。如果确实有必要的话我可以写
动态解析示例:
# 解析参数字典argd,返回语言码列表 def get_select_languages(argd): selects = [] # 存储当前选出的语言码 for k,flag in argd.items(): if k.startswith("language."): language = k[9:] # 删除"language." if language is tesseract的合法语言码: if flag: # 传入True selects.append(language) return selects
嗷,合理 看来写代码经验还是少了点啊哈哈哈,行
手写也太强了,那就先用着这个解决方案吧,以后有更新再说
插件已经初步成型。 但是我这里遇到一个很棘手的问题,tesseractOCR给出的box数据无法正确被umi_ocr使用。直接导致无法正确重组识别出来的文字。在开启竖版识别的情况下尤为严重。该处核心代码如下
top,left,width,height = int(item[6]), int(item[7]), int(item[8]), int(item[9]) # 此处的magic number来源于tesseractOCR本身在调用OCR后返回的table,参数固定。
topLeft = [top,left]
topRight = [top,left+width]
bottomLeft = [top+height,left]
bottomRight = [top+height,left+width]
box = [topLeft,topRight,bottomLeft,bottomRight]
当前全部代码因为代理抽风问题还没push到repo。理论上来讲解决完box的问题就可以用了 在和学长讨论这个box的问题
box列表的排序错了。四个元素应该是:从左上角开始,顺时针遍历四个角的坐标,即:
[topLeft,topRight, bottomRight, bottomLeft]
你下次遇到这类问题时,可以尝试跟已知正常的部分进行比较。比如先使用PaddleOCR插件,打印正确的box。然后同一张图片,使用tesseract插件打印box。将两个数据进行对比,很容易就能看出问题所在。
tesseract返回的最小单位似乎是单词,但Umi中是以行为最小单位的。你检查一下tesseract官方有没有提供返回整行的方法。
如果没有,要手动将tesseract的结果合并回行。即,同一行的子块( line_num 相同的结果),合并为一个。
这涉及到box、text、score的合并。score取本行所有子块的平均值即可。box的合并,也许可以用所有子块的x、y的最大/最小值。text的合并,要考虑两个单词是不是英文;英文单词间要添加空格,而中文没有空格。
合并俩单词可参考:
# 获取两个连续单词的分隔符。letter1为单词1结尾字母,letter2为单词2结尾字母
def _word_separator(self, letter1, letter2):
# 判断结尾和开头,是否属于汉藏语族
# 汉藏语族:行间无需分割符。印欧语族:则两行之间需加空格。
ranges = [
(0x4E00, 0x9FFF), # 汉字
(0x3040, 0x30FF), # 日文
(0xAC00, 0xD7AF), # 韩文
(0xFF01, 0xFF5E), # 全角字符
]
fa, fb = False, False
for l, r in ranges:
if l <= ord(letter1) <= r:
fa = True
if l <= ord(letter2) <= r:
fb = True
if fa and fb: # 两个字符都是汉藏语族,才没有空格
return ""
# 特殊情况:字母2为缩写,如 n't。或者字母2为结尾符号,意味着OCR错误分割。
if letter2 in {r"'", ",", ".", "!", "?", ";", ":"}:
return ""
# 其它正常情况,如 俩单词 或 一单词一汉字,加空格
return " "
box排序问题解决了,不过程序行为仍然不符合预期。当前代码已提交。
经过排查,我们发现tesseractOCR识别文字的box并不稳定,最常出现的情况是标点符号的box比文字的box小非常多。导致umi-ocr不能正确对其进行拼接。
我们研究了一下tesseract的传出数据,现在有两种解决方案,一种是在插件里根据tesseract提供的行号或段落号(参见api_tesseractorc.py第53行)在插件内进行合并字符串并计算新的大box,这样操作后umi_ocr不再需要(应该也不能)进行box合并操作。
第二种方法是给umi
我刚刚就在写这个,笑死了()
哈哈哈~~
另外,tesseract本身是个命令行程序,pytesseract是它的一个第三方python接口。
tesseract有不止一个第三方接口,如这也是一个。
如果觉得 pytesseract 这个接口太难用,自己解析结果较复杂。也可以测试一下别的接口,看看会不会封装得更好用。
pytesseract 会将每次交互的文本缓存到本地文件中,依我看……emmm……太不优雅了
已经依据pytesseract完成tesseract接口实现。目前正在测试中。已经推送repo 新的第三方接口我还没细看,如果确实省很多事就换一下,不过现在可用性还不错。 分词直接使用了您的函数,然后分词依据没再使用line num而是选择了level 5进行依据,目前测试会出现偶尔丢整行识别的情况,一会跑个batch测一下。可能是哪里逻辑还有点小问题。(目前测试是关掉自动识别排版按钮可以规避这个问题,好奇怪的临时解决方案)
你把整个插件打个压缩包扔release里
没事,先不用写i18n。现在还不确定有没有文本要改。差不多搞完了,快发布了在搞文本翻译。
丢失整行识别,是因为 101行 ,你根据if level != 5 and len(scores) != 0:
来执行datas.append。
所以最后几次for循环的文本块没有被添加到datas中(最后几次循环,level肯定是5)。
然后关于自定义语言码。既然咱的插件不支持自动下载新语言库,就意味着用户要手动下载语言库、放到engine/tessdata
目录中、还要手动填写语言短码。应该将“填写语言短码”这一步优化掉,改为程序自动搜索可以使用的语言库,在UI上显示出来。
具体来说,插件初始化时你可以搜索engine/tessdata
目录中.traineddata
后缀的文件,提取文件名,与tesseract语言列表进行对比,识别出它是什么语言库。然后,动态构建localOptions的"language"属性,添加对应的配置项。
本仓库现有的PaddleOCR-json等插件,均使用动态搜索语言配置文件、自动生成配置项的方式,可参考。
我考虑了一下,决定采用的方式是常见语言进行标识,其他语言统一显示为英文的动态生成方式。 然后我在翻阅所有可支持语言的时候发现两个特殊模块,一个是equ,是专门的数学识别模块,这个我会在更新中添加到常驻识别。另一个osd似乎和排版有关,我再研究一下。
已经实现。请检查,没问题我就添加git submodule并且提交pr了。
你现在可以先PR过来,后续继续优化。
以下我发现的一些问题和建议,请一条条核对:
textBlock = {"text":"文本", "box":包围盒, "score ":置信度,
"end": "\n", # 如果这个block为自然段的末尾行,那么结尾间隔符为"\n"。否则,为空格" "或者空""
}
在新版软件面板中,也会通过小回车图标,标出结尾为\n的文本块。
你需要从tesseract的结果中,判断哪些文本块属于自然段的结尾=,end为\n。其余文本块,end为" "或""(根据上下文是汉字还是字母)。
这时,软件面板上设置里的”排版解析方案“换成”不做处理“,Umi就会优先采用tesseract的排版结果。
TESSERACT_SUPPORTED = {
"equ": tr("数学公式"), # 这个使用tr翻译
"chi_sim": "简体中文",
"eng": "English",
"chi_tra": "繁體中文",
"jpn": "日本語",
"korean": "한국어",
"cyrillic": "Русский",
# .....补充更多语言
}
收到,这样我就把这里的issue关掉了,在tesseract处开一个新的todo issue,感谢建议。
如标题。 两者均针对tesseract可以支持多种语言同时识别的处理情况。tesseract在github上给出的可支持语言太多,全部写入可以但未免选择太过繁琐,所以我想在复选框里提供中英日,其他选项提供对应短码让用户自行选择填写。但是目前config里的optionsList只能做到单选。