如何找到两个图像之间的差异矩形

Gel*_*tin 5 .net c# algorithm comparison image

我有两个相同大小的图像.找到它们不同的矩形的最佳方法是什么.显然,我可以在不同的方向上浏览图像4次,但我想知道是否有更简单的方法.

例:

第一张图片http://i44.tinypic.com/2cg0u2h.png

第二张图片http://i43.tinypic.com/14l0y13.png

差异http://i40.tinypic.com/5agshd.png

Fid*_*del 5

如果您想要单个矩形,请使用 int.MaxValue 作为阈值。

var diff = new ImageDiffUtil(filename1, filename2);
var diffRectangles = diff.GetDiffRectangles(int.MaxValue);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果您想要多个矩形,请使用较小的阈值。

var diff = new ImageDiffUtil(filename1, filename2);
var diffRectangles = diff.GetDiffRectangles(8);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

ImageDiffUtil.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;

namespace diff_images
{
    public class ImageDiffUtil
    {
        Bitmap image1;
        Bitmap image2;

        public ImageDiffUtil(string filename1, string filename2)
        {
            image1 = Image.FromFile(filename1) as Bitmap;
            image2 = Image.FromFile(filename2) as Bitmap;
        }

        public IList<Point> GetDiffPixels()
        {
            var widthRange = Enumerable.Range(0, image1.Width);
            var heightRange = Enumerable.Range(0, image1.Height);

            var result = widthRange
                            .SelectMany(x => heightRange, (x, y) => new Point(x, y))
                            .Select(point => new
                            {
                                Point = point,
                                Pixel1 = image1.GetPixel(point.X, point.Y),
                                Pixel2 = image2.GetPixel(point.X, point.Y)
                            })
                            .Where(pair => pair.Pixel1 != pair.Pixel2)
                            .Select(pair => pair.Point)
                            .ToList();

            return result;
        }

        public IEnumerable<Rectangle> GetDiffRectangles(double distanceThreshold)
        {
            var result = new List<Rectangle>();

            var differentPixels = GetDiffPixels();

            while (differentPixels.Count > 0)
            {
                var cluster = new List<Point>()
                {
                    differentPixels[0]
                };
                differentPixels.RemoveAt(0);

                while (true)
                {
                    var left = cluster.Min(p => p.X);
                    var right = cluster.Max(p => p.X);
                    var top = cluster.Min(p => p.Y);
                    var bottom = cluster.Max(p => p.Y);
                    var width = Math.Max(right - left, 1);
                    var height = Math.Max(bottom - top, 1);
                    var clusterBox = new Rectangle(left, top, width, height);

                    var proximal = differentPixels
                                        .Where(point => GetDistance(clusterBox, point) <= distanceThreshold)
                                        .ToList();
                    proximal.ForEach(point => differentPixels.Remove(point));

                    if (proximal.Count == 0)
                    {
                        result.Add(clusterBox);
                        break;
                    }
                    else
                    {
                        cluster.AddRange(proximal);
                    }
                };
            }

            return result;
        }

        static double GetDistance(Rectangle rect, Point p)
        {
            var dx = Math.Max(rect.Left - p.X, 0);
            dx = Math.Max(dx, p.X - rect.Right);

            var dy = Math.Max(rect.Top - p.Y, 0);
            dy = Math.Max(dy, p.Y - rect.Bottom);
            return Math.Sqrt(dx * dx + dy * dy);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Form1.cs

using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace diff_images
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var filename1 = @"Gelatin1.PNG";
            var filename2 = @"Gelatin2.PNG";

            var diff = new ImageDiffUtil(filename1, filename2);
            var diffRectangles = diff.GetDiffRectangles(8);

            var img3 = Image.FromFile(filename2);
            Pen redPen = new Pen(Color.Red, 1);
            var padding = 3;
            using (var graphics = Graphics.FromImage(img3))
            {
                diffRectangles
                    .ToList()
                    .ForEach(rect =>
                    {
                        var largerRect = new Rectangle(rect.X - padding, rect.Y - padding, rect.Width + padding * 2, rect.Height + padding * 2);
                        graphics.DrawRectangle(redPen, largerRect);
                    });
            }

            var pb1 = new PictureBox()
            {
                Image = Image.FromFile(filename1),
                Left = 8,
                Top = 8,
                SizeMode = PictureBoxSizeMode.AutoSize
            };

            var pb2 = new PictureBox()
            {
                Image = Image.FromFile(filename2),
                Left = pb1.Left + pb1.Width + 16,
                Top = 8,
                SizeMode = PictureBoxSizeMode.AutoSize
            };

            var pb3 = new PictureBox()
            {
                Image = img3,
                Left = pb2.Left + pb2.Width + 16,
                Top = 8,
                SizeMode = PictureBoxSizeMode.AutoSize
            };

            Controls.Add(pb1);
            Controls.Add(pb2);
            Controls.Add(pb3);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Fox*_*ire 2

我认为没有更简单的方法。

事实上,执行此操作只需(非常)几行代码,因此除非您找到一个可以直接为您执行此操作的库,否则您将找不到更短的方法。