Mathematica 1170 1270 1096 1059 650528570551525525字节
最新版本节省了27个字节,因为不需要在分析之前先“修剪”盘子。倒数第二个版本仅使用原始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,9,9,15}->“ J”,
{15,9,15,14,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
是每个字符的签名。十进制值是黑色(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”}
打高尔夫球
通过使用单个十进制数字表示每个字符的所有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
另一个节省是通过将字母"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"]