是否有现有的字母数字子集更容易阅读?特别是,是否有一个子集具有较少的视觉模糊字符,通过删除(或等同)某些字符,我们减少了人为错误?
我知道“视觉模糊”在某种程度上是一种表达方式,但很明显D,O和0都是相似的,1和I也是相似的。我想最大化alpha-numerics集的大小,但最大限度地减少可能被误解的字符数。
我知道这个集合的唯一先例是删除字母D,F,I,O,Q和U的Canada Postal code系统,并创建该子集以帮助邮政系统的OCR过程
我最初的想法是只使用大写字母和数字如下:
A B = 8 C = G D = 0 = O = Q E = F H I = J = L = T = 1 = 7 K = X M N P R S = 5 U = V = Y W Z = 2 3 4 6 9
这个问题可能难以与给定的类型面分开。所选字体中字符的独特性可能会显着影响任何两个字符的潜在视觉模糊性,但我希望在大多数现代字体中,等同的上述字符将具有相似的足够外观以保证等同它们。
我对以上的想法感激不已 - 以上方程式是否合适,或者是否有更多应该等同的字符?小写字符会更合适吗?
答案 0 :(得分:10)
主要从this ux thread中汲取灵感,@ rwb提到
答案 1 :(得分:9)
由于类似的原因(例如编码密钥等),我需要替换十六进制(基数为16),我能想到的最好的是以下16个字符集,可用作替换十六进制:
0 1 2 3 4 5 6 7 8 9 A B C D E F Hexadecimal
H M N 3 4 P 6 7 R 9 T W C X Y F Replacement
在替换集中,我们考虑以下因素:
所有使用的字符都具有主要的区别特征,只能以真正糟糕的字体省略。
省略A E I O U以避免意外拼写单词。
完全避免在某些字体中可能非常相似或相同的字符集(根本不使用任何集合中的字符):
0 O D Q
1 I L J
8 B
5 S
2 Z
完全避免使用这些字符,希望用户输入正确的字符,而不是尝试纠正错误输入的字符。
对于不太相似但可能令人困惑的字符集,我们每集只使用一个字符,希望最有特色:
Y U V
这里使用了Y,因为它总是具有较低的垂直部分,并且具有衬线字体的衬线
C G
这里使用C,因为C似乎不太可能作为G输入,反之亦然
X K
这里使用X,因为它在大多数字体中更加一致
F E
这里使用F,因为它不是元音
在这些类似集合的情况下,集合中任何字符的输入可以自动转换为实际使用的字符(每个集合中列出的第一个字符)。请注意,如果可能使用十六进制输入,则不得将E自动转换为F(见下文)。
请注意,替换集中仍然存在类似声音的字母,这几乎是不可避免的。大声朗读时,应使用语音字母。
在替换集中使用标准十六进制中也存在的字符时,它们用于相同的base-16值。理论上,如果E不自动转换为F,则可以支持十六进制和替换字符的混合输入。
由于这只是一个字符替换,因此很容易转换为十六进制数。
大写似乎最适合输出的“规范”形式,虽然小写也看起来合理,除了“h”和“n”,在大多数字体中仍应相对清晰:
h m n 3 4 p 6 7 r 9 t w c x y f
输入当然可以不区分大小写。
基础32有几个类似的系统,请参阅http://en.wikipedia.org/wiki/Base32但是,这些显然需要引入更多看起来相似的字符,以换取每个字符额外25%的信息。
显然,以下集合也用于基础24中的Windows产品密钥,但同样具有更多相似的字符:
B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9
答案 2 :(得分:3)
我设置的22个明确的字符是:
c,d,f,h,j,k,m,n,p,r,t,v,w,x,y,2,3,4,5,6,8,9
我需要一组明确的字符来进行用户输入,我找不到其他人已经产生了符合我的标准的字符集和规则集的地方。
我的要求:
没有大写字母:应该在URI中使用,并由可能没有很多打字经验的人打字,即使是shift键也可能使它们变慢并引起不确定性。我还希望有人能够说“全部小写”,以减少不确定性,所以我要避免使用大写字母。
很少或没有元音:避免创建肮脏语言或令人惊讶的单词的一种简单方法是简单地忽略大多数元音。我认为保持“ y”是可以的。
始终如一地解决歧义性:我愿意使用一些模棱两可的字符,只要我在每个组中仅使用一个字符即可(例如,小写s,大写S和5中的一个,我可能只使用五个);这样,在后端,我可以将这些歧义字符中的任何一个替换为它们组中的一个正确字符。因此,在我在数据库中查找匹配的字符串之前,输入字符串“ 3Sh”将被替换为“ 35h”。
只需要创建令牌:我不需要像base64或base32这样编码信息,因此我的字符集中的确切字符数并不重要,除了我希望尽可能地大可能。它只需要用于生成随机UUID类型的id令牌。
强烈建议不要使用歧义性:我认为输入令牌并出问题的成本要比输入更长的令牌要高得多。当然,需要权衡取舍,但是我要强烈地选择简洁而不是简洁。
我确定的容易混淆的字符组:
明确的字符:
我认为这只剩下8个完全明确的小写/数字字符,没有元音:
d,h,j,m,n,r,t,3
从每个不明确的组中重新添加一个字符(并尝试使用看起来最独特的字符,同时避免使用大写字母),共有22个字符:
c,d,f,h,j,k,m,n,p,r,t,v,w,x,y,2,3,4,5,6,8,9
分析:
使用经验法则,一个数值等效范围为N的UUID足以避免sqrt(N)实例发生冲突:
答案 3 :(得分:3)
如果您可以选择仅使用大写字母,那么我将根据用户经常键入错误的字符来创建此字符集,但这完全取决于他们阅读文本所使用的字体。
要使用的字符:A C D E F G H J K L M N P Q R T U V W X Y 3 4 6 7 9
要避免的字符:
B similar to 8
I similar to 1
O similar to 0
S similar to 5
Z similar to 2
答案 4 :(得分:2)
这将是OCR中的一般问题。因此,对于控制OCR编码的端到端解决方案 - 已经开发了专门的字体来解决您提到的“视觉模糊”问题。 请参阅:http://en.wikipedia.org/wiki/OCR-A_font
作为附加信息:您可能想知道Base32编码 - 其中未使用数字'1'的符号,因为它可能会将用户与字母'l'的符号“混淆”。
答案 5 :(得分:2)
您所寻求的是一种明确,高效的人机代码。我建议使用文字(有意义的)单词编码整个数据,特别是名词。
我一直在开发一种软件来做到这一点 - 而且效率最高。我将其称为 WCode 。从技术上讲,它只是Base-1024编码 - 其中您使用的是单词而不是符号。
以下是链接:
演示文稿: https://docs.google.com/presentation/d/1sYiXCWIYAWpKAahrGFZ2p5zJX8uMxPccu-oaGOajrGA/edit
文档: https://docs.google.com/folder/d/0B0pxLafSqCjKOWhYSFFGOHd1a2c/edit
项目: https://github.com/San13/WCode(请等待我上传...)
答案 6 :(得分:2)
对于人类来说,看起来清晰的字母对于光学字符识别(OCR)也是明确的。通过删除所有对OCR造成混淆的字母,人们可以获得:
!+2345679:BCDEGHKLQSUZadehiopqstu
答案 7 :(得分:0)
这取决于你想要的大小。例如,只有集合{0,1}可能会运行良好。同样只是一组数字。但是你可能想要一个大约是原始字符集大小一半的集合。
我没有这样做,但这是一个建议。选择一种字体,选择一组初始字符,然后编写一些代码来执行以下操作。绘制每个字符以适合n×n方形的黑白像素,对于n = 1到(比如说)10。从边缘切掉任何全白的行和列,因为我们只对黑色区域。这为您提供了每个角色的10个代码列表。根据这些代码中有多少不同来测量任意两个字符之间的距离。估计您的应用可接受的距离。然后对一组相距甚远的角色进行蛮力搜索。
基本上,使用脚本来模拟斜视字符并查看哪些字符仍可分辨。
答案 8 :(得分:0)
这是我编写的一些python,它使用上述字符系统对整数进行编码和解码。
def base20encode(i):
"""Convert integer into base20 string of unambiguous characters."""
if not isinstance(i, int):
raise TypeError('This function must be called on an integer.')
chars, s = '012345689ACEHKMNPRUW', ''
while i > 0:
i, remainder = divmod(i, 20)
s = chars[remainder] + s
return s
def base20decode(s):
"""Convert string to unambiguous chars and then return integer from resultant base20"""
if not isinstance(s, str):
raise TypeError('This function must be called on a string.')
s = s.translate(bytes.maketrans(b'BGDOQFIJLT7KSVYZ', b'8C000E11111X5UU2'))
chars, i, exponent = '012345689ACEHKMNPRUW', 0, 1
for number in s[::-1]:
i += chars.index(number) * exponent
exponent *= 20
return i
base20decode(base20encode(10))
答案 9 :(得分:0)
base58:123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz