解决 QR 拼图的算法
Algorithm to solve QR puzzle
我正在构建算法以根据相同大小的块数自动解决/重建 QR 码。
我的做法:
- 获得 3 个边方块之一:位置方块
- 使用 ImageMagic 以某种方式获取外黑色边框的宽度
给定的示例是 14px x 14px(更新:它可能是 13px x 13px)
- 设置为常量:BLOCK_SIZE
- 开始循环匹配有效的图块和已编译的 QR 码块
有效是:不匹配且不是 3 个角块中的任何一个(黑色大方块)
4.1。呈现已编译的 qr 块和 1 个随机有效图块的所有可能组合,直到找到匹配
4.2 如果找到匹配(tile 可以放在已经 compiled/combined 二维码块的一侧)然后记录 match
4.3匹配条件:
没有宽度和高度符合此等式的黑色区域:
AREA_HEIGHT % BLOCK_SIZE == 0 && AREA_WIDTH % BLOCK_SIZE == 0
现在出现了一些实施并发症:
- 如何实现匹配一个瓦片到一个瓦片的算法(或者已经 compiled/combined QR 码块)?
我觉得ImageMagic可以解决。
目标是获取原始二维码
更新
正如我所见,解决方案缩小到让 ImageMagick 扫描并确定是否可以在不违反 QR 码规则的情况下将两个图块放在一起。算法应尝试并排放置 2 个图块并扫描边界区域。诀窍是测量连接瓷砖的黑色 lines/blocks 的宽度和高度。怎么做?
更新2
在某些情况下,使用 2 列宽度为 1px 的图块匹配进行比较是不够的。例如,两种算法都会将这 2 个图块连接成:
有效
和
无效
如您在 INVALID 中所见,第二个图块(右边的那个)的一部分已被删除,如红色箭头所示,但由于比较是由 1px - 算法完成的不关心这种情况。 Hance 无效二维码。
更新3
存档包含:
无效join.png
有效join.png
src1.png
src2-invalid.png
src2-valid.png
invalid.png
如果您的算法将加入 src1.png
和 src2-invalid.png
,它会失败。这是关于连接的瓷砖最终是否会产生有效的 QR。我希望你明白我的意思。
更新4
我会在测试并得到正确的解决方案后接受答案。可能需要一些时间....
更新 5:测试
Mark 的解决方案似乎一切都是正确的。
我对你的解释一无所知,但对于匹配图块来说,比较沿公共边缘的像素就足够了。这是因为拆分是跨 QR 单元格进行的,而不是在它们之间进行的。
您可以逐行填充数组,每次尝试所有未使用的块,直到找到匹配项。实际上可能会巧合地出现多个匹配项,因此建议在找到匹配项后继续搜索。这将导致递归实现。
角落和它们的直接邻居更容易手动放置。仔细观察一下,您也可以找到具有时序模式的块。
如果使用单个图块 PNG 中的所有可用信息,这很容易:
QR reader 表示:http://www.oracle.com/javaone/index.html
我花了不到 3 分钟的时间想出了解决方案——主要是因为我必须同时在 phone 上用一只手键入相应的命令....
您是如何生产瓷砖的?
更新
现在 @RCola 终于回答了我的问题 ("How did you produce the tiles?"),我将揭示我是如何快速想出正确的二维码图像的。
我没有按照他的要求使用算法。我用了"side-channel"攻击,by-passing这样的算法有什么需要考虑的。
这个 side-channel 使用了一个 "information leak",它包含在@RCola 的 ZIP 文件中提供的图块图像中。当 运行 执行一个简单的 identify
命令时,此信息会被泄露。这里我 运行 它不是作为 'simple' 命令,而是——为了使泄露的信息更明显——作为强制特定输出格式的命令:
identify -format "%f : %g\n" {1,2,3,4,5}*.png
10297-13918-3702.png : 400x400+160+0
11976-7751-26756.png : 400x400+80+0
13789-10513-4721.png : 400x400+80+160
13858-18007-13070.png : 400x400+240+0
15816-4564-31665.png : 400x400+160+240
16369-21469-8252.png : 400x400+320+80
17636-24599-1877.png : 400x400+80+240
18056-16294-30425.png : 400x400+80+320
20021-11440-20836.png : 400x400+240+320
20056-20936-29071.png : 400x400+0+240
21875-14159-1067.png : 400x400+320+240
22161-18187-20222.png : 400x400+240+80
22806-3380-17484.png : 400x400+0+160
24426-18830-5627.png : 400x400+320+160
24658-20374-23042.png : 400x400+0+0
26507-21853-11958.png : 400x400+240+240
27206-10104-18226.png : 400x400+0+320
28824-13023-24184.png : 400x400+160+80
30261-16558-25650.png : 400x400+0+80
31250-3578-9750.png : 400x400+320+0
32078-14314-1511.png : 400x400+160+160
4555-18116-29.png : 400x400+160+320
5004-10810-17642.png : 400x400+320+320
5167-27533-24066.png : 400x400+240+160
5774-30645-16062.png : 400x400+80+80
(identify {1,2,3,4,5}*.png
的输出中会包含相同的信息——只是不会跳得那么明显。)
这说明了什么? %g
percent-escape 打印 geometry 有关与 PNG tile 关联的 canvas 的信息:
400x400
是此图块 canvas 的整体大小。很明显,这是代表完整二维码的原始 PNG 的大小。
+X+Y
是在完整 canvas. 上与此图块关联的 偏移量
使用此信息可以非常容易地直接知道必须将哪个 PNG 图块放置在拼图的哪个位置:
+0+0
明显要到左上角
+0+80
显然刚好低于
+80+0
显然就在左上角的右边
- ...等等,直到
+320+320
进入右下角
OP 可以通过将 +repage
参数添加到他用来生成图块的 IM 命令来避免 side-channel 信息泄漏(在这种情况下会泄露完整的游戏)。
为了 "repair" 他提供的漏水瓷砖并制作更具挑战性的瓷砖,我这样做了:
mkdir challenge
for i in {1,2,3,4,5}*.png; do
convert $i +repage challenge/$i
done
更新 2
(作为对在十六进制编辑器的帮助下 "see" 信息失败感到绝望的评论的回答...)
与 identify
揭示的相同信息也可以在 exiftool
的帮助下获得(尽管以较少的 "accessible" 形式):
exiftool 11976-7751-26756.png | grep -E '(Virtual Image|Width|Height|Offset)'
Image Width : 80
Image Height : 80
Image Offset : 80, 0 (pixels)
Virtual Image Width : 400
Virtual Image Height : 400
我试过如下。
遍历所有 PNG 并提取它们的北边、东边、南边和西边。如果任何 PNG 有两条白边,请告诉用户它是 corner-piece。如果任何 PNG 有一条白边,请告诉用户它是 edge-piece.
遍历所有边块。将每个转换为 PBM 格式文件并去除 headers 和新行,使其成为一个 80 位长字符串,每个数字为零或一个表示黑色或白色。计算字符串的校验和,然后反转字符串以考虑翻转或旋转的图像,然后重新计算校验和。打印出校验和并通过管道输入 sort
,以便匹配的边一起出现。
代码如下:
#!/bin/bash
# Remove any edges generated in previous runs of this script
rm *_[NESW]*png 2> /dev/null
rm *_[NESW]*txt 2> /dev/null
DEBUG=1
# Process all PNGs
for f in *.png; do
echo "Processing $f ..."
# Get basename of image
base=$(basename -s .png "$f")
# Get width and height - not actually used at the moment
read w h <<< $(identify -format "%w %h" "$f")
[ $DEBUG -gt 0 ] && echo " width:$w"
[ $DEBUG -gt 0 ] && echo " height:$h"
# Extract North edge
convert "$f" +repage -crop x1+0+0 +repage "${base}_N.png"
[ $DEBUG -gt 0 ] && echo " North edge extracted"
# Extract East edge
convert "$f" +repage -gravity east -crop 1x+0+0 -rotate 90 +repage "${base}_E.png"
[ $DEBUG -gt 0 ] && echo " East edge extracted"
# Extract South edge
convert "$f" +repage -gravity south -crop x1+0+0 +repage "${base}_S.png"
[ $DEBUG -gt 0 ] && echo " South edge extracted"
# Extract West edge
convert "$f" +repage -gravity west -crop 1x+0+0 -rotate 90 +repage "${base}_W.png"
[ $DEBUG -gt 0 ] && echo " West edge extracted"
# Test if corner or edge piece
n=0
for edge in N E S W; do
name="${base}_${edge}.png"
min=$(identify -format "%[min]" "$name")
if [ $min -gt 0 ]; then
((n++))
e=$name
fi
done
[ $n -eq 1 ] && echo " $e is edge-piece"
[ $n -eq 2 ] && echo " $name is corner-piece"
done
EDITED FROM HERE ---
# Now convert all edges to text, forwards and backwards to allow rotation
for f in *_[NESW].png; do
base=$(basename -s png "$f")
# Convert to PBM format, remove 2 header lines and make into one line string
str=$(convert "$f" -compress none pbm: | sed "1,2d" | tr -d "\n ")
echo "$str:$f"
str=$(rev <<< $str)
echo "$str:$f (flipped)"
done | sort
部分输出(保存space)
Processing 4555-18116-29.png ...
width:80
height:80
North edge extracted
East edge extracted
South edge extracted
West edge extracted
4555-18116-29_S.png is edge-piece
Processing 5004-10810-17642.png ...
width:80
height:80
North edge extracted
East edge extracted
South edge extracted
West edge extracted
5004-10810-17642_W.png is corner-piece
Processing 5167-27533-24066.png ...
width:80
height:80
North edge extracted
East edge extracted
South edge extracted
West edge extracted
Processing 5774-30645-16062.png ...
width:80
height:80
North edge extracted
East edge extracted
South edge extracted
West edge extracted
0a7bb6f610c0f1a6da4794ea7ae00f00:10297-13918-3702_W.png (flipped)
0a7bb6f610c0f1a6da4794ea7ae00f00:11976-7751-26756_E.png (flipped) <-- this image is identical to the one above as the md5 checksum on the left is the same
0ce419e072c7ea5d14e3525d4afe150e:11976-7751-26756_W.png (flipped)
0ce419e072c7ea5d14e3525d4afe150e:13858-18007-13070_E.png (flipped) <-- this image is identical to the one above as the md5 checksum on the left is the same
0ce419e072c7ea5d14e3525d4afe150e:20056-20936-29071_S.png
0ce419e072c7ea5d14e3525d4afe150e:24658-20374-23042_E.png (flipped)
0ce419e072c7ea5d14e3525d4afe150e:24658-20374-23042_S.png
0ce419e072c7ea5d14e3525d4afe150e:27206-10104-18226_N.png
0ce419e072c7ea5d14e3525d4afe150e:30261-16558-25650_N.png
备注
请注意,这假设您没有在 @YvesDaoust 识别的 "fields" QR 码之间完全平铺图像。
此外,代码的某些部分是多余的,因为我在开发代码的同时开发算法 - 我认为 -rotates
和 +repages
是不必要的,事情可以优化更多,但没有表明问题需要速度。也可以在单个 IM 命令中提取北、东、南和西边缘。我获得的宽度和高度未使用,因此可以从代码中删除。
此外,md5 校验和并不是真正必要的,sort
会将 0001110001010110
放在另一个相同的字符串旁边,而无需对它们进行校验和。
应要求,我正在上传完整的解决方案。我删除了 md5 校验和的东西,因为它是不必要的。您需要向右滚动才能看到以下文件名:
00000000000000000000000000000000000000000000000000000000000000000000000000000000:10297-13918-3702_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:10297-13918-3702_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:11976-7751-26756_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:11976-7751-26756_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:13858-18007-13070_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:13858-18007-13070_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:16369-21469-8252_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:16369-21469-8252_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:18056-16294-30425_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:18056-16294-30425_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:20021-11440-20836_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:20021-11440-20836_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:20056-20936-29071_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:20056-20936-29071_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:21875-14159-1067_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:21875-14159-1067_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:22806-3380-17484_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:22806-3380-17484_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24426-18830-5627_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24426-18830-5627_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24658-20374-23042_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24658-20374-23042_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24658-20374-23042_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24658-20374-23042_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:27206-10104-18226_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:27206-10104-18226_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:27206-10104-18226_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:27206-10104-18226_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:30261-16558-25650_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:30261-16558-25650_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:31250-3578-9750_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:31250-3578-9750_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:31250-3578-9750_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:31250-3578-9750_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:4555-18116-29_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:4555-18116-29_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000111111111111100:21875-14159-1067_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000111111111111100:5004-10810-17642_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000001111111111111111111:28824-13023-24184_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000001111111111111111111:5774-30645-16062_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000011111111111111111111:13789-10513-4721_E.png
00000000000000000000000000000000000000000000000000000000000011111111111111111111:32078-14314-1511_W.png
00000000000000000000000000000000000000000000000000000001111111111111000000000000:11976-7751-26756_W.png
00000000000000000000000000000000000000000000000000000001111111111111000000000000:13858-18007-13070_E.png
00000000000000000000000000000000000000000000000000000001111111111111000000000000:20056-20936-29071_S.png (flipped)
00000000000000000000000000000000000000000000000000000001111111111111000000000000:24658-20374-23042_E.png
00000000000000000000000000000000000000000000000000000001111111111111000000000000:24658-20374-23042_S.png (flipped)
00000000000000000000000000000000000000000000000000000001111111111111000000000000:27206-10104-18226_N.png (flipped)
00000000000000000000000000000000000000000000000000000001111111111111000000000000:30261-16558-25650_N.png (flipped)
00000000000000000000000000000000000000000000000000000001111111111111000000000000:31250-3578-9750_W.png
00000000000000000000000000000000000000000000000000000011111111111110000000000000:16369-21469-8252_N.png
00000000000000000000000000000000000000000000000000000011111111111110000000000000:18056-16294-30425_W.png (flipped)
00000000000000000000000000000000000000000000000000000011111111111110000000000000:27206-10104-18226_E.png (flipped)
00000000000000000000000000000000000000000000000000000011111111111110000000000000:31250-3578-9750_S.png
00000000000000000000000000000000000000000000001111111111111111111111111111111111:10297-13918-3702_S.png
00000000000000000000000000000000000000000000001111111111111111111111111111111111:28824-13023-24184_N.png
00000000000000000000000000000000000001111111111111111111111111000000000000000000:20021-11440-20836_N.png (flipped)
00000000000000000000000000000000000001111111111111111111111111000000000000000000:26507-21853-11958_S.png (flipped)
00000000000000000000000000000000000001111111111111111111111111111111111111100000:15816-4564-31665_W.png
00000000000000000000000000000000000001111111111111111111111111111111111111100000:17636-24599-1877_E.png
00000000000000000000000000000000000001111111111111111111111111111111111111111111:21875-14159-1067_W.png
00000000000000000000000000000000000001111111111111111111111111111111111111111111:26507-21853-11958_E.png
00000000000000000000000000000000000011111111111111111111111110000000000000000000:13789-10513-4721_S.png
00000000000000000000000000000000000011111111111111111111111110000000000000000000:17636-24599-1877_N.png
00000000000000000000000000000001111111111111000000000000000000000000001111111111:22161-18187-20222_W.png
00000000000000000000000000000001111111111111000000000000000000000000001111111111:28824-13023-24184_E.png
00000000000000000000000000000011111111111111111111111111111111111111100000000000:15816-4564-31665_E.png (flipped)
00000000000000000000000000000011111111111111111111111111111111111111100000000000:26507-21853-11958_W.png (flipped)
00000000000000000000000000000111111111111111111111111111111111111111000000000000:20056-20936-29071_N.png (flipped)
00000000000000000000000000000111111111111111111111111111111111111111000000000000:22806-3380-17484_S.png (flipped)
00000000000000000000000000001111111111111111111111111111111111111110000000000000:18056-16294-30425_E.png (flipped)
00000000000000000000000000001111111111111111111111111111111111111110000000000000:4555-18116-29_W.png (flipped)
00000000000000000000000000111111111111100000000000001111111111111000000000000011:16369-21469-8252_S.png (flipped)
00000000000000000000000000111111111111100000000000001111111111111000000000000011:24426-18830-5627_N.png (flipped)
00000000000000000000000001111111111111111111111111111111111111110000000000000000:10297-13918-3702_W.png (flipped)
00000000000000000000000001111111111111111111111111111111111111110000000000000000:11976-7751-26756_E.png (flipped)
00000000000000000000000111111111111100000000000001111111111111111111111111111111:13789-10513-4721_N.png
00000000000000000000000111111111111100000000000001111111111111111111111111111111:5774-30645-16062_S.png
00000000000000000000111111111111100000000000000000000000000111111111111100000000:15816-4564-31665_N.png
00000000000000000000111111111111100000000000000000000000000111111111111100000000:32078-14314-1511_S.png
00000000000000000000111111111111100000000000001111111111111111111111111100000000:13789-10513-4721_W.png (flipped)
00000000000000000000111111111111100000000000001111111111111111111111111100000000:22806-3380-17484_E.png (flipped)
00000000000000000001111111111111111111111111000000000000000000000000000000000000:13789-10513-4721_S.png (flipped)
00000000000000000001111111111111111111111111000000000000000000000000000000000000:17636-24599-1877_N.png (flipped)
00000000000000000011111111111100000000000000000000000000111111111111111111111111:22161-18187-20222_S.png
00000000000000000011111111111100000000000000000000000000111111111111111111111111:5167-27533-24066_N.png
00000000000000000011111111111111111111111110000000000000000000000000000000000000:20021-11440-20836_N.png
00000000000000000011111111111111111111111110000000000000000000000000000000000000:26507-21853-11958_S.png
00000000000000001111111111111111111111111111111111111110000000000000000000000000:10297-13918-3702_W.png
00000000000000001111111111111111111111111111111111111110000000000000000000000000:11976-7751-26756_E.png
00000000000001111111111111000000000000000000000000000000000000000000000000000000:16369-21469-8252_N.png (flipped)
00000000000001111111111111000000000000000000000000000000000000000000000000000000:18056-16294-30425_W.png
00000000000001111111111111000000000000000000000000000000000000000000000000000000:27206-10104-18226_E.png
00000000000001111111111111000000000000000000000000000000000000000000000000000000:31250-3578-9750_S.png (flipped)
00000000000001111111111111000000000000011111111111110000000000000111111111111111:21875-14159-1067_N.png (flipped)
00000000000001111111111111000000000000011111111111110000000000000111111111111111:24426-18830-5627_S.png (flipped)
00000000000001111111111111000000000000011111111111111111111111111111111111111100:20021-11440-20836_W.png
00000000000001111111111111000000000000011111111111111111111111111111111111111100:4555-18116-29_E.png
00000000000001111111111111111111111111111111111111110000000000000000000000000000:18056-16294-30425_E.png
00000000000001111111111111111111111111111111111111110000000000000000000000000000:4555-18116-29_W.png
00000000000001111111111111111111111111111111111111111111111111111111111111111100:20021-11440-20836_E.png
00000000000001111111111111111111111111111111111111111111111111111111111111111100:5004-10810-17642_W.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:11976-7751-26756_W.png (flipped)
00000000000011111111111110000000000000000000000000000000000000000000000000000000:13858-18007-13070_E.png (flipped)
00000000000011111111111110000000000000000000000000000000000000000000000000000000:20056-20936-29071_S.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:24658-20374-23042_E.png (flipped)
00000000000011111111111110000000000000000000000000000000000000000000000000000000:24658-20374-23042_S.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:27206-10104-18226_N.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:30261-16558-25650_N.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:31250-3578-9750_W.png (flipped)
00000000000011111111111110000000000000111111111111111111111111111111111111111000:22806-3380-17484_N.png
00000000000011111111111110000000000000111111111111111111111111111111111111111000:30261-16558-25650_S.png
00000000000011111111111111111111111111000000000000011111111111111111111111111111:10297-13918-3702_E.png (flipped)
00000000000011111111111111111111111111000000000000011111111111111111111111111111:13858-18007-13070_W.png (flipped)
00000000000011111111111111111111111111111111111111100000000000000000000000000000:20056-20936-29071_N.png
00000000000011111111111111111111111111111111111111100000000000000000000000000000:22806-3380-17484_S.png
00000000000111111111111100000000000000000000000000000000000000111111111111100000:17636-24599-1877_W.png
00000000000111111111111100000000000000000000000000000000000000111111111111100000:20056-20936-29071_E.png
00000000000111111111111100000000000001111111111111000000000000111111111111111111:13858-18007-13070_S.png (flipped)
00000000000111111111111100000000000001111111111111000000000000111111111111111111:22161-18187-20222_N.png (flipped)
00000000000111111111111111111111111111111111111111000000000000000000000000000000:15816-4564-31665_E.png
00000000000111111111111111111111111111111111111111000000000000000000000000000000:26507-21853-11958_W.png
00000000001111111111111000000000000000000000000000000000000001111111111111000000:30261-16558-25650_E.png (flipped)
00000000001111111111111000000000000000000000000000000000000001111111111111000000:5774-30645-16062_W.png (flipped)
00000000001111111111111000000000000000000000000001111111111111111111111111000000:17636-24599-1877_S.png
00000000001111111111111000000000000000000000000001111111111111111111111111000000:18056-16294-30425_N.png
00000000001111111111111000000000000011111111111110000000000001111111111111000000:11976-7751-26756_S.png
00000000001111111111111000000000000011111111111110000000000001111111111111000000:5774-30645-16062_N.png
00000000001111111111111000000000000011111111111111111111111110000000000000111111:16369-21469-8252_W.png (flipped)
00000000001111111111111000000000000011111111111111111111111110000000000000111111:22161-18187-20222_E.png (flipped)
00000000111111111111100000000000000000000000000111111111111100000000000000000000:15816-4564-31665_N.png (flipped)
00000000111111111111100000000000000000000000000111111111111100000000000000000000:32078-14314-1511_S.png (flipped)
00000000111111111111100000000000000000000000000111111111111111111111111110000000:15816-4564-31665_S.png (flipped)
00000000111111111111100000000000000000000000000111111111111111111111111110000000:4555-18116-29_N.png (flipped)
00000000111111111111100000000000001111111111111000000000000011111111111110000000:32078-14314-1511_E.png
00000000111111111111100000000000001111111111111000000000000011111111111110000000:5167-27533-24066_W.png
00000000111111111111111111111111110000000000000000000000000000000000000001111111:28824-13023-24184_S.png (flipped)
00000000111111111111111111111111110000000000000000000000000000000000000001111111:32078-14314-1511_N.png (flipped)
00000000111111111111111111111111110000000000000111111111111100000000000000000000:13789-10513-4721_W.png
00000000111111111111111111111111110000000000000111111111111100000000000000000000:22806-3380-17484_E.png
00000001111111111111000000000000011111111111110000000000000111111111111100000000:32078-14314-1511_E.png (flipped)
00000001111111111111000000000000011111111111110000000000000111111111111100000000:5167-27533-24066_W.png (flipped)
00000001111111111111111111111111100000000000000000000000000111111111111100000000:15816-4564-31665_S.png
00000001111111111111111111111111100000000000000000000000000111111111111100000000:4555-18116-29_N.png
00000011111111111110000000000000000000000000000000000000011111111111110000000000:30261-16558-25650_E.png
00000011111111111110000000000000000000000000000000000000011111111111110000000000:5774-30645-16062_W.png
00000011111111111110000000000001111111111111000000000000011111111111110000000000:11976-7751-26756_S.png (flipped)
00000011111111111110000000000001111111111111000000000000011111111111110000000000:5774-30645-16062_N.png (flipped)
00000011111111111111111111111110000000000000000000000000011111111111110000000000:17636-24599-1877_S.png (flipped)
00000011111111111111111111111110000000000000000000000000011111111111110000000000:18056-16294-30425_N.png (flipped)
00000111111111111100000000000000000000000000000000000000111111111111100000000000:17636-24599-1877_W.png (flipped)
00000111111111111100000000000000000000000000000000000000111111111111100000000000:20056-20936-29071_E.png (flipped)
00000111111111111111111111111100000000000001111111111111111111111111111111111111:26507-21853-11958_N.png
00000111111111111111111111111100000000000001111111111111111111111111111111111111:5167-27533-24066_S.png
00000111111111111111111111111111111111111110000000000000000000000000000000000000:15816-4564-31665_W.png (flipped)
00000111111111111111111111111111111111111110000000000000000000000000000000000000:17636-24599-1877_E.png (flipped)
00011111111111111111111111111111111111111100000000000001111111111111000000000000:22806-3380-17484_N.png (flipped)
00011111111111111111111111111111111111111100000000000001111111111111000000000000:30261-16558-25650_S.png (flipped)
00111111111111100000000000000000000000000000000000000000000000000000000000000000:21875-14159-1067_S.png
00111111111111100000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_N.png
00111111111111111111111111111111111111111000000000000011111111111110000000000000:20021-11440-20836_W.png (flipped)
00111111111111111111111111111111111111111000000000000011111111111110000000000000:4555-18116-29_E.png (flipped)
00111111111111111111111111111111111111111111111111111111111111111110000000000000:20021-11440-20836_E.png (flipped)
00111111111111111111111111111111111111111111111111111111111111111110000000000000:5004-10810-17642_W.png (flipped)
11000000000000011111111111110000000000000111111111111100000000000000000000000000:16369-21469-8252_S.png
11000000000000011111111111110000000000000111111111111100000000000000000000000000:24426-18830-5627_N.png
11111100000000000001111111111111111111111111000000000000011111111111110000000000:16369-21469-8252_W.png
11111100000000000001111111111111111111111111000000000000011111111111110000000000:22161-18187-20222_E.png
11111110000000000000000000000000000000000000001111111111111111111111111100000000:28824-13023-24184_S.png
11111110000000000000000000000000000000000000001111111111111111111111111100000000:32078-14314-1511_N.png
11111110000000000000000000000000011111111111111111111111111111111111111111111111:24426-18830-5627_W.png (flipped)
11111110000000000000000000000000011111111111111111111111111111111111111111111111:5167-27533-24066_E.png (flipped)
11111111110000000000000000000000000011111111111110000000000000000000000000000000:22161-18187-20222_W.png (flipped)
11111111110000000000000000000000000011111111111110000000000000000000000000000000:28824-13023-24184_E.png (flipped)
11111111111111100000000000001111111111111000000000000011111111111110000000000000:21875-14159-1067_N.png
11111111111111100000000000001111111111111000000000000011111111111110000000000000:24426-18830-5627_S.png
11111111111111111100000000000011111111111110000000000000111111111111100000000000:13858-18007-13070_S.png
11111111111111111100000000000011111111111110000000000000111111111111100000000000:22161-18187-20222_N.png
11111111111111111110000000000000000000000000000000000000000000000000000000000000:28824-13023-24184_W.png
11111111111111111110000000000000000000000000000000000000000000000000000000000000:5774-30645-16062_E.png
11111111111111111111000000000000000000000000000000000000000000000000000000000000:13789-10513-4721_E.png (flipped)
11111111111111111111000000000000000000000000000000000000000000000000000000000000:32078-14314-1511_W.png (flipped)
11111111111111111111111100000000000000000000000000111111111111000000000000000000:22161-18187-20222_S.png (flipped)
11111111111111111111111100000000000000000000000000111111111111000000000000000000:5167-27533-24066_N.png (flipped)
11111111111111111111111111111000000000000011111111111111111111111111000000000000:10297-13918-3702_E.png
11111111111111111111111111111000000000000011111111111111111111111111000000000000:13858-18007-13070_W.png
11111111111111111111111111111110000000000000111111111111100000000000000000000000:13789-10513-4721_N.png (flipped)
11111111111111111111111111111110000000000000111111111111100000000000000000000000:5774-30645-16062_S.png (flipped)
11111111111111111111111111111111110000000000000000000000000000000000000000000000:10297-13918-3702_S.png (flipped)
11111111111111111111111111111111110000000000000000000000000000000000000000000000:28824-13023-24184_N.png (flipped)
11111111111111111111111111111111111110000000000000111111111111111111111111100000:26507-21853-11958_N.png (flipped)
11111111111111111111111111111111111110000000000000111111111111111111111111100000:5167-27533-24066_S.png (flipped)
11111111111111111111111111111111111111111110000000000000000000000000000000000000:21875-14159-1067_W.png (flipped)
11111111111111111111111111111111111111111110000000000000000000000000000000000000:26507-21853-11958_E.png (flipped)
11111111111111111111111111111111111111111111111000000000000000000000000001111111:24426-18830-5627_W.png
11111111111111111111111111111111111111111111111000000000000000000000000001111111:5167-27533-24066_E.png
这是一个更好的算法,我已经编写了脚本:
从每个图块中,从每个边缘切掉 1 像素的行或列,并将其输出为 ImageMagick 的特殊 *.text
格式,使用表明它们各自 left/right 的名称或 top/bottom 边原点。
转换每个这样的 column/row,创建其 *.txt
的 md5sum
并按字母顺序排序。
判断哪些MD5和相同
从相同的 MD5 和中确定适合相应边界的候选。
代码片段
for i in {1,2,3,4,5}*.png; do
convert ${i}[1x80+0+0] +repage left---edge-${i/.png/.text}
convert ${i}[1x80+79+0] +repage right--edge-${i/.png/.text}
convert ${i}[80x1+0+0] +repage top----edge-${i/.png/.text}
convert ${i}[80x1+0+79] +repage bottom-edge-${i/.png/.text}
done
一个这样的文本文件的例子是这样的:
cat right--edge-5167-27533-24066.text
# ImageMagick pixel enumeration: 1,80,255,gray
0,0: (0,0,0) #000000 gray(0)
0,1: (0,0,0) #000000 gray(0)
0,2: (0,0,0) #000000 gray(0)
0,3: (0,0,0) #000000 gray(0)
0,4: (0,0,0) #000000 gray(0)
0,5: (0,0,0) #000000 gray(0)
0,6: (0,0,0) #000000 gray(0)
0,7: (255,255,255) #FFFFFF gray(255)
0,8: (255,255,255) #FFFFFF gray(255)
0,9: (255,255,255) #FFFFFF gray(255)
0,10: (255,255,255) #FFFFFF gray(255)
0,11: (255,255,255) #FFFFFF gray(255)
0,12: (255,255,255) #FFFFFF gray(255)
0,13: (255,255,255) #FFFFFF gray(255)
0,14: (255,255,255) #FFFFFF gray(255)
0,15: (255,255,255) #FFFFFF gray(255)
0,16: (255,255,255) #FFFFFF gray(255)
0,17: (255,255,255) #FFFFFF gray(255)
0,18: (255,255,255) #FFFFFF gray(255)
0,19: (255,255,255) #FFFFFF gray(255)
0,20: (255,255,255) #FFFFFF gray(255)
0,21: (255,255,255) #FFFFFF gray(255)
0,22: (255,255,255) #FFFFFF gray(255)
0,23: (255,255,255) #FFFFFF gray(255)
0,24: (255,255,255) #FFFFFF gray(255)
0,25: (255,255,255) #FFFFFF gray(255)
0,26: (255,255,255) #FFFFFF gray(255)
0,27: (255,255,255) #FFFFFF gray(255)
0,28: (255,255,255) #FFFFFF gray(255)
0,29: (255,255,255) #FFFFFF gray(255)
0,30: (255,255,255) #FFFFFF gray(255)
0,31: (255,255,255) #FFFFFF gray(255)
0,32: (255,255,255) #FFFFFF gray(255)
0,33: (0,0,0) #000000 gray(0)
0,34: (0,0,0) #000000 gray(0)
0,35: (0,0,0) #000000 gray(0)
0,36: (0,0,0) #000000 gray(0)
0,37: (0,0,0) #000000 gray(0)
0,38: (0,0,0) #000000 gray(0)
0,39: (0,0,0) #000000 gray(0)
0,40: (0,0,0) #000000 gray(0)
0,41: (0,0,0) #000000 gray(0)
0,42: (0,0,0) #000000 gray(0)
0,43: (0,0,0) #000000 gray(0)
0,44: (0,0,0) #000000 gray(0)
0,45: (0,0,0) #000000 gray(0)
0,46: (0,0,0) #000000 gray(0)
0,47: (0,0,0) #000000 gray(0)
0,48: (0,0,0) #000000 gray(0)
0,49: (0,0,0) #000000 gray(0)
0,50: (0,0,0) #000000 gray(0)
0,51: (0,0,0) #000000 gray(0)
0,52: (0,0,0) #000000 gray(0)
0,53: (0,0,0) #000000 gray(0)
0,54: (0,0,0) #000000 gray(0)
0,55: (0,0,0) #000000 gray(0)
0,56: (0,0,0) #000000 gray(0)
0,57: (0,0,0) #000000 gray(0)
0,58: (0,0,0) #000000 gray(0)
0,59: (0,0,0) #000000 gray(0)
0,60: (0,0,0) #000000 gray(0)
0,61: (0,0,0) #000000 gray(0)
0,62: (0,0,0) #000000 gray(0)
0,63: (0,0,0) #000000 gray(0)
0,64: (0,0,0) #000000 gray(0)
0,65: (0,0,0) #000000 gray(0)
0,66: (0,0,0) #000000 gray(0)
0,67: (0,0,0) #000000 gray(0)
0,68: (0,0,0) #000000 gray(0)
0,69: (0,0,0) #000000 gray(0)
0,70: (0,0,0) #000000 gray(0)
0,71: (0,0,0) #000000 gray(0)
0,72: (0,0,0) #000000 gray(0)
0,73: (0,0,0) #000000 gray(0)
0,74: (0,0,0) #000000 gray(0)
0,75: (0,0,0) #000000 gray(0)
0,76: (0,0,0) #000000 gray(0)
0,77: (0,0,0) #000000 gray(0)
0,78: (0,0,0) #000000 gray(0)
0,79: (0,0,0) #000000 gray(0)
如您所见,它是对提取列的每个像素颜色的文本描述(其中像素坐标在每行文本的第一个字段中给出)。第一行表示使用哪种颜色space。
*按字母顺序对 MD5 和进行排序
按字母顺序对这些文本文件的 MD5 总和进行排序时,在像素颜色行和列相同的地方应该会立即显而易见:
md5sum *.text | sort
结果:
(我在某些行的末尾手动添加了一些注释。)
09c0670b59c03fb3d6f8116ee0fe35a2 bottom-edge-10297-13918-3702.text
09c0670b59c03fb3d6f8116ee0fe35a2 top----edge-28824-13023-24184.text
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-20056-20936-29071.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-22806-3380-17484.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-24658-20374-23042.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-27206-10104-18226.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-30261-16558-25650.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-16369-21469-8252.text #right edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-21875-14159-1067.text #right edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-24426-18830-5627.text #right edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-31250-3578-9750.text #right edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-5004-10810-17642.text #right edge of QR
217c799ce772d99e11b7ba2a04f42bb7 bottom-edge-11976-7751-26756.text
217c799ce772d99e11b7ba2a04f42bb7 top----edge-5774-30645-16062.text
2c96cebc6cc175b54cae54f1a27771fa bottom-edge-24426-18830-5627.text
2c96cebc6cc175b54cae54f1a27771fa top----edge-21875-14159-1067.text
3088414b0fe1190bbd4ed9315d86a0ac left---edge-13789-10513-4721.text
3088414b0fe1190bbd4ed9315d86a0ac right--edge-22806-3380-17484.text
3755d45bb6ad21b70f545f39c5550eda left---edge-17636-24599-1877.text
3755d45bb6ad21b70f545f39c5550eda right--edge-20056-20936-29071.text
41fc32b4b70622b4aff7d9e81f81daad left---edge-13858-18007-13070.text
41fc32b4b70622b4aff7d9e81f81daad right--edge-10297-13918-3702.text
480bed740a716fa10593ba061c5b6df5 left---edge-5004-10810-17642.text
480bed740a716fa10593ba061c5b6df5 right--edge-20021-11440-20836.text
55cc4713ee13ebbeb5c2e212e430da94 bottom-edge-28824-13023-24184.text
55cc4713ee13ebbeb5c2e212e430da94 top----edge-32078-14314-1511.text
62fecd6971445d4176a842727767d3f7 left---edge-4555-18116-29.text
62fecd6971445d4176a842727767d3f7 right--edge-18056-16294-30425.text
69565761226f122f98267862108119a6 left---edge-21875-14159-1067.text
69565761226f122f98267862108119a6 right--edge-26507-21853-11958.text
72cec2b0a518c2cce7204188923d9f79 left---edge-26507-21853-11958.text
72cec2b0a518c2cce7204188923d9f79 right--edge-15816-4564-31665.text
7343348f1b10e47b33e0bde47b455c2b left---edge-16369-21469-8252.text
7343348f1b10e47b33e0bde47b455c2b right--edge-22161-18187-20222.text
7661c257d28e1916208ed2a70989e42d bottom-edge-13789-10513-4721.text
7661c257d28e1916208ed2a70989e42d top----edge-17636-24599-1877.text
7d2a0d7aae6dc017ffa7af7180b1c017 left---edge-5167-27533-24066.text
7d2a0d7aae6dc017ffa7af7180b1c017 right--edge-32078-14314-1511.text
85b744d1774cd4ebe50f0cc40d10b491 left---edge-18056-16294-30425.text
85b744d1774cd4ebe50f0cc40d10b491 right--edge-27206-10104-18226.text
88942ff37ce0e884d1995a6dd11708d6 left---edge-10297-13918-3702.text
88942ff37ce0e884d1995a6dd11708d6 right--edge-11976-7751-26756.text
9185daee4fdcea482c9fa805bba40346 bottom-edge-31250-3578-9750.text
9185daee4fdcea482c9fa805bba40346 top----edge-16369-21469-8252.text
9b8a7f18e4ebbc7249e5f26ac18190a8 left---edge-28824-13023-24184.text
9b8a7f18e4ebbc7249e5f26ac18190a8 right--edge-5774-30645-16062.text
9bd8f7a474229aefd988c4231f3b26f4 bottom-edge-21875-14159-1067.text
9bd8f7a474229aefd988c4231f3b26f4 top----edge-5004-10810-17642.text
a1778c1a468c122bf408a9c2bec9135c bottom-edge-13858-18007-13070.text
a1778c1a468c122bf408a9c2bec9135c top----edge-22161-18187-20222.text
a4f3eee0e523f1b343d292987da297b3 bottom-edge-20056-20936-29071.text
a4f3eee0e523f1b343d292987da297b3 bottom-edge-24658-20374-23042.text
a4f3eee0e523f1b343d292987da297b3 top----edge-27206-10104-18226.text
a4f3eee0e523f1b343d292987da297b3 top----edge-30261-16558-25650.text
af851da184ea6d6586c64aaefdc6875b bottom-edge-22806-3380-17484.text
af851da184ea6d6586c64aaefdc6875b top----edge-20056-20936-29071.text
b4047de9fb6458ebfde5b3a11b40241a left---edge-5774-30645-16062.text
b4047de9fb6458ebfde5b3a11b40241a right--edge-30261-16558-25650.text
b58fe9214967f6d2311e11cb0bf1acc4 left---edge-15816-4564-31665.text
b58fe9214967f6d2311e11cb0bf1acc4 right--edge-17636-24599-1877.text
bef4d7004da4f5de4ca5beeabc1222e8 bottom-edge-5774-30645-16062.text
bef4d7004da4f5de4ca5beeabc1222e8 top----edge-13789-10513-4721.text
c042d1cd3dfb339177e8da3c2907d58e bottom-edge-15816-4564-31665.text
c042d1cd3dfb339177e8da3c2907d58e top----edge-4555-18116-29.text
c5f38ebda77190495d77df1fb7002d1e bottom-edge-32078-14314-1511.text
c5f38ebda77190495d77df1fb7002d1e top----edge-15816-4564-31665.text
c61f738453fa3a86b52b2de5c0d43530 left---edge-20021-11440-20836.text
c61f738453fa3a86b52b2de5c0d43530 right--edge-4555-18116-29.text
c772762652d22cbf228e57f0dcf1a3b4 bottom-edge-22161-18187-20222.text
c772762652d22cbf228e57f0dcf1a3b4 top----edge-5167-27533-24066.text
cfaa399406e0be3d07297f23c684e7c3 left---edge-11976-7751-26756.text
cfaa399406e0be3d07297f23c684e7c3 left---edge-31250-3578-9750.text
cfaa399406e0be3d07297f23c684e7c3 right--edge-13858-18007-13070.text
cfaa399406e0be3d07297f23c684e7c3 right--edge-24658-20374-23042.text
d39c2a0c14c20b66b441d368c164171d bottom-edge-18056-16294-30425.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d bottom-edge-20021-11440-20836.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d bottom-edge-27206-10104-18226.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d bottom-edge-4555-18116-29.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d bottom-edge-5004-10810-17642.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-10297-13918-3702.text #top edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-11976-7751-26756.text #top edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-13858-18007-13070.text #top edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-24658-20374-23042.text #top edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-31250-3578-9750.text #top edge of QR
d71e7b561d2cc251c962a843daff53bb bottom-edge-5167-27533-24066.text
d71e7b561d2cc251c962a843daff53bb top----edge-26507-21853-11958.text
d7ffe4aaf744387e7fa9db32271247e0 bottom-edge-26507-21853-11958.text
d7ffe4aaf744387e7fa9db32271247e0 top----edge-20021-11440-20836.text
da2aa01201b3da20a970928bc2bdef36 bottom-edge-30261-16558-25650.text
da2aa01201b3da20a970928bc2bdef36 top----edge-22806-3380-17484.text
dd86f02cfc0e260463c75ae5b8709f33 bottom-edge-16369-21469-8252.text
dd86f02cfc0e260463c75ae5b8709f33 top----edge-24426-18830-5627.text
dfdaa88ebf33284ac0367f92060cd060 bottom-edge-17636-24599-1877.text
dfdaa88ebf33284ac0367f92060cd060 top----edge-18056-16294-30425.text
f8e2f384f2269e086dc00fb6ff0b3f41 left---edge-32078-14314-1511.text
f8e2f384f2269e086dc00fb6ff0b3f41 right--edge-13789-10513-4721.text
fa59372704f3b48912a33f3780e9dce7 left---edge-22161-18187-20222.text
fa59372704f3b48912a33f3780e9dce7 right--edge-28824-13023-24184.text
fff7e26c6f9852fcfa51e79d154dc58a left---edge-24426-18830-5627.text
fff7e26c6f9852fcfa51e79d154dc58a right--edge-5167-27533-24066.text
可以立即识别出以下模式:
- 10 个相同的 MD5 和
d39c2a0c14c20b66b441d368c164171d
- 10 个相同的 MD5 和
10be914aa8b6aaa8c0e35a4a93421f3a
- left/right 边
的 20 对相同的 MD5 和
- top/bottom 边
的 20 对相同的 MD5 和
在“1”的情况下。和“2”。很容易看出这些都是全白边,代表 left/right/top/bottom 条完整的 QR。
剩下的比赛,'3'。和“4”。可以很容易地以确定的方式将每个单独的图块调整到左侧或右侧 "partner"。
更新
直到现在我才看到马克的回答。但是我看他的方法和我的差不多。
虽然我不愿意添加我的完整脚本来生成最终重新组合的二维码。
所以如果 Mark 的解决方案包括这个,他应该得到正确答案的批准。
我正在构建算法以根据相同大小的块数自动解决/重建 QR 码。
我的做法:
- 获得 3 个边方块之一:位置方块
- 使用 ImageMagic 以某种方式获取外黑色边框的宽度
给定的示例是 14px x 14px(更新:它可能是 13px x 13px)
- 设置为常量:BLOCK_SIZE
- 开始循环匹配有效的图块和已编译的 QR 码块
有效是:不匹配且不是 3 个角块中的任何一个(黑色大方块)
4.1。呈现已编译的 qr 块和 1 个随机有效图块的所有可能组合,直到找到匹配
4.2 如果找到匹配(tile 可以放在已经 compiled/combined 二维码块的一侧)然后记录 match
4.3匹配条件:
没有宽度和高度符合此等式的黑色区域:
AREA_HEIGHT % BLOCK_SIZE == 0 && AREA_WIDTH % BLOCK_SIZE == 0
现在出现了一些实施并发症:
- 如何实现匹配一个瓦片到一个瓦片的算法(或者已经 compiled/combined QR 码块)?
我觉得ImageMagic可以解决。 目标是获取原始二维码
更新
正如我所见,解决方案缩小到让 ImageMagick 扫描并确定是否可以在不违反 QR 码规则的情况下将两个图块放在一起。算法应尝试并排放置 2 个图块并扫描边界区域。诀窍是测量连接瓷砖的黑色 lines/blocks 的宽度和高度。怎么做?
更新2
在某些情况下,使用 2 列宽度为 1px 的图块匹配进行比较是不够的。例如,两种算法都会将这 2 个图块连接成:
有效
和
无效
如您在 INVALID 中所见,第二个图块(右边的那个)的一部分已被删除,如红色箭头所示,但由于比较是由 1px - 算法完成的不关心这种情况。 Hance 无效二维码。
更新3
存档包含:
无效join.png
有效join.png
src1.png
src2-invalid.png
src2-valid.png
invalid.png
如果您的算法将加入 src1.png
和 src2-invalid.png
,它会失败。这是关于连接的瓷砖最终是否会产生有效的 QR。我希望你明白我的意思。
更新4
我会在测试并得到正确的解决方案后接受答案。可能需要一些时间....
更新 5:测试
Mark 的解决方案似乎一切都是正确的。
我对你的解释一无所知,但对于匹配图块来说,比较沿公共边缘的像素就足够了。这是因为拆分是跨 QR 单元格进行的,而不是在它们之间进行的。
您可以逐行填充数组,每次尝试所有未使用的块,直到找到匹配项。实际上可能会巧合地出现多个匹配项,因此建议在找到匹配项后继续搜索。这将导致递归实现。
角落和它们的直接邻居更容易手动放置。仔细观察一下,您也可以找到具有时序模式的块。
如果使用单个图块 PNG 中的所有可用信息,这很容易:
QR reader 表示:http://www.oracle.com/javaone/index.html
我花了不到 3 分钟的时间想出了解决方案——主要是因为我必须同时在 phone 上用一只手键入相应的命令....
您是如何生产瓷砖的?
更新
现在 @RCola 终于回答了我的问题 ("How did you produce the tiles?"),我将揭示我是如何快速想出正确的二维码图像的。
我没有按照他的要求使用算法。我用了"side-channel"攻击,by-passing这样的算法有什么需要考虑的。
这个 side-channel 使用了一个 "information leak",它包含在@RCola 的 ZIP 文件中提供的图块图像中。当 运行 执行一个简单的 identify
命令时,此信息会被泄露。这里我 运行 它不是作为 'simple' 命令,而是——为了使泄露的信息更明显——作为强制特定输出格式的命令:
identify -format "%f : %g\n" {1,2,3,4,5}*.png
10297-13918-3702.png : 400x400+160+0
11976-7751-26756.png : 400x400+80+0
13789-10513-4721.png : 400x400+80+160
13858-18007-13070.png : 400x400+240+0
15816-4564-31665.png : 400x400+160+240
16369-21469-8252.png : 400x400+320+80
17636-24599-1877.png : 400x400+80+240
18056-16294-30425.png : 400x400+80+320
20021-11440-20836.png : 400x400+240+320
20056-20936-29071.png : 400x400+0+240
21875-14159-1067.png : 400x400+320+240
22161-18187-20222.png : 400x400+240+80
22806-3380-17484.png : 400x400+0+160
24426-18830-5627.png : 400x400+320+160
24658-20374-23042.png : 400x400+0+0
26507-21853-11958.png : 400x400+240+240
27206-10104-18226.png : 400x400+0+320
28824-13023-24184.png : 400x400+160+80
30261-16558-25650.png : 400x400+0+80
31250-3578-9750.png : 400x400+320+0
32078-14314-1511.png : 400x400+160+160
4555-18116-29.png : 400x400+160+320
5004-10810-17642.png : 400x400+320+320
5167-27533-24066.png : 400x400+240+160
5774-30645-16062.png : 400x400+80+80
(identify {1,2,3,4,5}*.png
的输出中会包含相同的信息——只是不会跳得那么明显。)
这说明了什么? %g
percent-escape 打印 geometry 有关与 PNG tile 关联的 canvas 的信息:
400x400
是此图块 canvas 的整体大小。很明显,这是代表完整二维码的原始 PNG 的大小。+X+Y
是在完整 canvas. 上与此图块关联的 偏移量
使用此信息可以非常容易地直接知道必须将哪个 PNG 图块放置在拼图的哪个位置:
+0+0
明显要到左上角+0+80
显然刚好低于+80+0
显然就在左上角的右边- ...等等,直到
+320+320
进入右下角
OP 可以通过将 +repage
参数添加到他用来生成图块的 IM 命令来避免 side-channel 信息泄漏(在这种情况下会泄露完整的游戏)。
为了 "repair" 他提供的漏水瓷砖并制作更具挑战性的瓷砖,我这样做了:
mkdir challenge
for i in {1,2,3,4,5}*.png; do
convert $i +repage challenge/$i
done
更新 2
(作为对在十六进制编辑器的帮助下 "see" 信息失败感到绝望的评论的回答...)
与 identify
揭示的相同信息也可以在 exiftool
的帮助下获得(尽管以较少的 "accessible" 形式):
exiftool 11976-7751-26756.png | grep -E '(Virtual Image|Width|Height|Offset)'
Image Width : 80
Image Height : 80
Image Offset : 80, 0 (pixels)
Virtual Image Width : 400
Virtual Image Height : 400
我试过如下。
遍历所有 PNG 并提取它们的北边、东边、南边和西边。如果任何 PNG 有两条白边,请告诉用户它是 corner-piece。如果任何 PNG 有一条白边,请告诉用户它是 edge-piece.
遍历所有边块。将每个转换为 PBM 格式文件并去除 headers 和新行,使其成为一个 80 位长字符串,每个数字为零或一个表示黑色或白色。计算字符串的校验和,然后反转字符串以考虑翻转或旋转的图像,然后重新计算校验和。打印出校验和并通过管道输入
sort
,以便匹配的边一起出现。
代码如下:
#!/bin/bash
# Remove any edges generated in previous runs of this script
rm *_[NESW]*png 2> /dev/null
rm *_[NESW]*txt 2> /dev/null
DEBUG=1
# Process all PNGs
for f in *.png; do
echo "Processing $f ..."
# Get basename of image
base=$(basename -s .png "$f")
# Get width and height - not actually used at the moment
read w h <<< $(identify -format "%w %h" "$f")
[ $DEBUG -gt 0 ] && echo " width:$w"
[ $DEBUG -gt 0 ] && echo " height:$h"
# Extract North edge
convert "$f" +repage -crop x1+0+0 +repage "${base}_N.png"
[ $DEBUG -gt 0 ] && echo " North edge extracted"
# Extract East edge
convert "$f" +repage -gravity east -crop 1x+0+0 -rotate 90 +repage "${base}_E.png"
[ $DEBUG -gt 0 ] && echo " East edge extracted"
# Extract South edge
convert "$f" +repage -gravity south -crop x1+0+0 +repage "${base}_S.png"
[ $DEBUG -gt 0 ] && echo " South edge extracted"
# Extract West edge
convert "$f" +repage -gravity west -crop 1x+0+0 -rotate 90 +repage "${base}_W.png"
[ $DEBUG -gt 0 ] && echo " West edge extracted"
# Test if corner or edge piece
n=0
for edge in N E S W; do
name="${base}_${edge}.png"
min=$(identify -format "%[min]" "$name")
if [ $min -gt 0 ]; then
((n++))
e=$name
fi
done
[ $n -eq 1 ] && echo " $e is edge-piece"
[ $n -eq 2 ] && echo " $name is corner-piece"
done
EDITED FROM HERE ---
# Now convert all edges to text, forwards and backwards to allow rotation
for f in *_[NESW].png; do
base=$(basename -s png "$f")
# Convert to PBM format, remove 2 header lines and make into one line string
str=$(convert "$f" -compress none pbm: | sed "1,2d" | tr -d "\n ")
echo "$str:$f"
str=$(rev <<< $str)
echo "$str:$f (flipped)"
done | sort
部分输出(保存space)
Processing 4555-18116-29.png ...
width:80
height:80
North edge extracted
East edge extracted
South edge extracted
West edge extracted
4555-18116-29_S.png is edge-piece
Processing 5004-10810-17642.png ...
width:80
height:80
North edge extracted
East edge extracted
South edge extracted
West edge extracted
5004-10810-17642_W.png is corner-piece
Processing 5167-27533-24066.png ...
width:80
height:80
North edge extracted
East edge extracted
South edge extracted
West edge extracted
Processing 5774-30645-16062.png ...
width:80
height:80
North edge extracted
East edge extracted
South edge extracted
West edge extracted
0a7bb6f610c0f1a6da4794ea7ae00f00:10297-13918-3702_W.png (flipped)
0a7bb6f610c0f1a6da4794ea7ae00f00:11976-7751-26756_E.png (flipped) <-- this image is identical to the one above as the md5 checksum on the left is the same
0ce419e072c7ea5d14e3525d4afe150e:11976-7751-26756_W.png (flipped)
0ce419e072c7ea5d14e3525d4afe150e:13858-18007-13070_E.png (flipped) <-- this image is identical to the one above as the md5 checksum on the left is the same
0ce419e072c7ea5d14e3525d4afe150e:20056-20936-29071_S.png
0ce419e072c7ea5d14e3525d4afe150e:24658-20374-23042_E.png (flipped)
0ce419e072c7ea5d14e3525d4afe150e:24658-20374-23042_S.png
0ce419e072c7ea5d14e3525d4afe150e:27206-10104-18226_N.png
0ce419e072c7ea5d14e3525d4afe150e:30261-16558-25650_N.png
备注
请注意,这假设您没有在 @YvesDaoust 识别的 "fields" QR 码之间完全平铺图像。
此外,代码的某些部分是多余的,因为我在开发代码的同时开发算法 - 我认为 -rotates
和 +repages
是不必要的,事情可以优化更多,但没有表明问题需要速度。也可以在单个 IM 命令中提取北、东、南和西边缘。我获得的宽度和高度未使用,因此可以从代码中删除。
此外,md5 校验和并不是真正必要的,sort
会将 0001110001010110
放在另一个相同的字符串旁边,而无需对它们进行校验和。
应要求,我正在上传完整的解决方案。我删除了 md5 校验和的东西,因为它是不必要的。您需要向右滚动才能看到以下文件名:
00000000000000000000000000000000000000000000000000000000000000000000000000000000:10297-13918-3702_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:10297-13918-3702_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:11976-7751-26756_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:11976-7751-26756_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:13858-18007-13070_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:13858-18007-13070_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:16369-21469-8252_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:16369-21469-8252_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:18056-16294-30425_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:18056-16294-30425_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:20021-11440-20836_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:20021-11440-20836_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:20056-20936-29071_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:20056-20936-29071_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:21875-14159-1067_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:21875-14159-1067_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:22806-3380-17484_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:22806-3380-17484_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24426-18830-5627_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24426-18830-5627_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24658-20374-23042_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24658-20374-23042_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24658-20374-23042_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:24658-20374-23042_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:27206-10104-18226_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:27206-10104-18226_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:27206-10104-18226_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:27206-10104-18226_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:30261-16558-25650_W.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:30261-16558-25650_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:31250-3578-9750_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:31250-3578-9750_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:31250-3578-9750_N.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:31250-3578-9750_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:4555-18116-29_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:4555-18116-29_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_E.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_S.png
00000000000000000000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000111111111111100:21875-14159-1067_S.png (flipped)
00000000000000000000000000000000000000000000000000000000000000000111111111111100:5004-10810-17642_N.png (flipped)
00000000000000000000000000000000000000000000000000000000000001111111111111111111:28824-13023-24184_W.png (flipped)
00000000000000000000000000000000000000000000000000000000000001111111111111111111:5774-30645-16062_E.png (flipped)
00000000000000000000000000000000000000000000000000000000000011111111111111111111:13789-10513-4721_E.png
00000000000000000000000000000000000000000000000000000000000011111111111111111111:32078-14314-1511_W.png
00000000000000000000000000000000000000000000000000000001111111111111000000000000:11976-7751-26756_W.png
00000000000000000000000000000000000000000000000000000001111111111111000000000000:13858-18007-13070_E.png
00000000000000000000000000000000000000000000000000000001111111111111000000000000:20056-20936-29071_S.png (flipped)
00000000000000000000000000000000000000000000000000000001111111111111000000000000:24658-20374-23042_E.png
00000000000000000000000000000000000000000000000000000001111111111111000000000000:24658-20374-23042_S.png (flipped)
00000000000000000000000000000000000000000000000000000001111111111111000000000000:27206-10104-18226_N.png (flipped)
00000000000000000000000000000000000000000000000000000001111111111111000000000000:30261-16558-25650_N.png (flipped)
00000000000000000000000000000000000000000000000000000001111111111111000000000000:31250-3578-9750_W.png
00000000000000000000000000000000000000000000000000000011111111111110000000000000:16369-21469-8252_N.png
00000000000000000000000000000000000000000000000000000011111111111110000000000000:18056-16294-30425_W.png (flipped)
00000000000000000000000000000000000000000000000000000011111111111110000000000000:27206-10104-18226_E.png (flipped)
00000000000000000000000000000000000000000000000000000011111111111110000000000000:31250-3578-9750_S.png
00000000000000000000000000000000000000000000001111111111111111111111111111111111:10297-13918-3702_S.png
00000000000000000000000000000000000000000000001111111111111111111111111111111111:28824-13023-24184_N.png
00000000000000000000000000000000000001111111111111111111111111000000000000000000:20021-11440-20836_N.png (flipped)
00000000000000000000000000000000000001111111111111111111111111000000000000000000:26507-21853-11958_S.png (flipped)
00000000000000000000000000000000000001111111111111111111111111111111111111100000:15816-4564-31665_W.png
00000000000000000000000000000000000001111111111111111111111111111111111111100000:17636-24599-1877_E.png
00000000000000000000000000000000000001111111111111111111111111111111111111111111:21875-14159-1067_W.png
00000000000000000000000000000000000001111111111111111111111111111111111111111111:26507-21853-11958_E.png
00000000000000000000000000000000000011111111111111111111111110000000000000000000:13789-10513-4721_S.png
00000000000000000000000000000000000011111111111111111111111110000000000000000000:17636-24599-1877_N.png
00000000000000000000000000000001111111111111000000000000000000000000001111111111:22161-18187-20222_W.png
00000000000000000000000000000001111111111111000000000000000000000000001111111111:28824-13023-24184_E.png
00000000000000000000000000000011111111111111111111111111111111111111100000000000:15816-4564-31665_E.png (flipped)
00000000000000000000000000000011111111111111111111111111111111111111100000000000:26507-21853-11958_W.png (flipped)
00000000000000000000000000000111111111111111111111111111111111111111000000000000:20056-20936-29071_N.png (flipped)
00000000000000000000000000000111111111111111111111111111111111111111000000000000:22806-3380-17484_S.png (flipped)
00000000000000000000000000001111111111111111111111111111111111111110000000000000:18056-16294-30425_E.png (flipped)
00000000000000000000000000001111111111111111111111111111111111111110000000000000:4555-18116-29_W.png (flipped)
00000000000000000000000000111111111111100000000000001111111111111000000000000011:16369-21469-8252_S.png (flipped)
00000000000000000000000000111111111111100000000000001111111111111000000000000011:24426-18830-5627_N.png (flipped)
00000000000000000000000001111111111111111111111111111111111111110000000000000000:10297-13918-3702_W.png (flipped)
00000000000000000000000001111111111111111111111111111111111111110000000000000000:11976-7751-26756_E.png (flipped)
00000000000000000000000111111111111100000000000001111111111111111111111111111111:13789-10513-4721_N.png
00000000000000000000000111111111111100000000000001111111111111111111111111111111:5774-30645-16062_S.png
00000000000000000000111111111111100000000000000000000000000111111111111100000000:15816-4564-31665_N.png
00000000000000000000111111111111100000000000000000000000000111111111111100000000:32078-14314-1511_S.png
00000000000000000000111111111111100000000000001111111111111111111111111100000000:13789-10513-4721_W.png (flipped)
00000000000000000000111111111111100000000000001111111111111111111111111100000000:22806-3380-17484_E.png (flipped)
00000000000000000001111111111111111111111111000000000000000000000000000000000000:13789-10513-4721_S.png (flipped)
00000000000000000001111111111111111111111111000000000000000000000000000000000000:17636-24599-1877_N.png (flipped)
00000000000000000011111111111100000000000000000000000000111111111111111111111111:22161-18187-20222_S.png
00000000000000000011111111111100000000000000000000000000111111111111111111111111:5167-27533-24066_N.png
00000000000000000011111111111111111111111110000000000000000000000000000000000000:20021-11440-20836_N.png
00000000000000000011111111111111111111111110000000000000000000000000000000000000:26507-21853-11958_S.png
00000000000000001111111111111111111111111111111111111110000000000000000000000000:10297-13918-3702_W.png
00000000000000001111111111111111111111111111111111111110000000000000000000000000:11976-7751-26756_E.png
00000000000001111111111111000000000000000000000000000000000000000000000000000000:16369-21469-8252_N.png (flipped)
00000000000001111111111111000000000000000000000000000000000000000000000000000000:18056-16294-30425_W.png
00000000000001111111111111000000000000000000000000000000000000000000000000000000:27206-10104-18226_E.png
00000000000001111111111111000000000000000000000000000000000000000000000000000000:31250-3578-9750_S.png (flipped)
00000000000001111111111111000000000000011111111111110000000000000111111111111111:21875-14159-1067_N.png (flipped)
00000000000001111111111111000000000000011111111111110000000000000111111111111111:24426-18830-5627_S.png (flipped)
00000000000001111111111111000000000000011111111111111111111111111111111111111100:20021-11440-20836_W.png
00000000000001111111111111000000000000011111111111111111111111111111111111111100:4555-18116-29_E.png
00000000000001111111111111111111111111111111111111110000000000000000000000000000:18056-16294-30425_E.png
00000000000001111111111111111111111111111111111111110000000000000000000000000000:4555-18116-29_W.png
00000000000001111111111111111111111111111111111111111111111111111111111111111100:20021-11440-20836_E.png
00000000000001111111111111111111111111111111111111111111111111111111111111111100:5004-10810-17642_W.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:11976-7751-26756_W.png (flipped)
00000000000011111111111110000000000000000000000000000000000000000000000000000000:13858-18007-13070_E.png (flipped)
00000000000011111111111110000000000000000000000000000000000000000000000000000000:20056-20936-29071_S.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:24658-20374-23042_E.png (flipped)
00000000000011111111111110000000000000000000000000000000000000000000000000000000:24658-20374-23042_S.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:27206-10104-18226_N.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:30261-16558-25650_N.png
00000000000011111111111110000000000000000000000000000000000000000000000000000000:31250-3578-9750_W.png (flipped)
00000000000011111111111110000000000000111111111111111111111111111111111111111000:22806-3380-17484_N.png
00000000000011111111111110000000000000111111111111111111111111111111111111111000:30261-16558-25650_S.png
00000000000011111111111111111111111111000000000000011111111111111111111111111111:10297-13918-3702_E.png (flipped)
00000000000011111111111111111111111111000000000000011111111111111111111111111111:13858-18007-13070_W.png (flipped)
00000000000011111111111111111111111111111111111111100000000000000000000000000000:20056-20936-29071_N.png
00000000000011111111111111111111111111111111111111100000000000000000000000000000:22806-3380-17484_S.png
00000000000111111111111100000000000000000000000000000000000000111111111111100000:17636-24599-1877_W.png
00000000000111111111111100000000000000000000000000000000000000111111111111100000:20056-20936-29071_E.png
00000000000111111111111100000000000001111111111111000000000000111111111111111111:13858-18007-13070_S.png (flipped)
00000000000111111111111100000000000001111111111111000000000000111111111111111111:22161-18187-20222_N.png (flipped)
00000000000111111111111111111111111111111111111111000000000000000000000000000000:15816-4564-31665_E.png
00000000000111111111111111111111111111111111111111000000000000000000000000000000:26507-21853-11958_W.png
00000000001111111111111000000000000000000000000000000000000001111111111111000000:30261-16558-25650_E.png (flipped)
00000000001111111111111000000000000000000000000000000000000001111111111111000000:5774-30645-16062_W.png (flipped)
00000000001111111111111000000000000000000000000001111111111111111111111111000000:17636-24599-1877_S.png
00000000001111111111111000000000000000000000000001111111111111111111111111000000:18056-16294-30425_N.png
00000000001111111111111000000000000011111111111110000000000001111111111111000000:11976-7751-26756_S.png
00000000001111111111111000000000000011111111111110000000000001111111111111000000:5774-30645-16062_N.png
00000000001111111111111000000000000011111111111111111111111110000000000000111111:16369-21469-8252_W.png (flipped)
00000000001111111111111000000000000011111111111111111111111110000000000000111111:22161-18187-20222_E.png (flipped)
00000000111111111111100000000000000000000000000111111111111100000000000000000000:15816-4564-31665_N.png (flipped)
00000000111111111111100000000000000000000000000111111111111100000000000000000000:32078-14314-1511_S.png (flipped)
00000000111111111111100000000000000000000000000111111111111111111111111110000000:15816-4564-31665_S.png (flipped)
00000000111111111111100000000000000000000000000111111111111111111111111110000000:4555-18116-29_N.png (flipped)
00000000111111111111100000000000001111111111111000000000000011111111111110000000:32078-14314-1511_E.png
00000000111111111111100000000000001111111111111000000000000011111111111110000000:5167-27533-24066_W.png
00000000111111111111111111111111110000000000000000000000000000000000000001111111:28824-13023-24184_S.png (flipped)
00000000111111111111111111111111110000000000000000000000000000000000000001111111:32078-14314-1511_N.png (flipped)
00000000111111111111111111111111110000000000000111111111111100000000000000000000:13789-10513-4721_W.png
00000000111111111111111111111111110000000000000111111111111100000000000000000000:22806-3380-17484_E.png
00000001111111111111000000000000011111111111110000000000000111111111111100000000:32078-14314-1511_E.png (flipped)
00000001111111111111000000000000011111111111110000000000000111111111111100000000:5167-27533-24066_W.png (flipped)
00000001111111111111111111111111100000000000000000000000000111111111111100000000:15816-4564-31665_S.png
00000001111111111111111111111111100000000000000000000000000111111111111100000000:4555-18116-29_N.png
00000011111111111110000000000000000000000000000000000000011111111111110000000000:30261-16558-25650_E.png
00000011111111111110000000000000000000000000000000000000011111111111110000000000:5774-30645-16062_W.png
00000011111111111110000000000001111111111111000000000000011111111111110000000000:11976-7751-26756_S.png (flipped)
00000011111111111110000000000001111111111111000000000000011111111111110000000000:5774-30645-16062_N.png (flipped)
00000011111111111111111111111110000000000000000000000000011111111111110000000000:17636-24599-1877_S.png (flipped)
00000011111111111111111111111110000000000000000000000000011111111111110000000000:18056-16294-30425_N.png (flipped)
00000111111111111100000000000000000000000000000000000000111111111111100000000000:17636-24599-1877_W.png (flipped)
00000111111111111100000000000000000000000000000000000000111111111111100000000000:20056-20936-29071_E.png (flipped)
00000111111111111111111111111100000000000001111111111111111111111111111111111111:26507-21853-11958_N.png
00000111111111111111111111111100000000000001111111111111111111111111111111111111:5167-27533-24066_S.png
00000111111111111111111111111111111111111110000000000000000000000000000000000000:15816-4564-31665_W.png (flipped)
00000111111111111111111111111111111111111110000000000000000000000000000000000000:17636-24599-1877_E.png (flipped)
00011111111111111111111111111111111111111100000000000001111111111111000000000000:22806-3380-17484_N.png (flipped)
00011111111111111111111111111111111111111100000000000001111111111111000000000000:30261-16558-25650_S.png (flipped)
00111111111111100000000000000000000000000000000000000000000000000000000000000000:21875-14159-1067_S.png
00111111111111100000000000000000000000000000000000000000000000000000000000000000:5004-10810-17642_N.png
00111111111111111111111111111111111111111000000000000011111111111110000000000000:20021-11440-20836_W.png (flipped)
00111111111111111111111111111111111111111000000000000011111111111110000000000000:4555-18116-29_E.png (flipped)
00111111111111111111111111111111111111111111111111111111111111111110000000000000:20021-11440-20836_E.png (flipped)
00111111111111111111111111111111111111111111111111111111111111111110000000000000:5004-10810-17642_W.png (flipped)
11000000000000011111111111110000000000000111111111111100000000000000000000000000:16369-21469-8252_S.png
11000000000000011111111111110000000000000111111111111100000000000000000000000000:24426-18830-5627_N.png
11111100000000000001111111111111111111111111000000000000011111111111110000000000:16369-21469-8252_W.png
11111100000000000001111111111111111111111111000000000000011111111111110000000000:22161-18187-20222_E.png
11111110000000000000000000000000000000000000001111111111111111111111111100000000:28824-13023-24184_S.png
11111110000000000000000000000000000000000000001111111111111111111111111100000000:32078-14314-1511_N.png
11111110000000000000000000000000011111111111111111111111111111111111111111111111:24426-18830-5627_W.png (flipped)
11111110000000000000000000000000011111111111111111111111111111111111111111111111:5167-27533-24066_E.png (flipped)
11111111110000000000000000000000000011111111111110000000000000000000000000000000:22161-18187-20222_W.png (flipped)
11111111110000000000000000000000000011111111111110000000000000000000000000000000:28824-13023-24184_E.png (flipped)
11111111111111100000000000001111111111111000000000000011111111111110000000000000:21875-14159-1067_N.png
11111111111111100000000000001111111111111000000000000011111111111110000000000000:24426-18830-5627_S.png
11111111111111111100000000000011111111111110000000000000111111111111100000000000:13858-18007-13070_S.png
11111111111111111100000000000011111111111110000000000000111111111111100000000000:22161-18187-20222_N.png
11111111111111111110000000000000000000000000000000000000000000000000000000000000:28824-13023-24184_W.png
11111111111111111110000000000000000000000000000000000000000000000000000000000000:5774-30645-16062_E.png
11111111111111111111000000000000000000000000000000000000000000000000000000000000:13789-10513-4721_E.png (flipped)
11111111111111111111000000000000000000000000000000000000000000000000000000000000:32078-14314-1511_W.png (flipped)
11111111111111111111111100000000000000000000000000111111111111000000000000000000:22161-18187-20222_S.png (flipped)
11111111111111111111111100000000000000000000000000111111111111000000000000000000:5167-27533-24066_N.png (flipped)
11111111111111111111111111111000000000000011111111111111111111111111000000000000:10297-13918-3702_E.png
11111111111111111111111111111000000000000011111111111111111111111111000000000000:13858-18007-13070_W.png
11111111111111111111111111111110000000000000111111111111100000000000000000000000:13789-10513-4721_N.png (flipped)
11111111111111111111111111111110000000000000111111111111100000000000000000000000:5774-30645-16062_S.png (flipped)
11111111111111111111111111111111110000000000000000000000000000000000000000000000:10297-13918-3702_S.png (flipped)
11111111111111111111111111111111110000000000000000000000000000000000000000000000:28824-13023-24184_N.png (flipped)
11111111111111111111111111111111111110000000000000111111111111111111111111100000:26507-21853-11958_N.png (flipped)
11111111111111111111111111111111111110000000000000111111111111111111111111100000:5167-27533-24066_S.png (flipped)
11111111111111111111111111111111111111111110000000000000000000000000000000000000:21875-14159-1067_W.png (flipped)
11111111111111111111111111111111111111111110000000000000000000000000000000000000:26507-21853-11958_E.png (flipped)
11111111111111111111111111111111111111111111111000000000000000000000000001111111:24426-18830-5627_W.png
11111111111111111111111111111111111111111111111000000000000000000000000001111111:5167-27533-24066_E.png
这是一个更好的算法,我已经编写了脚本:
从每个图块中,从每个边缘切掉 1 像素的行或列,并将其输出为 ImageMagick 的特殊
*.text
格式,使用表明它们各自 left/right 的名称或 top/bottom 边原点。转换每个这样的 column/row,创建其
*.txt
的md5sum
并按字母顺序排序。判断哪些MD5和相同
从相同的 MD5 和中确定适合相应边界的候选。
代码片段
for i in {1,2,3,4,5}*.png; do
convert ${i}[1x80+0+0] +repage left---edge-${i/.png/.text}
convert ${i}[1x80+79+0] +repage right--edge-${i/.png/.text}
convert ${i}[80x1+0+0] +repage top----edge-${i/.png/.text}
convert ${i}[80x1+0+79] +repage bottom-edge-${i/.png/.text}
done
一个这样的文本文件的例子是这样的:
cat right--edge-5167-27533-24066.text
# ImageMagick pixel enumeration: 1,80,255,gray
0,0: (0,0,0) #000000 gray(0)
0,1: (0,0,0) #000000 gray(0)
0,2: (0,0,0) #000000 gray(0)
0,3: (0,0,0) #000000 gray(0)
0,4: (0,0,0) #000000 gray(0)
0,5: (0,0,0) #000000 gray(0)
0,6: (0,0,0) #000000 gray(0)
0,7: (255,255,255) #FFFFFF gray(255)
0,8: (255,255,255) #FFFFFF gray(255)
0,9: (255,255,255) #FFFFFF gray(255)
0,10: (255,255,255) #FFFFFF gray(255)
0,11: (255,255,255) #FFFFFF gray(255)
0,12: (255,255,255) #FFFFFF gray(255)
0,13: (255,255,255) #FFFFFF gray(255)
0,14: (255,255,255) #FFFFFF gray(255)
0,15: (255,255,255) #FFFFFF gray(255)
0,16: (255,255,255) #FFFFFF gray(255)
0,17: (255,255,255) #FFFFFF gray(255)
0,18: (255,255,255) #FFFFFF gray(255)
0,19: (255,255,255) #FFFFFF gray(255)
0,20: (255,255,255) #FFFFFF gray(255)
0,21: (255,255,255) #FFFFFF gray(255)
0,22: (255,255,255) #FFFFFF gray(255)
0,23: (255,255,255) #FFFFFF gray(255)
0,24: (255,255,255) #FFFFFF gray(255)
0,25: (255,255,255) #FFFFFF gray(255)
0,26: (255,255,255) #FFFFFF gray(255)
0,27: (255,255,255) #FFFFFF gray(255)
0,28: (255,255,255) #FFFFFF gray(255)
0,29: (255,255,255) #FFFFFF gray(255)
0,30: (255,255,255) #FFFFFF gray(255)
0,31: (255,255,255) #FFFFFF gray(255)
0,32: (255,255,255) #FFFFFF gray(255)
0,33: (0,0,0) #000000 gray(0)
0,34: (0,0,0) #000000 gray(0)
0,35: (0,0,0) #000000 gray(0)
0,36: (0,0,0) #000000 gray(0)
0,37: (0,0,0) #000000 gray(0)
0,38: (0,0,0) #000000 gray(0)
0,39: (0,0,0) #000000 gray(0)
0,40: (0,0,0) #000000 gray(0)
0,41: (0,0,0) #000000 gray(0)
0,42: (0,0,0) #000000 gray(0)
0,43: (0,0,0) #000000 gray(0)
0,44: (0,0,0) #000000 gray(0)
0,45: (0,0,0) #000000 gray(0)
0,46: (0,0,0) #000000 gray(0)
0,47: (0,0,0) #000000 gray(0)
0,48: (0,0,0) #000000 gray(0)
0,49: (0,0,0) #000000 gray(0)
0,50: (0,0,0) #000000 gray(0)
0,51: (0,0,0) #000000 gray(0)
0,52: (0,0,0) #000000 gray(0)
0,53: (0,0,0) #000000 gray(0)
0,54: (0,0,0) #000000 gray(0)
0,55: (0,0,0) #000000 gray(0)
0,56: (0,0,0) #000000 gray(0)
0,57: (0,0,0) #000000 gray(0)
0,58: (0,0,0) #000000 gray(0)
0,59: (0,0,0) #000000 gray(0)
0,60: (0,0,0) #000000 gray(0)
0,61: (0,0,0) #000000 gray(0)
0,62: (0,0,0) #000000 gray(0)
0,63: (0,0,0) #000000 gray(0)
0,64: (0,0,0) #000000 gray(0)
0,65: (0,0,0) #000000 gray(0)
0,66: (0,0,0) #000000 gray(0)
0,67: (0,0,0) #000000 gray(0)
0,68: (0,0,0) #000000 gray(0)
0,69: (0,0,0) #000000 gray(0)
0,70: (0,0,0) #000000 gray(0)
0,71: (0,0,0) #000000 gray(0)
0,72: (0,0,0) #000000 gray(0)
0,73: (0,0,0) #000000 gray(0)
0,74: (0,0,0) #000000 gray(0)
0,75: (0,0,0) #000000 gray(0)
0,76: (0,0,0) #000000 gray(0)
0,77: (0,0,0) #000000 gray(0)
0,78: (0,0,0) #000000 gray(0)
0,79: (0,0,0) #000000 gray(0)
如您所见,它是对提取列的每个像素颜色的文本描述(其中像素坐标在每行文本的第一个字段中给出)。第一行表示使用哪种颜色space。
*按字母顺序对 MD5 和进行排序
按字母顺序对这些文本文件的 MD5 总和进行排序时,在像素颜色行和列相同的地方应该会立即显而易见:
md5sum *.text | sort
结果:
(我在某些行的末尾手动添加了一些注释。)
09c0670b59c03fb3d6f8116ee0fe35a2 bottom-edge-10297-13918-3702.text
09c0670b59c03fb3d6f8116ee0fe35a2 top----edge-28824-13023-24184.text
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-20056-20936-29071.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-22806-3380-17484.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-24658-20374-23042.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-27206-10104-18226.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a left---edge-30261-16558-25650.text #left edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-16369-21469-8252.text #right edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-21875-14159-1067.text #right edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-24426-18830-5627.text #right edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-31250-3578-9750.text #right edge of QR
10be914aa8b6aaa8c0e35a4a93421f3a right--edge-5004-10810-17642.text #right edge of QR
217c799ce772d99e11b7ba2a04f42bb7 bottom-edge-11976-7751-26756.text
217c799ce772d99e11b7ba2a04f42bb7 top----edge-5774-30645-16062.text
2c96cebc6cc175b54cae54f1a27771fa bottom-edge-24426-18830-5627.text
2c96cebc6cc175b54cae54f1a27771fa top----edge-21875-14159-1067.text
3088414b0fe1190bbd4ed9315d86a0ac left---edge-13789-10513-4721.text
3088414b0fe1190bbd4ed9315d86a0ac right--edge-22806-3380-17484.text
3755d45bb6ad21b70f545f39c5550eda left---edge-17636-24599-1877.text
3755d45bb6ad21b70f545f39c5550eda right--edge-20056-20936-29071.text
41fc32b4b70622b4aff7d9e81f81daad left---edge-13858-18007-13070.text
41fc32b4b70622b4aff7d9e81f81daad right--edge-10297-13918-3702.text
480bed740a716fa10593ba061c5b6df5 left---edge-5004-10810-17642.text
480bed740a716fa10593ba061c5b6df5 right--edge-20021-11440-20836.text
55cc4713ee13ebbeb5c2e212e430da94 bottom-edge-28824-13023-24184.text
55cc4713ee13ebbeb5c2e212e430da94 top----edge-32078-14314-1511.text
62fecd6971445d4176a842727767d3f7 left---edge-4555-18116-29.text
62fecd6971445d4176a842727767d3f7 right--edge-18056-16294-30425.text
69565761226f122f98267862108119a6 left---edge-21875-14159-1067.text
69565761226f122f98267862108119a6 right--edge-26507-21853-11958.text
72cec2b0a518c2cce7204188923d9f79 left---edge-26507-21853-11958.text
72cec2b0a518c2cce7204188923d9f79 right--edge-15816-4564-31665.text
7343348f1b10e47b33e0bde47b455c2b left---edge-16369-21469-8252.text
7343348f1b10e47b33e0bde47b455c2b right--edge-22161-18187-20222.text
7661c257d28e1916208ed2a70989e42d bottom-edge-13789-10513-4721.text
7661c257d28e1916208ed2a70989e42d top----edge-17636-24599-1877.text
7d2a0d7aae6dc017ffa7af7180b1c017 left---edge-5167-27533-24066.text
7d2a0d7aae6dc017ffa7af7180b1c017 right--edge-32078-14314-1511.text
85b744d1774cd4ebe50f0cc40d10b491 left---edge-18056-16294-30425.text
85b744d1774cd4ebe50f0cc40d10b491 right--edge-27206-10104-18226.text
88942ff37ce0e884d1995a6dd11708d6 left---edge-10297-13918-3702.text
88942ff37ce0e884d1995a6dd11708d6 right--edge-11976-7751-26756.text
9185daee4fdcea482c9fa805bba40346 bottom-edge-31250-3578-9750.text
9185daee4fdcea482c9fa805bba40346 top----edge-16369-21469-8252.text
9b8a7f18e4ebbc7249e5f26ac18190a8 left---edge-28824-13023-24184.text
9b8a7f18e4ebbc7249e5f26ac18190a8 right--edge-5774-30645-16062.text
9bd8f7a474229aefd988c4231f3b26f4 bottom-edge-21875-14159-1067.text
9bd8f7a474229aefd988c4231f3b26f4 top----edge-5004-10810-17642.text
a1778c1a468c122bf408a9c2bec9135c bottom-edge-13858-18007-13070.text
a1778c1a468c122bf408a9c2bec9135c top----edge-22161-18187-20222.text
a4f3eee0e523f1b343d292987da297b3 bottom-edge-20056-20936-29071.text
a4f3eee0e523f1b343d292987da297b3 bottom-edge-24658-20374-23042.text
a4f3eee0e523f1b343d292987da297b3 top----edge-27206-10104-18226.text
a4f3eee0e523f1b343d292987da297b3 top----edge-30261-16558-25650.text
af851da184ea6d6586c64aaefdc6875b bottom-edge-22806-3380-17484.text
af851da184ea6d6586c64aaefdc6875b top----edge-20056-20936-29071.text
b4047de9fb6458ebfde5b3a11b40241a left---edge-5774-30645-16062.text
b4047de9fb6458ebfde5b3a11b40241a right--edge-30261-16558-25650.text
b58fe9214967f6d2311e11cb0bf1acc4 left---edge-15816-4564-31665.text
b58fe9214967f6d2311e11cb0bf1acc4 right--edge-17636-24599-1877.text
bef4d7004da4f5de4ca5beeabc1222e8 bottom-edge-5774-30645-16062.text
bef4d7004da4f5de4ca5beeabc1222e8 top----edge-13789-10513-4721.text
c042d1cd3dfb339177e8da3c2907d58e bottom-edge-15816-4564-31665.text
c042d1cd3dfb339177e8da3c2907d58e top----edge-4555-18116-29.text
c5f38ebda77190495d77df1fb7002d1e bottom-edge-32078-14314-1511.text
c5f38ebda77190495d77df1fb7002d1e top----edge-15816-4564-31665.text
c61f738453fa3a86b52b2de5c0d43530 left---edge-20021-11440-20836.text
c61f738453fa3a86b52b2de5c0d43530 right--edge-4555-18116-29.text
c772762652d22cbf228e57f0dcf1a3b4 bottom-edge-22161-18187-20222.text
c772762652d22cbf228e57f0dcf1a3b4 top----edge-5167-27533-24066.text
cfaa399406e0be3d07297f23c684e7c3 left---edge-11976-7751-26756.text
cfaa399406e0be3d07297f23c684e7c3 left---edge-31250-3578-9750.text
cfaa399406e0be3d07297f23c684e7c3 right--edge-13858-18007-13070.text
cfaa399406e0be3d07297f23c684e7c3 right--edge-24658-20374-23042.text
d39c2a0c14c20b66b441d368c164171d bottom-edge-18056-16294-30425.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d bottom-edge-20021-11440-20836.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d bottom-edge-27206-10104-18226.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d bottom-edge-4555-18116-29.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d bottom-edge-5004-10810-17642.text #bottom edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-10297-13918-3702.text #top edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-11976-7751-26756.text #top edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-13858-18007-13070.text #top edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-24658-20374-23042.text #top edge of QR
d39c2a0c14c20b66b441d368c164171d top----edge-31250-3578-9750.text #top edge of QR
d71e7b561d2cc251c962a843daff53bb bottom-edge-5167-27533-24066.text
d71e7b561d2cc251c962a843daff53bb top----edge-26507-21853-11958.text
d7ffe4aaf744387e7fa9db32271247e0 bottom-edge-26507-21853-11958.text
d7ffe4aaf744387e7fa9db32271247e0 top----edge-20021-11440-20836.text
da2aa01201b3da20a970928bc2bdef36 bottom-edge-30261-16558-25650.text
da2aa01201b3da20a970928bc2bdef36 top----edge-22806-3380-17484.text
dd86f02cfc0e260463c75ae5b8709f33 bottom-edge-16369-21469-8252.text
dd86f02cfc0e260463c75ae5b8709f33 top----edge-24426-18830-5627.text
dfdaa88ebf33284ac0367f92060cd060 bottom-edge-17636-24599-1877.text
dfdaa88ebf33284ac0367f92060cd060 top----edge-18056-16294-30425.text
f8e2f384f2269e086dc00fb6ff0b3f41 left---edge-32078-14314-1511.text
f8e2f384f2269e086dc00fb6ff0b3f41 right--edge-13789-10513-4721.text
fa59372704f3b48912a33f3780e9dce7 left---edge-22161-18187-20222.text
fa59372704f3b48912a33f3780e9dce7 right--edge-28824-13023-24184.text
fff7e26c6f9852fcfa51e79d154dc58a left---edge-24426-18830-5627.text
fff7e26c6f9852fcfa51e79d154dc58a right--edge-5167-27533-24066.text
可以立即识别出以下模式:
- 10 个相同的 MD5 和
d39c2a0c14c20b66b441d368c164171d
- 10 个相同的 MD5 和
10be914aa8b6aaa8c0e35a4a93421f3a
- left/right 边 的 20 对相同的 MD5 和
- top/bottom 边 的 20 对相同的 MD5 和
在“1”的情况下。和“2”。很容易看出这些都是全白边,代表 left/right/top/bottom 条完整的 QR。
剩下的比赛,'3'。和“4”。可以很容易地以确定的方式将每个单独的图块调整到左侧或右侧 "partner"。
更新
直到现在我才看到马克的回答。但是我看他的方法和我的差不多。
虽然我不愿意添加我的完整脚本来生成最终重新组合的二维码。
所以如果 Mark 的解决方案包括这个,他应该得到正确答案的批准。