比较某些部分可变但无关紧要的图像

Comparing images in which some parts are variable, but should not matter

我担心发现图像之间存在差异,如下面的黑色椭圆形样本所示。

我的问题是图像的某些部分是也是变量,但我不想在寻找差异时考虑这部分。为了克服这个问题,我想 "transparent" 现在用红色标记的区域:变量部分 Date/Time 和 Date/Time 编辑字段应该被排除在比较之外,从下图:

一种方法是: 我可以使用“透明”颜色来标记不应比较的图像区域。为此,我需要按以下方式修改图像的基线副本:

如何通过编码将上述手动工作自动化?我想在 C 代码中实现上述行为。

Normally, such an 'image' as is used in the example is NOT a single image.

Rather it is a large number of images overlaying each other.

Most likely, the 'image' is made of:

the background
the outside border (which has 4 parts)
the upper left icon
the upper border clickable button( three of them)

the text field: Date/Time:
the input field: (for the date/time)

the text field: 'Table:'
the input multi line field/ with initial text 'Customers'

etc etc etc

I.E. that is not a single image but rather many images
that overlay each other

a single image would be something like a .bmp or .tif or .jpg file

如果您要提供一个矩形来着色,为什么不首先忽略一个矩形区域呢?这是一些伪代码

int compareimages (char *im1, char* im2, int wid, int dep, int x0, int y0, int x1, int y1) {
    int x, y;
    for (y=0; y<dep; y++)
        for (x=0; x<wid; x++)
            if (x<x0 || x>x1 || y<y0 || y>y1)     // if outside rectangle
                if im1[y*wid+x] != im2[y*wid+x]   // compare pixels
                    return 0;
    return 1;
}

UPDATE 几个要忽略的区域,它们可能重叠。

仍然不难:只需提供一个矩形数组。当您首先检查它们时,它仍然比麻烦地绘制区域更容易。

#include <stdio.h>

#define WID 200
#define DEP 600

typedef struct {
    int left;
    int top;
    int right;
    int bot;
} rect;

char image1[WID*DEP];
char image2[WID*DEP];

int inrect (int x, int y, rect r) {
    if (x<r.left || x>r.right || y<r.top || y>r.bot)
        return 0;
    return 1;
}

int compareimages (char *im1, char* im2, int wid, int dep, rect *rarr, int rects) {
    int x, y, n, ignore;
    for (y=0; y<dep; y++)
        for (x=0; x<wid; x++) {
            ignore = 0;
            for (n=0; n<rects; n++)
                ignore |= inrect (x, y, rarr[n]);
            if (!ignore)
                if (im1[y*wid+x] != im2[y*wid+x])   // compare pixels
                    return 0;
        }
    return 1;
}

int main(void) {
    rect rectarr[2] = { {10, 10, 50, 50}, { 40, 40, 90, 90 }};
    // ... load images ...

    // put pixel in one of the rectangles
    image1[20*WID+20] = 1;
    if (compareimages (image1, image2, WID, DEP, rectarr, 2))
        printf ("Same\n");
    else
        printf ("Different\n");

    // put pixel outside any rectangles
    image1[0] = 1;
    if (compareimages (image1, image2, WID, DEP, rectarr, 2))
        printf ("Same\n");
    else
        printf ("Different\n");
    return 0;
}

程序输出:

Same
Different

EDIT 添加了另一个版本的函数,比较 4 个像素分量。

int compareimages (char *im1, char* im2, int wid, int dep, rect *rarr, int rects) {
    int x, y, n, ignore;
    for (y=0; y<dep; y++)
        for (x=0; x<wid; x++) {
            ignore = 0;
            for (n=0; n<rects; n++)
                ignore |= inrect (x, y, rarr[n]);
            if (!ignore) {
                if (im1[y*wid*4+x] != im2[y*wid*4+x])   // compare pixels
                    return 0;
                if (im1[y*wid*4+x+1] != im2[y*wid*4+x+1])
                    return 0;
                if (im1[y*wid*4+x+2] != im2[y*wid*4+x+2])
                    return 0;
                if (im1[y*wid*4+x+3] != im2[y*wid*4+x+3])
                    return 0;
            }
        }
    return 1;
}

我的建议是:

  1. 首先使用 ImageMagick 将解决方案作为命令行实施。
  2. 一旦成功,将此命令行移植到 ImageMagick 的 C API。

这里有一些关于使用 ImageMagick 比较图像的答案 compare。它们可能不适用于您的确切问题,但您提供了足够的理论背景和实际示例来帮助您入门:

  • ImageMagick compare executable: unrecognized option -metric
  • ImageMagick: “Diff” an Image

如果我对你的问题的理解正确,你只想比较两张图片的某些部分,任何你想从比较中排除你已经知道的其他部分(无趣的)差异。对吗?

以这两张图为例:

顺便说一句,这两张图片已经生成为PDF,我也可以将下面描述的过程应用于PDF页面(无需先将它们转换为图像文件)。

您不一定需要 透明 面具——您也可以使用黑色(或任何颜色)面具。

创建一个 280x20 像素大小的绿色遮罩:

convert -size 280x20 xc:green greenmask-280x20.png

现在使用 composite 将遮罩放在每个图像的顶部:

convert                               \
   http://i.stack.imgur.com/Q1pyC.png \
   greenmask-280x20.png               \
    -geometry +32+35                  \
    -compose over                     \
    -composite                        \
   c.png


convert                               \
   http://i.stack.imgur.com/JVije.png \
   greenmask-280x20.png               \
    -geometry +32+35                  \
    -compose over                     \
    -composite                        \
   r.png

-geometry +32+35 参数可能需要一些解释:它告诉 ImageMagick 将绿色掩码的左上角放置在原始图像的右侧 32 像素和左上角底部 35 像素处。

生成的图像在这里:

这里有一个讨论 ImageMagick 已知的不同 compose 方法的答案:

现在您的图像已准备好进行 统计视觉 比较,由 ImageMagick 的 compare 命令提供:

compare c.png r.png -compose src delta.png

delta.png显示所有不同的红色像素,其余为白色:

或者,使用最简单的 compare 命令,其中参考图像用作顶部带有红色增量像素的浅色背景:

compare c.png r.png  delta2.png