我有两个非常相似的图像(特别是两个屏幕截图),我正在尝试找到查找图像哪些区域已更改的最佳(最快)方法(作为代表不同区域的矩形数组)
几个标准:
- 它不需要像素精确,但必须包括所有更改,无论多么小(即,单个像素更改周围有很大的误差范围是可以接受的)
- 它需要快速(理想情况下,2x 1920x1080 图像在今天购买的典型消费机器上应该需要 <20 毫秒)
- 它不需要可配置的阈值(但如果有一个解决方案允许这样做,这将是一个很好的奖励)
- 可以假设输入图像始终是完美的无损图像。
我有两个工作解决方案,但一个是蛮力逐像素计算,当然非常慢。对于另一个,我尝试将两个图像分成不同大小的块,并计算每个块的校验和,但这也非常慢。
对于那些想知道我在构建什么的人 - 它是一种更笨(且更慢)的远程桌面,可以在没有任何插件的情况下在浏览器中使用。
您需要进行每个像素的比较。我认为它不应该那么慢。例如代码:
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 = <texture1>;
};
sampler textureSampler2 = sampler_state{
Texture = <texture2>;
};
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部分的计算非常简单。使用带有Visual studio的XNA的基本片段,我只是将draw函数编写为:
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 内存、Nvidia Geforce GT525m 的笔记本电脑。
这是程序的输出,显示了不同的图像(抱歉,这是高度缩放的,因为我没有 1920*1080 屏幕:>),此外还有两个图像 im1 和 im2,它们之间有一些小差异:http://img526.imageshack.us/img526/2345/computationtime.jpg
我对 GPU 编程很陌生,所以如果我在如何计算时间或其他方面犯了一个巨大的错误,请随时告诉!
编辑:首先要注意的是,我刚刚读到"这将是一个不平凡的操作,因为 GPU 不能很好地处理分支。
此致敬意