【问题标题】:Set of unambiguous looking letters & numbers for user input用于用户输入的一组明确的字母和数字
【发布时间】:2012-08-08 19:41:59
【问题描述】:

是否存在更易于阅读的字母数字子集?特别是,是否存在具有较少视觉模糊字符的子集,并且通过删除(或等同)某些字符可以减少人为错误?

我知道“视觉上模棱两可”的表达方式有些古怪,但很明显 D、O 和 0 都很相似,1 和 I 也很相似。我想最大化字母数字集的大小,但尽量减少可能被误解的字符数。

我所知道的此类集合的唯一先例是 Canada Postal code 系统,该系统删除了字母 D、F、I、O、Q 和 U,并且创建该子集是为了帮助邮政系统的 OCR 过程。

我最初的想法是只使用大写字母和数字,如下所示:

一种 B = 8 C = G D = 0 = O = Q E = F H 我 = J = L = T = 1 = 7 K = X 米 ñ 磷 R S = 5 U = V = Y W Z = 2 3 4 6 9

这个问题可能很难与给定的字体分开。所选字体中字符的独特性可能会显着影响任何两个字符的潜在视觉模糊性,但我希望在大多数现代字体中,上述等同的字符将具有足够相似的外观以保证将它们等同。

我将不胜感激以上的想法 - 上述等式是否合适,或者是否有更多的字符应该等同?小写字符会更合适吗?

【问题讨论】:

  • 注意:“视觉模糊”是指人类的上下文,而不是 OCR 系统。所需的解决方案是辅助手动输入。
  • @rwb:如果您将此作为答案,它可能会获得赏金。用户体验中的讨论正是 OP 所寻找的。​​span>
  • 赏金已关闭 - 我有一个“更好”的解决方案..
  • 在 GitHub 上发布.. 预计 6 小时

标签: character hid typography


【解决方案1】:

这将是 OCR 中的普遍问题。因此,对于控制 OCR 编码的端到端解决方案 - 已经开发了专门的字体来解决您提到的“视觉模糊”问题。 见:http://en.wikipedia.org/wiki/OCR-A_font

作为附加信息:您可能想了解 Base32 编码 - 其中不使用数字“1”的符号,因为它可能会“混淆”用户与字母“l”的符号。

【讨论】:

  • 谢谢 - Base32 是一个很好的提示。严格来说,这个问题仅通过加拿大邮政删除对机器阅读器模棱两可的字符的先例与 OCR 相关。我对一个对人类来说不那么模棱两可的字符(或字形,真的)集很感兴趣。
  • 您可以在 base32 编码中使用您的自定义符号集,而实现部分保持不变。
【解决方案2】:

这取决于您希望您的套装有多大。例如,只有 {0, 1} 集可能会很好地工作。同样只有一组数字。但您可能想要一个大约是原始字符集一半大小的字符集。

我还没有这样做,但这里有一个建议。选择一种字体,选择一组初始字符,然后编写一些代码来执行以下操作。绘制每个字符以适合 n×n 的黑白像素正方形,n = 1 到(比如说)10。从边缘切掉所有全白的行和列,因为我们只对黑色区域。这为您提供了每个字符的 10 个代码列表。通过这些代码中有多少不同来测量任何两个字符之间的距离。估计您的应用程序可接受的距离。然后对相距很远的一组字符进行暴力搜索。

基本上,使用脚本来模拟眯眼看角色,看看你还能分辨出哪些角色。

【讨论】:

  • 这在很大程度上取决于字体,甚至字体大小。它还可能需要一些蛮力对齐:LI 共享几个像素,直到您放置垂直笔划以使它们重叠。
【解决方案3】:

主要从@rwb提到的this ux thread中汲取灵感,

  • Several programs 使用类似的东西。您帖子中的列表似乎与这些程序中使用的列表非常相似,我认为对于大多数用途来说应该足够了。您可以添加总是添加冗余(纠错)以“原谅”小错误;不过,这将要求您将代码分隔开(请参阅Hamming distance)。
  • 除了反复试验外,没有提及用于导出列表的特定方法 与人类(这对于非 ocr 非常有用:您的用户人类)
  • 使用字符分组(例如,5 个一组)来增加上下文(“5 个组中的第二个中的第一个字符”)可能是有意义的
  • 可以通过使用complete nouns(来自几乎没有相似之处的字典;word-edit-distance 在这里可能有用)而不是字符来消除歧义。人们可能会将“1”与“i”混淆,但很少有人会将“one”与“ice”混淆。
  • 另一种选择是将您的代码变成可以大声读出的(假)单词。 markov model 可以帮助您。

