快速计算两个相似图像之间的“脏污”区域

我有两个非常相似的图像(具体来说,两个截图),我试图找到最好(最快)的方式来查找图像的哪些区域已经改变(作为代表不同区域的矩形arrays)

一些标准:

  • 它不需要像素精确,但必须包括所有变化但是很小(即单像素变化可以接受它周围有很大的误差范围)
  • 它需要很快(理想情况下,2x 1920×1080图像在今天购买的典型消费者机器上应该小于20ms)
  • 它不需要可配置的阈值(但如果有一个允许这个的解决方案,那将是一个很好的奖励)
  • 可以假设输入图像总是完美无损图像。

我有两个工作解决方案,但其中一个是逐个像素计算,这当然是非常慢的。 另一方面,我尝试将两个图像分成不同大小的块并计算每个块的校验和,但这也很慢。

只是对于那些想知道我正在构建什么的人 – 它是一种可以在没有任何插件的浏览器中使用的dumber(和较慢的)远程桌面。

您需要进行每像素像素比较。 我认为它不应该那么慢。 例如代码:

  int size = 1920 * 1080 * 3; byte[] image1 = new byte[size]; byte[] image2 = new byte[size]; byte[] diff = new byte[size]; var sw = new System.Diagnostics.Stopwatch(); sw.Start(); for (int i = 0; i < size; i++) { diff[i] = (byte) (image1[i] - image1[i]); } sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); 

在我的笔记本电脑上运行大约40毫秒。 如果它只是灰度,它运行不到20毫秒。 如果您将使用真实图像数据, diff [i]!= 0将指示两个图像的变化。

如果使用Bitmap.GetPixel或其他慢速方法读取像素值,则解决方案可能会很慢。 如果是这种情况,我建议查看Bitmap.LockBits或使用不安全的方法。

我之前的答案因其格式而被删除,我将以更好的方式再次编写。

我问你是否考虑使用GPU来计算两个图像之间的图像差异。 与CPU计算相比,这种解决方案可以大大增加您的计算时间,因为GPU是高度并行的。

使用C#,您可以尝试使用XNA来实现此目的。 实际上,我使用单通道HLSL(它是用于使用direct3D编程GPU)的像素着色器进行了一些测试:

 texture texture1; texture texture2; sampler textureSampler1 = sampler_state{ Texture = ; }; sampler textureSampler2 = sampler_state{ Texture = ; }; float4 pixelShaderFunction(float2 TextureCoordinate : TEXCOORD0) : COLOR0{ float4 color1 = tex2D(textureSampler1,TextureCoordinate); float4 color2 = tex2D(textureSampler2,TextureCoordinate); if((color1.r == color2.r) && (color1.g == color2.g) && (color1.b == color2.b)){ color1.r = 0; color1.g = 0; color1.b = 0; } else{ color1.r = 255; color1.g = 255; color1.b = 255; } return color1; } technique Compare { pass Pass1 { PixelShader = compile ps_2_0 pixelShaderFunction(); } } 

XNA部分的计算非常简单。 使用XNA的基本片段和visual studio,我只是将绘制函数写为:

 protected override void Draw(GameTime gameTime) { Stopwatch sw = new Stopwatch(); sw.Start(); GraphicsDevice.Clear(Color.CornflowerBlue); e.Parameters["texture1"].SetValue(im1); e.Parameters["texture2"].SetValue(im2); spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone, e); spriteBatch.Draw(im1,new Vector2(0,0),Color.White); spriteBatch.End(); base.Draw(gameTime); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); } 

im1和im2是作为Texture2D加载的两个1920 * 1080彩色bmp图像,e是作为效果加载的file.fx。

使用这种技术,我在相当普通的计算机上获得了17 / 18ms的计算时间(笔记本电脑的I5-2410m @ 2.3Ghz,4Gb ram,Nvidia Geforce GT525m。

这是程序的输出,显示差异图像(抱歉这是高度缩放,因为我没有1920 * 1080屏幕:>),此外是两个图像im1和im2,它们之间有一些差别: http ://img526.imageshack.us/img526/2345/computationtime.jpg

我对GPU编程很陌生,所以如果我在计算时间或其他方面犯了很大的错误,请随时告诉我!

编辑:首先要注意的是,我只是读到“它将是一个非常重要的操作,因为GPU不能很好地处理分支。”

最好的祝福