2014-10-28 42 views
0

我的目的是比较两个图像之间的像素,并找出最小(优化的)包含图像之间所有不同像素的矩形区域。 简单地说,我比较了两幅图像的所有像素(例如1024 * 768像素),发现了不同的部分,但由于速度而不是好主意。 我需要做这个比较每秒至少十五次。 你知道更有效的算法吗?查找两个图像之间的不同区域

+0

您不指定使用的平台/语言。这样的像素比较任务通常可以支持每秒100 MBytes以上的速度,使用C或SSE优化的C.如果我理解您的问题,那么可能没有比蛮力更好的方法。 – 2014-10-28 13:33:17

回答

1

如果你的像素值存储在二维数组中(比如灰度值为0-255),你可以做的就是像矩阵一样处理数组,然后减去两个数组。结果中的条目是零是相同的像素,非零表示它们是不同的。然后,您会发现包含非零条目的顶部行作为您的y-MAX,您的y-MIN包含非零的最低行,x-MIN包含非零的第一列和非零的最后一列为x-MAX。然后该矩形具有4个坐标:

  • (X-MIN,Y-MIN)--lower左角
  • (X-MAX,Y-MIN)--lower右上角
  • (X- MAX,Y-MAX)--top右上角
  • (X-MIN,Y-MAX)--top左侧开出角球

如果你碰巧知道所有的条目都至少为零(可能是通过获取绝对值来完成,但这会增加成本),那么你可以通过右边所有1的列向量乘以矩阵。这会给你一个行数。然后,您会找到第一个和最后一个非零的行数(自上而下搜索,自下而上)。如果你在左边乘以全1的行向量,你会得到相同的结果,但是列总和。再次寻找那些非零的。

矩阵运算很好,因为有优化的库可以帮助加速计算(并且矩阵并不那么大)......特别是如果您有可用于执行计算的GPU。但即使在串行中,小矩阵向量计算也不是那么耗时。

8

从另一个图像中减去一个图像。相同的像素将变为零,即黑色。

找到一个黑色的角落,并使用trim(修剪边框/边缘)类型的命令来修剪黑色边框,这将告诉您区别的区域。

这是很简单的ImageMagick的两行做,如果你可以使用 - 它可对C/C多的平台++,Python和Perl中......

让我们两个图像,a.jpgb.jpg

enter image description here

enter image description here

你看到我做了什么呢? :-)

现在我们可以使用ImageMagick来查找差异和不同的区域。我正在使用命令行,但正如我所说的,您可以使用C/C++,Perl,Python,.NET或其他任何可以漂浮您的船的设备。

要么用它来寻找差异:

convert a.jpg b.jpg \ 
     -compose difference \ 
     -composite \ 
     -threshold 0 \ 
     -separate \ 
     -evaluate-sequence Add \ 
     diff.jpg 

其中给出了这样的:

enter image description here

或者使用:

composite a.jpg b.jpg -compose difference diff.jpg 

其中给出了这样的:

enter image description here

或者用这个简单的减法:

convert a.jpg b.jpg -compose minus -composite diff.jpg 

enter image description here

现在你可以使用ImageMagick的边框装饰功能来评价,如果你修剪所有的黑色边框过什么会留下,像这样:

convert a.jpg b.jpg \ 
     -compose difference \ 
     -composite \ 
     -threshold 0 \ 
     -separate \ 
     -evaluate-sequence Add \ 
     -format "%w %h %@" \ 
     info: 

它输出这个:

400 463 264x240+80+176 

告诉你图像是400x463,如果你裁剪了边框,你将剩下一个矩形264x240,其左上像素偏移80,176从图像的左上角。

只是为了好玩,我会绘制矩形到图像中的红色,用这个命令:

convert diff.jpg \ 
     -stroke red \ 
     -fill transparent \ 
     -draw "rectangle 80,176 344,416" \ 
     rect.jpg 

其中给出了这样的:

enter image description here

从本质上讲,你可以做我的全部在这里用一行或两行shell解释,或者8-10行C/C++。请注意,边界框稍大,因为我叠加的漫画具有透明的矩形背景。如果您需要在差分中允许一定程度的“粗糙”,您还可以使用-fuzz 5%来允许图像中的细微差异。

检测的边界框的另一方式是squidge的差分图像,直到它是一个高大的图像,只有一个像素宽,这样的:

convert diff.jpg -scale 1x! -threshold 1% t.jpg 

得到的图像如下:

enter image description here

现在,如果将输出转换为文本格式,您可以很容易地找到第一个白色像素(在程序中,您不会这样做 - 您会写一个循环代替 - 但我是示出的概念在这里):

convert diff.jpg -scale 1x! -threshold 1% txt: | grep -m1 white 

0,176: (255,255,255) #FFFFFF white 

grep -m1 white查找具有在它white第一行,然后停止寻找(匹配被限制为1)。这表明白色像素的第一行是176 - 与上面的红色框相比。现在我们可以找到最后一个白色像素,使用:

convert diff.jpg -scale 1x! -threshold 1% txt: | grep white | tail -1 

0,415: (255,255,255) #FFFFFF white 

并且我们知道行415是边界框的底部。

现在你squidge图像的宽而扁的版本仅有1个像素高,并找到自己的边框的左,右极限:

convert diff.jpg -scale x1! -threshold 1% txt: | grep -m1 white 

80,0: (255,255,255) #FFFFFF white 

convert diff.jpg -scale x1! -threshold 1% txt: | grep white | tail -1 

343,0: (255,255,255) #FFFFFF white 

所以您边框的左右极限是80和343 - 根据红色矩形。

+2

+1的详细示例,而不仅仅是文本。 – kkuilla 2014-10-29 09:58:36

相关问题