【讨论】:

  • 错误修正在 UX 中可能被低估了。这里一个有价值的位可能是视觉距离度量 - 例如 O/D/0 更接近于例如C/Q,但离例如更远。 I/H/R。正如其他地方所提到的,这可能在很大程度上取决于字体。不依赖于视觉的基于符号的纠错(例如 Reed Solomon)可能更简单、更有效。这真是一个很棒的见解,tucuxi,谢谢!
【解决方案4】:

您寻求的是明确、高效的人机代码。我建议使用文字(有意义的)单词,尤其是名词来编码整个数据。

我一直在开发一种软​​件来做到这一点——而且效率最高。我称之为 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(请稍候,我正在上传……)

【讨论】:

【解决方案5】:

出于类似的原因(例如,用于对密钥进行编码等),我需要替换十六进制(以 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

【讨论】:

【解决方案6】:

这是我编写的一些 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))

【讨论】:

    【解决方案7】:

    我的 23 个明确字符是:

    c,d,e,f,h,j,k,m,n,p,r,t,v,w,x,y,2,3,4,5,6,8,9

    我需要一组明确的字符供用户输入,但我找不到其他人已经生成符合我标准的字符集和规则集的任何地方。

    我的要求:

    1. 没有大写字母:这应该在 URI 中使用,并且由可能没有很多打字经验的人输入,对于他们来说,即使是 shift 键也会减慢他们的速度并导致不确定性。我也希望有人能够说“全小写”以减少不确定性,所以我想避免大写字母。

    2. 很少或没有元音:避免产生粗俗语言或令人惊讶的词的简单方法是简单地省略大多数元音。我认为保留“e”和“y”是可以的。

    3. 始终如一地解决歧义:我愿意使用一些歧义字符,只要我只使用每组中的一个字符(例如,在小写 s、大写 S 和五个中,我可能只使用五个);这样,在后端,我可以用他们组中的一个正确字符替换这些模棱两可的字符中的任何一个。因此,在我在我的数据库中查找它的匹配项之前,输入字符串“3Sh”将被替换为“35h”。

    4. 只需要创建标记:我不需要像 base64 或 base32 那样对信息进行编码,所以我的集合中的确切字符数并不重要,除了我希望可能的。它只需要对生成随机 UUID 类型的 id 令牌有用。

    5. 非常喜欢明确性:我认为与某人必须输入更长的令牌相比,输入令牌并出现问题的成本要高得多。当然,有一个权衡,但我更喜欢简洁而不是模糊。

    我发现的易混淆的字符组:

    • A/4
    • b/6/G
    • 8/B
    • c/C
    • f/f
    • 9/g/q
    • i/I/1/l/7 - 太模糊而无法使用;请注意,欧洲的“1”可能看起来很像许多人的“7”
    • k/K
    • o/O/0 - 太含糊而无法使用
    • p/p
    • s/S/5
    • v/v
    • w/w
    • x/x
    • 年/年
    • z/Z/2

    明确的字符:

    我认为这只剩下 9 个完全明确的小写/数字字符,没有元音:

    d,e,h,j,m,n,r,t,3

    从每个模棱两可的组中添加一个字符(并尝试更喜欢看起来最明显的字符,同时避免大写),共有 23 个字符:

    c,d,e,f,h,j,k,m,n,p,r,t,v,w,x,y,2,3,4,5,6,8,9

    分析:

    使用经验法则,即具有 N 种可能性的数值等效范围的 UUID 足以避免 sqrt(N) 实例的冲突:

    • 使用此字符集的 8 位 UUID 应该足以避免大约 300,000 个实例的冲突
    • 使用此字符集的 16 位 UUID 应该足以避免大约 800 亿个实例的冲突。

    【讨论】:

      【解决方案8】:

      如果您可以选择仅使用大写字母,我会根据用户通常输入错误的字符创建此集合,但这完全取决于他们阅读文本时使用的字体。

      要使用的字符: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
      

      【讨论】:

        【解决方案9】:

        base58:123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

        【讨论】:

          【解决方案10】:

          对于人类而言具有明确外观的字母对于光学字符识别 (OCR) 而言也是明确的。通过删除所有对 OCR 造成混淆的字母对,可以获得:

           !+2345679:BCDEGHKLQSUZadehiopqstu
          

          https://www.monperrus.net/martin/store-data-paper

          【讨论】:

            猜你喜欢
            • 2018-07-02
            • 1970-01-01
            • 2020-03-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-01-31
            • 1970-01-01
            相关资源
            最近更新 更多