web-dev-qa-db-ja.com

ユーザー入力用の明確に見える文字と数字のセット

読みやすい英数字の既存のサブセットはありますか?特に、視覚的に曖昧な文字が少ないサブセットはありますか?特定の文字を削除(または同等化)することで、人的エラーを減らしますか?

「視覚的に曖昧」という表現はやや不自然ですが、D、O、0がすべて類似しており、1とIも類似していることは明らかです。英数字のセットのサイズを最大にしたいのですが、誤解される可能性のある文字の数を最小にします。

そのようなセットについて私が知っている唯一の前例は、 カナダの郵便番号 文字D、F、I、O、Q、およびUを削除するシステムであり、そのサブセットは郵便を支援するために作成されましたシステムの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 [。 ] 9 

この問題は、特定の書体から分離するのが難しい場合があります。選択した書体の文字の識別性は、任意の2つの文字の潜在的な視覚的曖昧さに大きく影響する可能性がありますが、ほとんどの最新の書体では、同等の上記の文字は、同等にするのに十分な類似の外観を持つと思います。

上記について考えていただければ幸いです。上記の方程式は適切ですか、それとも同等にする必要のある文字が他にもありますか?小文字の方が適していますか?

24
Brian M. Hunt

主に このUXスレッド からインスピレーションを得て、@ rwbが言及し、

  • いくつかプログラム 同様のものを使用します。あなたの投稿のリストは、これらのプログラムで使用されているものと非常に似ているようで、ほとんどの目的には十分なはずです。小さな間違いを「許す」ために、常に冗長性(エラー訂正)を追加することができます。ただし、これにはコードのスペースを空ける必要があります( ハミング距離 を参照)。
  • 人間による試行錯誤を除いて、リストの導出に使用された特定の方法に関する参照はありません(これは非OCRに最適です:ユーザー人間です)
  • 文字のグループ化(たとえば、5つのグループ)を使用してコンテキスト(「5つのグループの2番目の最初の文字」)を増やすことは理にかなっています。
  • 文字の代わりに 完全な名詞 (類似点が少ない辞書から。ここではWord-edit-distanceが役立つ場合があります)を使用することで、あいまいさを解消できます。 「1」と「i」を混同する人もいるかもしれませんが、「one」と「ice」を混同する人はほとんどいません。
  • もう1つのオプションは、コードを大声で読み上げることができる(偽の)単語にすることです。 markovモデル はそこであなたを助けるかもしれません。
13
tucuxi

同様の理由(たとえば、キーのエンコードなど)で16進数(基数16)の置換が必要でした。私が思いつくことができる最善の方法は、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

交換セットでは、次のことを考慮します。

使用されるすべての文字には、本当にひどいフォントでのみ省略される主要な特徴があります。

母音AE I O Uは、誤って単語を綴らないように省略されています。

一部のフォントで非常に類似または同一である可能性のある文字のセットは完全に回避されます(どのセットの文字もまったく使用されません)。

0 O D Q 
1 I L J
8 B 
5 S
2 Z

これらの文字を完全に回避することにより、ユーザーが誤って入力された文字を修正しようとするのではなく、正しい文字を入力することが期待されます。

類似性は低いが混乱を招く可能性のある文字のセットの場合、各セットで1つの文字のみを使用します。これは、できれば最も特徴的な文字です。

Y U V 

ここではYが使用されています。これは、常に下部の垂直セクションがあり、セリフフォントのセリフがあるためです。

C G         

ここでは、CがGとして入力される可能性が低いため、Cが使用されます。

X K         

ここではXが使用されています。これは、ほとんどのフォントでより一貫性があるためです。

F E         

ここでは母音ではないのでFを使用します

これらの同様のセットの場合、セット内の任意の文字のエントリは、実際に使用されている文字(各セットにリストされている最初の文字)に自動的に変換される可能性があります。 16進入力を使用する可能性がある場合は、Eを自動的にFに変換してはならないことに注意してください(以下を参照)。

交換セットにはまだ似たような文字が含まれていることに注意してください。これはほとんど避けられません。音読するときは、ふりがなを使用する必要があります。

標準の16進数にも存在する文字が置換セットで使用されている場合、それらは同じ基数16の値に使用されます。理論的には、Eが自動的にFに変換されない限り、16進文字と置換文字の混合入力をサポートできます。

これは単なる文字置換であるため、16進数への変換/ 16進数からの変換は簡単です。

出力の「正規」形式には大文字が最適のようですが、ほとんどのフォントで比較的明確な「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
12
trepidacious

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. あいまいさを一貫して解決する:各グループから1つの文字のみを使用する限り(たとえば、小文字のs、大文字のS、および5つのうち、5つしか使用しない場合があります)、あいまいな文字を使用してもかまいません。そうすれば、バックエンドで、これらのあいまいな文字をグループ内の1つの正しい文字に置き換えることができます。したがって、入力文字列「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
  • y/Y
  • z/Z/2

明確な文字:

これにより、母音のない、完全に明確な小文字/数字の文字が9つだけ残ると思います。

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

これらのあいまいなグループのそれぞれから1文字を追加すると(大文字を避けながら、最もはっきりと見える文字を優先しようとします)、23文字になります。

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

分析:

Sqrt(N)インスタンスの衝突を回避するには、Nの可能性の数値的に同等の範囲を持つUUIDで十分であるという経験則を使用します。

  • この文字セットを使用する8桁のUUIDは、約300,000インスタンスの衝突を回避するのに十分なはずです。
  • この文字セットを使用する16桁のUUIDは、約800億のインスタンスの衝突を回避するのに十分なはずです。
4
Ben Wheeler

あなたが求めているのは、明確で効率的なヒューマンコンピュータコードです。私がお勧めするのは、データ全体をリテラル(意味のある)単語、特に名詞でエンコードすることです。

私はまさにそれを行うためのソフトウェアを開発してきました-そして最も効率的に。私はそれを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 (移動するまでお待ちくださいアップロードしています...)

3
Ujjwal Singh

これは、OCRの一般的な問題です。したがって、OCRエンコーディングが制御されるエンドツーエンドソリューションのために、あなたが言及した「視覚的な曖昧さ」の問題を解決するために特殊なフォントが開発されました。参照: http://en.wikipedia.org/wiki/OCR-A_font

追加情報として:Base32エンコーディングについて知りたい場合があります。数字「1」の記号は、ユーザーをアルファベット「l」の記号と「混同する可能性があるため」使用されていません。

2
Ujjwal Singh

セットの大きさによって異なります。たとえば、セット{0、1}だけがおそらくうまく機能します。同様に、数字のセットのみ。ただし、元の文字セットの約半分のサイズのセットが必要になる場合があります。

私はこれをしていませんが、ここに提案があります。フォントを選択し、最初の文字セットを選択して、次のことを行うためのコードを記述します。 n = 1から(たとえば)10の場合、白黒ピクセルのn行n列の正方形に収まるように各文字を描画します。関心があるのはエッジからすべて白の行と列を切り取ります。黒い領域。これにより、各文字の10個のコードのリストが得られます。これらのコードの違いの数によって、任意の2文字間の距離を測定します。アプリケーションで許容できる距離を見積もります。次に、それほど離れていない文字のセットをブルートフォース検索します。

基本的に、スクリプトを使用してキャラクターの目を細めることをシミュレートし、どのキャラクターを区別できるかを確認します。

1
Hew Wolff

上記の文字システムを使用して整数をエンコードおよびデコードするために作成した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))
1
Lucas