获取一幅图像在另一幅图像中的位置
我有一个显示网站的浏览器截图。 现在我想找出网站(视口)的位置(相对于整个屏幕截图)。 在这个图像中看到一个带有黑色边框的矩形:
在开始image processing之前,我有可能向网站的DOM添加任何东西。
我已经尝试生成QR码,将其添加到视口的左上angular和右下angular,然后使用imagemagick来确定QR码在较大图像中的位置:
compare -metric "rmse" -subimage-search -dissimilarity-threshold "0.1" -virtual-pixel "edge" "haystack.png" "needle.png" "results.png"
然而,这需要很长的时间。 事实上,我在40分钟后辞职了。
我使用了QR码,因为通过使用时间戳,我可以确信这张图片不会在网站的其他地方find。
此外,截图中QR码的大小是原始QR码的两倍,但我想这是由于我的Mac屏幕有144dpi。
我正在使用node.js,所以我需要任何可以通过命令行(如imagemagick )执行的东西,以便我可以从节点或直接节点模块执行它。
我有一个优势,就是我可以select想要在更大的图像中search的图像。 我猜测要find的确切知识可能是一个有用的信息来加速过程(但我不知道如何使用这些信息)。
如果您发现子图像search太慢,我有几个build议可以考虑加快search速度。
1.减小图像大小
我进行了一个小实验来testing在各种大小的干草堆中search不同大小的针,如下所示:
#!/bin/bash # Create a range of haystack sizes for h in 200 400 800; do # And a range of needle sizes for n in 10 20 40; do # Create haystack to search in, containing two needles convert -size ${h}x${h}! gradient:red-black -fill white \ -draw "rectangle 100,100 139,139" \ -draw "rectangle 150,150 189,189" \ haystack.png # Create a needle this size to search for convert -size ${n}x${n}! xc:white needle.png cp haystack.png haystack_${h}x${h}.png cp needle.png needle${n}x${n}.png # Search, measuring the time start=$SECONDS compare -dissimilarity-threshold 1.0 -metric rmse -subimage-search haystack.png needle.png null: > /dev/null 2>&1 end=$SECONDS ((elapsed=end-start)) echo Haystack:${h}x${h}, needle:${n}x${n}, time:$elapsed done done
并发现大小如何影响search时间,如下所示:
Haystack:200x200, needle:10x10, time:2 Haystack:200x200, needle:20x20, time:2 Haystack:200x200, needle:40x40, time:2 Haystack:400x400, needle:10x10, time:8 Haystack:400x400, needle:20x20, time:8 Haystack:400x400, needle:40x40, time:10 Haystack:800x800, needle:10x10, time:33 Haystack:800x800, needle:20x20, time:36 Haystack:800x800, needle:40x40, time:47
正如你所看到的,图像的大小有很大的不同。
这里有三个不同大小的干草堆,每个包含2个白色“ 针 ”:
这里是ImageMagick认为“ 针 ”所在的“ 结果 ”图像:
尽可能地停下来
如果添加参数-similarity-threshold
并将其设置为合理的值,则可以在find第一个匹配项时立即停止search,如grep -m 1
。
像这样设置会使它在第一次完美匹配时停止(相似度为零):
-similarity-threshold 0.0
或者像这样设置会使它停止在第一个“非常好的匹配”
-similarity-threshold 0.05
并且默认设置是1.0
从不匹配,从而导致search在整个图像上继续。
现在我知道你想find视口的顶部和底部,这是两场比赛,看起来很快find第一场比赛是没有用的。 但孔子说, “旋转你的形象” 🙂
所以,find你的第一个(即顶部)匹配,然后旋转你的图像(和针)180度,再次search,但这次你从底部search,可以再次停止在第一场比赛。 (旋转你的结果。)
3.使用你付出的所有可爱的核心 – 并行化!
您可以将图像拆分为多个部分,并行search以充分利用您为之付出的所有可爱的英特尔内核。 你需要小心重叠一点,以便你的针没有跨越你所切割的边界,但是你所需要的就是在针的宽度上添加一条条纹到search区域……就像这样
#!/bin/bash # Create a range of haystack sizes for h in 200 400 800; do # And a range of needle sizes for n in 10 20 40; do # Create haystack to search in, containing two needles convert -size ${h}x${h}! gradient:red-black -fill white \ -draw "rectangle 100,100 139,139" \ -draw "rectangle 150,150 189,189" \ haystack.png # Create a needle this size to search for convert -size ${n}x${n}! xc:white needle.png cp haystack.png haystack_${h}x${h}.png cp needle.png needle${n}x${n}.png # Search, measuring the time start=$SECONDS compare -dissimilarity-threshold 1.0 -metric rmse -subimage-search haystack.png needle.png null: > /dev/null 2>&1 end=$SECONDS ((elapsed=end-start)) echo Haystack:${h}x${h}, needle:${n}x${n}, time:$elapsed ((a=h/2)) ((b=h/2)) ((c=a+n)) ((d=b+n)) ((e=an)) ((f=bn)) # Measure time for parallel search, including dividing up image start=$SECONDS convert haystack.png -crop ${c}x${d}+0+0 +repage h1.png convert haystack.png -crop ${a}x${b}+${a}+0 +repage h2.png convert haystack.png -crop ${a}x${b}+0+${b} +repage h3.png convert haystack.png -crop ${c}x${d}+${e}+${f} +repage h4.png for p in 1 2 3 4; do compare -dissimilarity-threshold 1.0 -metric rmse -subimage-search h${p}.png needle.png null: > /dev/null 2>&1 & done wait end=$SECONDS ((elapsed=end-start)) echo Parallel Haystack:${h}x${h}, needle:${n}x${n}, time:$elapsed done done
你可以看到并行时间几乎比单线程时间快4倍:
Haystack:200x200, needle:10x10, time:2 Parallel Haystack:200x200, needle:10x10, time:0 Haystack:200x200, needle:20x20, time:2 Parallel Haystack:200x200, needle:20x20, time:1 Haystack:200x200, needle:40x40, time:2 Parallel Haystack:200x200, needle:40x40, time:1 Haystack:400x400, needle:10x10, time:8 Parallel Haystack:400x400, needle:10x10, time:2 Haystack:400x400, needle:20x20, time:8 Parallel Haystack:400x400, needle:20x20, time:3 Haystack:400x400, needle:40x40, time:10 Parallel Haystack:400x400, needle:40x40, time:4 Haystack:800x800, needle:10x10, time:33 Parallel Haystack:800x800, needle:10x10, time:10 Haystack:800x800, needle:20x20, time:36 Parallel Haystack:800x800, needle:20x20, time:11 Haystack:800x800, needle:40x40, time:47 Parallel Haystack:800x800, needle:40x40, time:14