1

I am concerned about to find dissimilarities between images as shown in the samples underneath with the black oval shape.

My problem is that some part of image is also variable, but I do not want to consider this part when finding dissimilarities. To overcome this problem I want to make "transparent" that area which is now marked with red color: the variable part Date/Time and the Date/Time edit field should be excluded from comparison as can be seen from image below:

enter image description here

One way is: I can use a “transparent” color to mark image areas that should not be compared. To do this, I need to modify the baseline copy of an image in the following manner:

  • Open the baseline image in an image editor (for instance, in MSPaint).
  • Select the color that you will use as the “transparent” color.
  • Change the color of the top-left pixel to the “transparent” color.
  • Use the “transparent” color to fill image areas that you want to exclude from comparison.

How to do automate above manual work through coding? I want to implement above behavior in C code.

Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
amol saxena
  • 299
  • 2
  • 5
  • 12
  • How would your program know which part to paint in red ? Or how would the user do that ? – chmike Mar 05 '15 at 15:27
  • Can you please better explain and try to reword your question? The part were I don't understand is *"my problem is that some part of image is variable"*. Because comparing images normally is about comparing *different* images (that is: images ***with*** some variables). To compare two images with ***no*** differences at all is not that interesting... – Kurt Pfeifle Mar 05 '15 at 15:33
  • As you can see i am not worried about Date/Time value as it will always change , i am comparing only static text or position of button ,label,input field etc between two images as marked in black oval shape.I will provide x0y0,x1,y1 as input parameter for marking the area with color – amol saxena Mar 05 '15 at 16:01
  • Perhaps the question your really looking to find is: "how to perform image analysis". That is a long, complex, operation that is not within the scope of SO. – user3629249 Mar 05 '15 at 16:24
  • I have code to compare two images pixel by pixel but before compare such kind of screenshot w i want to paint that dynamic area with some color. – amol saxena Mar 05 '15 at 16:29

3 Answers3

4

My suggestion is:

  1. First implement the solution as a command line with ImageMagick.
  2. Once this works, port this command line over to ImageMagick's C API.

Here are a few answers about comparing images using ImageMagick compare. They may not apply to your precise question, but thy provide enough theoretical background with practical examples to get you started:

If I understand your question correctly, you do want to compare only some parts of two images, any you want to exclude other parts from the comparison where you already know there are (uninteresting) differences. Right?

Taking these two images as an example:

compare.png

reference.png

BTW, these two images have been born as PDFs, and I could apply the procedure described below to PDF pages too (without a need to convert them to image files first).

You do not necessarily need a transparent mask -- you can use a black (or any color) one too.

Create a green mask of 280x20 pixels size:

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

Now use composite to place the mask on top of each of the images:

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


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

The -geometry +32+35 parameter maybe requires some explanation: it tells ImageMagick to place the top left corner of the greenmask 32 pixels to the right and 35 pixels to the bottom of the top left corner of the original image.

The resulting images are here:

c.png

r.png

An answer that discusses the different compose methods known to ImageMagick is here:

Now your images are ready for either statistical or visual comparison, provided by ImageMagick's compare command:

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

The delta.png shows all pixels in red which are different, the rest is white:

delta.png

Or, using the most simple compare command, where the reference image serves as a pale background with red delta pixels on top:

compare c.png r.png  delta2.png

delta2.png

Community
  • 1
  • 1
Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
3

If you are providing a rectangle to colour in, why not just ignore a rectangular area in the first place? Here is some pseudo code

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 for several areas to be ignored, which may overlap.

Still not hard: just provide an array of rectangles. It is still going to be easier than going to the trouble of painting out areas when you can check them in the first place.

#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;
}

Program output:

Same
Different

EDIT added another version of the function, comparing 4 pixel components.

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;
}
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • This holds good if image having one dynamic area, if multiple dynamic area is there then its very difficult to ignore all rectangular area – amol saxena Mar 05 '15 at 16:45
  • 1
    Now you have changed the question! You said "a rectangle". Just extend the idea to provide the function with a linked list, or array, or rectangle structs. – Weather Vane Mar 05 '15 at 16:48
  • can you please provide the code for at least for two rectangular area remaining i will take care – amol saxena Mar 05 '15 at 16:58
  • Last question i didn't get the logic image1[20*WID+20] = 1; this means pixel in one of the rectangle and pixel outside any rectangles image1[0] = 1; ? – amol saxena Mar 05 '15 at 19:18
  • `image1[20*WID+20]=1` sets the pixel at (20,20) in my cheap image representation as a 1-D array, which is inside the first rectangle defined. `image1[0]=1` sets the pixel at (0,0) which is not in either of the 2 rectangles, sorry it was a bit lazy of me to do it that way. Because I declared the two image arrays as global (static) they would be initialised to all `0` values - my susbstitute for loading some images. – Weather Vane Mar 05 '15 at 19:31
  • what does this vertical bar means in code "ignore |= inrect (x, y, rarr[n]);" – amol saxena Mar 15 '15 at 10:06
  • @amolsaxena the similar `a += b;` means `a = a + b;`, but in this case `a |= b;` means `a = a | b;` The `|` is `bitwise OR`. As it relates to my answer, `ignore` tallies whether any of the calls to `inrect()` return `1`. Summing the return values would have done just as well. – Weather Vane Mar 15 '15 at 18:36
  • can you please help me out last time , your code works perfectly if each pixel contains 1byte, as for me i am working on bitmap image here each pixel contains 4 byte(Red,Green,Blue and Alpha) then how to apply your logic in that case – amol saxena Mar 16 '15 at 03:22
  • 1
    @amolsaxena I have added another version of `compareimages()` which checks 4 bytes per pixel. If you can't get it working I think you need to ask another question now showing your code and asking why it does not work properly. – Weather Vane Mar 16 '15 at 16:34
0
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
user3629249
  • 16,402
  • 1
  • 16
  • 17