Bug
发现
前些天,在bilibili
的首页刷到一个名为 修BUG的第一天 我给微软的 PowerToys 修了一个 BUG
的视频。恰好Powertoys
这款软件我也在使用,于是便点进去看了看视频,是一个文字识别输出方面的Bug,但视频作者过于自信的语气,加之“标题的第一天”就是没有C#
或者大型项目
开发经验的代名词,对于他代码,我怀疑有问题。
第二天早上起来,测试相关模块功能,果然,只是从一个错误转移成了另一个错误。
Bug
解释
Using TextExtractor to extract Chinese always contains spaces
最初的bug源于此,是由于中文的文字图片识别引擎返回的内容是以字
为单位的,英文
部分则是以词为单位。最初的代码在所有的识别单位中添加一个
(空格)作为间隔。如此便导致了中文汉字间包含错误空格。
[TextExtractor] Add space between CJK words and non-CJK
错误修复示范:遍历判断单位是否CJK文字,如果是则不加空格,不是的话就前后各加一个空格。也就是从这 里 是 AO 的 blog , 你 好 !
变成了这里是 AO 的 blog , 你好 !
。
而实际正确的应该是这里是AO的blog,你好!
,英文和中文之间最好没有空格,标点也不应该有空格。这里就有一个新问题,标点怎么涵盖?既然是CJK,那么日语和韩语的情况呢?
韩文引擎表现不同,非单字识别,测试日文如下:
1そ の 後 、 2 人 の 住 む 関東 は 本格的 に 梅雨入 り し 、 雨 の 日 の 午前 た け の さ さ や か な 交流 が は し ま る 。
显然,日语的假名并没有算到CJK words
里。观察一下源代码:
1var cjkRegex = new Regex(@"\p{IsCJKUnifiedIdeographs}");
2foreach (OcrLine ocrLine in ocrResult.Lines){
3 bool isBeginning = true;
4 bool isCJKPrev = false;
5 foreach (OcrWord ocrWord in ocrLine.Words){
6 bool isCJK = cjkRegex.IsMatch(ocrWord.Text);
7 // Use spaces to separate non-CJK words.
8 if (!isBeginning && (!isCJK || !isCJKPrev)){
9 _ = text.Append(' ');
10 }
11 _ = text.Append(ocrWord.Text);
12 isCJKPrev = isCJK;
13 isBeginning = false;
14}
15...
16}
问题就出现在代码最开头,CJKUnifiedIdeographs
只包含CJK的汉字部分
。因此数字,假名,符号,统统都有空格。
Patch
那么,是否把所有的CJK符号
放到判断式子里就万事大吉了呢?并不,考虑下面情况,空格依旧是重要的:
1韩文半角符号
2⑨ 记得给你的switch充电
3「卍 解」天锁斩月
4现在的B站都喜欢给标题加上空格——《反 复 横 跳》
文本的多样性决定了,空格的出现是难以预料的,引擎的输出格式决定了丢失了一部分的信息,这部分的信息是难以通过代码复现的(比如这个项目的处理也有问题)。此问题应该交由引擎处理,或者分割开来,交给各语言的native speaker
来写处理规则,而不是简单的加个残缺的范围了事。
考虑到这个模块也不是主要模块,引擎目前功能并不完善,不支持多语言识别,语言种类识别加之识别率一般,所以简单做个补丁。
1// var cjkRegex = new Regex(@"\p{IsCJKUnifiedIdeographs}|\p{IsHiragana}|\p{IsKatakana}|[\uFF61-\uFF9F]|[\u3000-\u3003]");
2var cjkRegex = new Regex(@"\p{IsCJKUnifiedIdeographs}|\p{IsHiragana}|\p{IsKatakana}|[\uFF61-\uFF9F]");
{IsCJKUnifiedIdeographs}
for Kanji in JP and ZH
{IsHiragana}
for Hiragana
{IsKatakana}
for Katakana
[\uFF61-\uFF9F]
for Half-width Katakana
[\u3000-\u3003]
for the most common Punctuation
考虑中文、日文、韩文,加入最常用的假名,半角假名。可供正常阅读。
1その後 、 2 人の住む関東は本格的に梅雨入りし 、 雨の日の午前たけのささやかな交流がはじまる 。
吐槽
-
这个问题并没有得到很好的解决。最上策:有一个完备的引擎处理,准确的识别,具备以行为单位输出的功能。中策:分开处理,对每一种语言的符号进行详细的考证,编写规则,确保一般文本的准确性。(混合语言和新型新式可能会出错。)
-
微软,提高代码和审核的标准!(我说我电脑怎么越来越卡。这代码不卡才怪。) 如果没更好的解决办法,你就先把我的patch
并进去或者把那个问题代码迁出来吧。
更新
上游程序通过更加复杂的筛选方案,已经修复此Bug,并已合并到Powertoy
中,此帖终结。哈哈,相比之下,自己写的代码也是一坨,彼此彼此啦。