Mathematica 1170 1270 1096 1059 650 528 570 551 525 498バイト
最新バージョンでは、解析前にプレートを「トリミング」する必要がないため、27バイトが節約されます。最後から2番目のバージョンでは、元の24個のサンプルポイントのうち10個だけを使用して26バイトを節約しました。
z=Partition;h@i_:=i~PixelValue~#/.{_,_,_,z_}:>⌈z⌉&/@z[{45,99,27,81,63,81,9,63,45,63,9,45,45,45,63,45,45,27,45,9},2];f@p_:=h/@SortBy[Select[p~ColorReplace~Yellow~ComponentMeasurements~{"Image","Centroid"},100<Last@ImageDimensions@#[[2,1]]<120&],#[[2,2,1]]&][[All,2,1]]/.Thread[IntegerDigits[#,2,10]&/@(z[IntegerDigits[Subscript["ekqeuiv5pa5rsebjlic4i5886qsmvy34z5vu4e7nlg9qqe3g0p8hcioom6qrrkzv4k7c9fdc3shsm1cij7jrluo", "36"]],4]/.{a__Integer}:> FromDigits[{a}])-> Characters@"BD54TARP89Q0723Z6EFGCSWMNVYXHUJKL1"]
LegionMammal978の基数10の長いリストを単一の基数36の数としてパックするというアイデアによって保存された122バイト。彼は最終的なコードからさらに20バイトを切り取った。
528バイトから570バイトへのジャンプは、返される文字の順序がナンバープレート上の文字の順序に対応するようにするための追加コードによるものでした。各文字の重心にはx座標が含まれ、xに沿った文字の相対的な位置が明らかになります。
未ゴルフコード
coordinates=Flatten[Table[{x,y},{y,99,0,-18},{x,9,72,18}],1];
h[img_] :=ArrayReshape[PixelValue[img, #] /. {_, _, _, z_} :> ⌈z⌉ & /@ coordinates, {6, 4}];
plateCrop[img_]:=ColorReplace[ImageTrim[img,{{100,53},{830,160}}],Yellow];
codes={{{15,13,15,13,13,15},"B"},{{15,8,8,8,9,15},"C"},{{15,13,13,13,13,15},"D"},{{15,8,14,8,8,15},"E"},{{15,8,14,8,8,8},"F"},{{15,8,8,11,9,15},"G"},{{6,6,6,6,15,9},"A"},{{9,9,15,15,9,9},"H"},{{8,8,8,8,8,15},"L"},{{9,15,15,15,13,9},"M"},{{15,9,9,9,9,15},"0"},{{9,10,12,14,10,9},"K"},{{9,13,13,11,11,9},"N"},{{8,8,8,8,8,8},"1"},{{1,1,1,1,9,15},"J"},{{15,9,15,14,8,8},"P"},{{15,9,9,9,15,15},"Q"},{{15,9,15,14,10,11},"R"},{{15,8,12,3,1,15},"S"},{{9,15,6,6,6,6},"V"},{{15,6,6,6,6,6},"T"},{{9,15,15,15,15,15},"W"},{{9,9,9,9,9,15},"U"},{{9,14,6,6,14,9},"X"},{{9,14,6,6,6,6},"Y"},{{15,3,2,4,12,15},"Z"},{{15,9,9,9,9,15},"0"},{{8,8,8,8,8,8},"1"},{{15,1,3,6,12,15},"2"},{{15,1,3,1,9,15},"3"},{{2,6,6,15,2,2},"4"},{{7,12,14,1,1,15},"5"},{{15,8,14,9,9,15},"6"},{{15,1,2,2,6,4},"7"},{{15,9,15,9,9,15},"8"},{{15,9,15,1,9,15},"9"}};
decryptRules=Rule@@@codes;
isolateLetters[img_]:=SortBy[Select[ComponentMeasurements[plateCrop[img],{"Image","Centroid"}],ImageDimensions[#[[2,1]]][[2]]>100&],#[[2,2,1]]&][[All,2,1]]
f[plate_]:=FromDigits[#,2]&/@#&/@h/@isolateLetters[plate]/.decryptRules
概要
基本的な考え方は、入力画像からのピクセルの体系的なサンプリングが、真正な画像上の同じ場所からのピクセルと一致するかどうかをチェックすることです。コードの大部分は各文字のビット署名で構成されており、
この図は、「J」、「P」、「Q」、および「R」の文字からサンプリングされたピクセルを示しています。
ピクセル値は行列として表すことができます。暗い太字1
は黒いセルに対応しています。は0
白血球に対応します。
これらは、JPQ Rの復号化置換ルールです。
{1、1、1、1、1、9、15}-> "J"、
{15、9、15、14、8、8}-> "P"、
{15、9、9、9、9、15、15 }-> "Q"、
{15、9、15、14、10、11}-> "R"
「0」のルールが次の理由であることが理解できるはずです。
{15、9、9、9、9、9、15}-> "0"
したがって、文字「Q」と区別できます。
以下は、最終バージョンで使用される10ポイントを示しています。これらのポイントは、すべてのキャラクターを識別するのに十分です。
機能がすること
plateCrop[img]
フレームと左端をプレートから削除し、背景を白にします。100〜120ピクセルの高さの可能性のある文字、イメージコンポーネントを選択することにより、最終バージョンからこの機能を削除することができました。
isolateLetters[img]
トリミングされた画像から個々の文字を削除します。
からの出力plateCrop
がの入力として切り取られた画像の場所を示すことで、その動作を表示できますisolateLetters
。出力は、個々の文字のリストです。
Coordinates
ピクセルカラーをチェックするための24の均等に分布した位置です。座標は、最初の図の座標に対応しています。
coordinates=Flatten[Table[{x,y},{y,99,0,-18},{x,9,72,18}],1];
{{9、99}、{27、99}、{45、99}、{63、99}、{9、81}、{27、81}、{45、81}、{63、81}、{ 9、63}、{27、63}、{45、63}、{63、63}、{9、45}、{27、45}、{45、45}、{63、45}、{9、 27}、{27、27}、{45、27}、{63、27}、{9、9}、{27、9}、{45、9}、{63、9}}
h
ピクセルをバイナリに変換します。
h[img_] :=ArrayReshape[PixelValue[img, #] /. {_, _, _, z_} :> ⌈z⌉ & /@ coordinates, {6, 4}];
codes
各文字の署名です。10進値は、黒(0)および白(1)セルのバイナリコードの略語です。ゴルフバージョンでは、ベース36が使用されます。
codes={{{15, 9, 9, 9, 9, 15}, "0"}, {{8, 8, 8, 8, 8, 8}, "1"}, {{15, 1, 3,6,12, 15}, "2"}, {{15, 1, 3, 1, 9, 15}, "3"}, {{2, 6, 6, 15, 2, 2}, "4"}, {{7, 12, 14, 1, 1, 15},"5"}, {{15, 8, 14, 9, 9, 15}, "6"}, {{15, 1, 2, 2, 6, 4},"7"}, {{15, 9, 15, 9, 9, 15}, "8"}, {{15, 9, 15, 1, 9, 15},"9"}, {{6, 6, 6, 6, 15, 9}, "A"}, {{15, 13, 15, 13, 13, 15}, "B"}, {{15, 8, 8, 8, 9, 15}, "C"}, {{15, 13, 13, 13, 13, 15}, "D"}, {{15, 8, 14, 8, 8, 15}, "E"}, {{15, 8, 14, 8, 8, 8},"F"}, {{15, 8, 8, 11, 9, 15}, "G"}, {{9, 9, 15, 15, 9, 9}, "H"}, {{1, 1, 1, 1, 9, 15}, "J"}, {{9, 10, 12, 14, 10, 9}, "K"}, {{8, 8, 8, 8, 8, 15}, "L"}, {{9, 15, 15, 15, 13, 9}, "M"}, {{9, 13, 13, 11, 11, 9}, "N"}, {{15, 9, 15, 14, 8, 8}, "P"}, {{15, 9, 9, 9, 15, 15}, "Q"}, {{15, 9, 15, 14, 10, 11}, "R"}, {{15, 8, 12, 3, 1, 15}, "S"}, {{15, 6, 6, 6, 6, 6}, "T"}, {{9, 9, 9, 9, 9, 15}, "U"}, {{9, 15, 6, 6, 6, 6}, "V"}, {{9, 15, 15, 15, 15, 15}, "W"}, {{9, 14, 6, 6, 14, 9}, "X"}, {{9, 14, 6, 6, 6, 6}, "Y"}, {{15, 3, 2, 4, 12, 15}, "Z"}};
(* decryptRules
は、署名をそれぞれの文字に置き換えるためのものです*)
decryptRules=Rule@@@codes;
f
ナンバープレートの画像を取得し、文字を返す関数です。
f[plate_]:=FromDigits[#,2]&/@#&/@h/@isolate[plateCrop@plate]/.decryptRules;
{「A」、「B」、「C」、「D」、「E」、「F」、「G」}
{「H」、「1」、「J」、「K」、「L」、 「M」、「N」、「0」}
{「P」、「Q」、「R」、「S」、「T」、「U」、「V」、「W」}
{「X」、 「Y」、「Z」、「0」、「1」、「2」、「3」、「4」}
{「5」、「6」、「7」、「8」、「9」}
ゴルフ
単一の10進数を使用して各文字の24ビット(白または黒)をすべて表すことにより、コードが短縮されます。たとえば、文字「J」は次の置換ルールを使用します1118623 -> "J"
。
1118623に対応
IntegerDigits[1118623 , 2, 24]
{0、0、0、1、0、0、0、1、0、0、0、1、0、0、0、1、1、0、0、1、1、1、1、1}
次のように再パッケージ化できます
ArrayReshape[{0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1}, {6, 4}]
{{0、0、0、1}、{0、0、0、1}、{0、0、0、1}、{0、0、0、1}、{1、0、0、1} 、{1、1、1、1}}
これは、上で見た「J」の単純なマトリックスです。
%//MatrixForm
もう1つの節約は、アルファベット"0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
を文字のリストとしてではなく表現することです。
最後に、を除く長いバージョンのすべてのh
関数f
は、個別に定義されるのではなく、関数に統合されました。
h@i_:=ArrayReshape[i~PixelValue~#/.{_,_,_,z_}:>⌈z⌉&/@Join@@Table[{x,y},{y,99,0,-18},{x,9,72,18}],{6,4}];f@p_:=#~FromDigits~2&/@(Join@@@h/@SortBy[Select[p~ImageTrim~{{100,53},{830,160}}~ColorReplace~Yellow~ComponentMeasurements~{"Image","Centroid"},Last@ImageDimensions@#[[2,1]]>100&],#[[2,2,1]]&][[;;,2,1]])/.Thread[IntegerDigits[36^^1c01agxiuxom9ds3c3cskcp0esglxf68g235g1d27jethy2e1lbttwk1xj6yf590oin0ny1r45wc1i6yu68zxnm2jnb8vkkjc5yu06t05l0xnqhw9oi2lwvzd5f6lsvsb4izs1kse3xvx694zwxz007pnj8f6n,8^8]->Characters@"J4A51LUHKNYXVMW732ZTCGSFE60Q98PRDB"]