是否有使用 C# 比较两个 PNG 图像的一部分而不是完整图像的功能?

Posted

技术标签:

【中文标题】是否有使用 C# 比较两个 PNG 图像的一部分而不是完整图像的功能?【英文标题】:Is there a function to compare a part of two PNG images rather than full using C#? 【发布时间】:2021-11-05 03:34:32 【问题描述】:

我在 Visual Studio 2019 IDE 上使用 .NET Framework 编写用于比较两个图像的算法。

虽然比较工作正常,但如果我比较整个 png,但问题是作为主副本的图片(与新生成的图像进行比较)是在过去拍摄的,左上角的旧日期和时间的时间戳是由于最新生成的图片总是会因为图片上时间戳的时间差而产生图片不匹配的失败结果。 目前我正在使用以下内容,它适用于相同的时间戳图像

System.Drawing
System.Drawing.Imaging
Bitmap original_image = (Bitmap)Bitmap.FromFile(imageFile);
Bitmap test_image = (Bitmap)Bitmap.FromFile(testimageFile);
if(object.Equals(original_image,test_image)
return true
BitmpaData bitmapDataMasterPicture = original_image.LockBits(new Rectangle(0,0,original_image.Width,original_image.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
BitmpaData bitmapDataTestPicture = test_image.LockBits(new Rectangle(0,0,test_image.Width,test_image.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);

for(int i = 0; i<totalBytes-1 ;i++)
if(bitmapDataMasterPicture[i] != bitmapDataTestPicture[i])

return false;

original_image.UnlockBits(bitmapDataMasterPicture);
test_image.UnlockBits(bitmapDataTestPicture);

是否有使用 C# 比较两个 png 图像的一部分而不是完整图像的函数/算法?那就是跳过左上角的时间戳。

【问题讨论】:

如果我比较整个 png,比较就可以了 嗯,我们看不到您的代码,所以我们无法告诉您如何调整它。它希望您实际上是在对图像进行映射,而不仅仅是参考?? This: object.Equals(original_image,test_image) 正在比较两个引用,它将始终返回 false,因为引用显然不一样。要确定与内容相关的相等性,您需要以某种方式解析位图数据。使用Bitmap.LockBits() 解析数据或简单地加载图像字节并使用SequenceEquals() 进行比较(必须相同)。 您确实给了一个Rectangle 以将该区域锁定到LockBits 操作。您需要做的就是调整它的坐标和大小。 【参考方案1】:

您可以裁剪图像或绘制一个覆盖时间戳的实心矩形。

Graphics oGraphics= Graphics.FromImage(original_image);
Rectangle rect = new Rectangle(0, 0, 200, 200);
oGraphics.DrawRectangle(new Pen(Color.Black, 3), rect);

【讨论】:

@jimi 感谢您的回复,我将更详细地编辑问题。在我已经附加了代码之后,我实际上是在使用 Bitmap.LockBits() 。但问题是如何从两个图像中删除作为时间戳的图像的一部分并比较 png 图像的其余部分。 好吧,如果您知道要跳过多少行,那么只需执行此操作..! - 有很多关于如何使用 x-y-double 循环来检查 lockbit 像素的示例.. 嗨@TaW 我怎样才能跳过行? 您将从合适的偏移量开始。对于 x-y 循环跳过 30 行像素,从 30 开始 y;对于单个循环,从 (width+stride) * 30 * bpp.. 开始 @A786 使用 LockBits 时,您永远不应该遍历所有字节;位图上每一行的长度被四舍五入到下一个 4 字节的倍数,因此可以包含不属于实际图像数据的字节。您应该逐行检查它,使用可以从 BitmapData 对象中检索的 Stride 作为数据宽度,但只检查像素数据的实际 (width * bpp)。 (承认这在 32bppARGB 中不太重要,因为一个像素是 4 个字节,但掌握原理很重要。)【参考方案2】:

大家好,感谢您的回复。我设法通过在 y 轴上设置偏移量来解决问题,如下所示:

    BitmpaData bitmapDataMasterPicture = original_image.LockBits(new 
 Rectangle(0,10,original_image.Width,original_image.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);


BitmpaData bitmapDataTestPicture = test_image.LockBits(new Rectangle(0,10,test_image.Width,test_image.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);

【讨论】:

以上是关于是否有使用 C# 比较两个 PNG 图像的一部分而不是完整图像的功能?的主要内容,如果未能解决你的问题,请参考以下文章

是否有更改以返回像 response.png 而不是 response.bin 这样的 png 文件

使用 css3 进行图像替换和过渡?

C#中的pHash图像比较实现

在 C# 中比较两个图像的算法

如何使用 C# 反转 XAML PNG 图像的颜色?

拖动png图像时是否可以删除背景颜色?