检查图像是否相同

时间:2014-11-26 01:52:20

标签: image matlab image-processing

好的,所以我正致力于编写一个读取两个图像并确定图像是否相同的功能。有两件事需要检查:

1. The dimensions are the same
2. The dimensions are the same, but the picture itself is different

如果是第二种情况,那么我需要我的功能输出图像像素相同的白色和图像像素不同的黑色。这应该很简单,但出于某种原因,我正在努力。如果图片是相同的,那么我希望它读出'图像是相同的'。如果尺寸不同,那么我希望它说'图像有不同的尺寸'。如果尺寸匹配,但图片不同,那么:

(1) Create an output image that highlights the differences between the
two images. This image should be exclusively black and white, where it
is white everywhere that the two images have the same RGB values, but
black wherever the RGB values of the images differ. This image should
be named by the following naming convention:
'<imageName1>_vs_<imageName2>.png.'
(2) Output the string 'The RBG values are different: see %s.',
where you should print the name of your output file into the '%s'

我有两个第一个案件正在运作。这是我遇到问题的第三个问题。我只是得到一张白色照片。

Test case:
oranges :http://tinypic.com/r/2072gaq/8
tangerines: http://tinypic.com/r/2ufy2bn/8
Solution: http://tinypic.com/r/nqvbep/8
out3 = checkImage('oranges.png', 'tangerines.png');
oute => 'The RGB values are different: see oranges_vs_tangerines.png.'
      - oranges_vs_tangerines.png should look like
        oranges_vs_tangerines_soln.png

这是我到目前为止所做的:

function[comparison] = checkImage(pic1,pic2)
%// Reads in the images
img1 = imread(pic1);
img2 = imread(pic2);

%//Extracts the layers for both pictures
red1 = img1(:,:,1);
green1  = img1(:,:,2);
blue1 = img1(:,:,3);

red2 = img2(:,:,1);
green2 = img2(:,:,2);
blue2 = img2(:,:,3);

%// Finds the dimensions of both pictures
[r1, c1, l1] = size(img1);
[r2, c2, l2] = size(img2);

%// My lovely comparison loop
if size(img1) == size(img2)  
%// Subcase to check if image is the same
    if red1 == red2 & green1 == green2 & blue1 == blue2
    comparison = 'The images are the same';
%//Something down here has to be wrong
    elseif red1 ~= red2 & green1 == green2 & blue1 == blue2
            red = 0;
            green = 255;
            blue = 255;
    elseif red1 ~= red2 & green1 ~= green2 & blue1 == blue2
            red = 0;
            green = 0;
            blue = 255;
    elseif red1 ~= red2 & green1 ~= green2 & blue1 ~= blue2
            red = 0;
            green = 0;
            blue =0;
    elseif red1 == red2 & green1 ~= green2 & blue1 == blue2
            red = 255;
            green = 0;
            blue = 255;
    elseif red1 == red2 & green1 ~= green2 & blue1 ~= blue2
            red = 255;
            green = 0;
            blue = 0;
    else
        red = 255;
        green = 255;
        blue = 0;
%// This part could be the issue, but I am unsure
         newpic = cat(3,red,green,blue);
          name1 = pic1(1:end-4);
          name2 = pic2(1:end);
          picture = [name1 '_vs_' name2];
          imwrite(newpic,picture);
         comparison = sprintf('The RBG values are different: see %s.',picture);
    end   
       %// This appears to work fine 
elseif r1 & c1 & l1 ~= r2 & c2 & l2
    comparison = 'The images have different dimensions.';
else %// I put this in for S&G
         comparison = 'My code is wrong';  
end
end

我感谢任何帮助/建议。我认为我过多地复杂化了这段代码。

编辑:我意识到我的代码正在纠正这些值,但我实际上还没有写到它们的位置。就像,它不知道如何将颜色放在不匹配的地方。我知道我知道怎么做。我只需要更加努力思考。

尝试二:

function[comparison] = checkImage(pic1,pic2)
img1 = imread(pic1);
img2 = imread(pic2);

red1 = img1(:,:,1);
green1  = img1(:,:,2);
blue1 = img1(:,:,3);

red2 = img2(:,:,1);
green2 = img2(:,:,2);
blue2 = img2(:,:,3);

[r1, c1, l1] = size(img1);
[r2, c2, l2] = size(img2);

mask1 = red1 ~= red2 & green1 == green2 & blue1 == blue2;
mask2 = red1 ~= red2 & green1 ~= green2 & blue1 == blue2;
mask3 = red1 ~= red2 & green1 ~= green2 & blue1 ~= blue2;
mask4 = red1 == red2 & green1 ~= green2 & blue1 == blue2;
mask5 = red1 == red2 & green1 ~= green2 & blue1 ~= blue2;
mask6 = red1 ~= red2 & green1 ~= green2 & blue1 ~= blue2;

color1 = [red1 green1 blue1];
color2 = [red2 green2 blue2];
if size(img1) == size(img2) 
    if red1 == red2 & green1 == green2 & blue1 == blue2
    comparison = 'The images are the same';
    elseif mask1 == 1
            red1(mask1) = 0;
            green1(mask1) = 255;
            blue1(mask1) = 255;
    elseif mask2 == 1
            red1(mask2) = 0;
            green1(mask2) = 0;
            blue1(mask2) = 255;
    elseif mask3 == 1
            red1(mask3) = 0;
            green1(mask3) = 0;
            blue1(mask3) =0;
    elseif mask4 == 1
            red1(mask4) = 255;
            green1(mask4) = 0;
            blue1(mask4) = 255;
    elseif mask5 == 1
            red1(mask5) = 255;
            green1(mask5) = 0;
            blue1(mask5) = 0;
    else
        red1(mask6) = 255;
        green1(mask6) = 255;
        blue1(mask6) = 0;
         newpic = cat(3,red1,green1,blue1);
          name1 = pic1(1:end-4);
          name2 = pic2(1:end);
          picture = [name1 '_vs_' name2];
          imwrite(newpic,picture);
         comparison = sprintf('The RBG values are different: see %s.',picture);
    end   

elseif r1 & c1 & l1 ~= r2 & c2 & l2
    comparison = 'The images have different dimensions.';
else 
         comparison = 'My code is wrong';  
end

end

1 个答案:

答案 0 :(得分:2)

好的,让我们简化问题描述...主要是因为它可以让我更快地回答这个问题,并让我更好地理解需要做什么:

给出两张图片:

  1. 我们需要检查两者的尺寸是否相同。
  2. 如果尺寸匹配,那么我们需要检查两张图片是否完全相同。如果是,那么我们将输出图像是相同的。
  3. 如果不是,那么您需要浏览两个图像的每个像素,然后标记该位置是否具有相同的白色RGB值,或者它们没有相同的黑色值。
  4. 此外,您提供了示例图像和基本事实:

    图像#1

    http://oi59.tinypic.com/2072gaq.jpg

    图像#2

    http://oi58.tinypic.com/2ufy2bn.jpg

    地面真相(可爱!)

    http://oi59.tinypic.com/nqvbep.jpg

    请注意,图像是使用JPEG量化进行量化的,因此,由于量化噪声,您将无法获得完全相同的输出。你会在这里和那里得到一些虚假的像素,但整体画面看起来应该是一样的。


    我们假设图像是以img1img2加载的。

    img1 = imread('http://oi59.tinypic.com/2072gaq.jpg');
    img2 = imread('http://oi58.tinypic.com/2ufy2bn.jpg');
    

    首先,让我们检查尺寸是否相同:

    img1Rows = size(img1, 1);
    img1Cols = size(img1, 2);
    img2Rows = size(img2, 1);
    img2Cols = size(img2, 2);
    
    if (img1Rows ~= img2Rows) || (img1Cols ~= img2Cols)
        disp('Image dimensions are not the same');
        return;
    end
    

    上面的代码读取每个图像的尺寸(行和列),并检查两个图像的行和列是否匹配。如果他们不这样做,我们输出它们的尺寸不同然后退出。

    现在,如果它们是相同的,那么让我们检查图像是否完全相同。我建议你做的是拍摄每张图片并重新塑造它们,使它们适合单个矢量。执行此操作后,逐点进行并将所有这些差异相加。如果图像完全相同,则所有差异的总和将为零。我还要将图像转换为double精度以允许负差异。不确定您是否覆盖了数据类型,但图像通常是无符号的8位整数,这意味着有效的数字范围介于[0,255]之间。任何低于0的值都会被剪切为0,而任何大于255的值都会被剪切为255.因此,如果你做了0 - 1并且这是无符号的8位整数,那么这将被注册为0的差值,这是不正确。因此,让我们将图像转换为double,并取绝对值,以确保我们不会出现一些情况,即我们有一些负数和正数取消给我们零和。因此:

    img1_double = double(img1);
    img2_double = double(img2);
    if sum( abs( img1_double(:) - img2_double(:) ) ) == 0.0
        disp('The images are the same');
        return;
    end
    

    现在,我们遇到图像不具有相同内容的情况。我要做的是提取每个颜色平面,然后做一个巨大的相等运算符,看看我们是否在相应的位置有相同的RGB值。换句话说:

    out = (img1(:,:,1) == img2(:,:,1)) & (img1(:,:,2) == img2(:,:,2)) & (img1(:,:,3) == img2(:,:,3));
    out = 255*uint8(cat(3,out,out,out));
    

    这基本上检查图像在相应位置是否具有相同的RGB值。这将生成一个二进制图像,指示我们上面定义的标准。因为您需要返回彩色图像,我们只需在第三维中复制图像三次,转换为uint8,然后乘以255将其转换为RGB图像。

    你还可以做的是你可以将它美化为for循环。首先分配全部为逻辑true的图像,然后提取每个图像的颜色平面对,找到每个颜色平面相等的位置,然后逻辑AND结果并将其附加到out。我们基本上实现了与上面相同的功能,但它更加紧凑。因此:

    out = true(size(img1,1), size(img1,2));
    for p = 1 : 3
        img1_plane = img1(:,:,p);
        img2_plane = img2(:,:,p);
        out = out & (img1_plane == img2_plane);
    end
    out = 255*uint8(cat(3,out,out,out));
    

    如果我们使用imshow(out);显示此图片,我们会得到:

    enter image description here

    甜。现在,我们要做的就是显示相应的消息。您已经在上面的代码中完成了这项工作。现在,如果我们想把这一切都包装成一个很好的函数,我们会这样做:

    function [comparison] = checkImage(pic1,pic2)
       img1 = imread(pic1);
       img2 = imread(pic2);
    
       img1Rows = size(img1, 1);        
       img1Cols = size(img1, 2);
       img2Rows = size(img2, 1);
       img2Cols = size(img2, 2);
    
       if (img1Rows ~= img2Rows) || (img1Cols ~= img2Cols)
           comparison = 'Image dimensions are not the same';
           return;
       end
    
       img1_double = double(img1);
       img2_double = double(img2);
       if sum( abs( img1_double(:) - img2_double(:) ) ) == 0.0
           comparison = 'The images are the same';
           return;
       end
    
       out = (img1(:,:,1) == img2(:,:,1)) & (img1(:,:,2) == img2(:,:,2)) & (img1(:,:,3) == img2(:,:,3));
    
       % // OR
       %out = true(size(img1,1), size(img1,2));
       %for p = 1 : 3
       %    img1_plane = img1(:,:,p);
       %    img2_plane = img2(:,:,p);
       %    out = out & (img1_plane == img2_plane);
       %end
       out = 255*uint8(cat(3,out,out,out));
       picture = [pic1(1:end-4) '_vs_' pic2(1:end-4) '.png'];
       imwrite(out, picture);
       comparison = sprintf('The RGB values are different: see %s.',picture);
    

    记下最后三行代码。我们通过提取两个图像名称的最后四个字符,然后在中间添加_vs_字符串,并附加.png来创建我们将保存图像的字符串。在字符串的末尾。我们也将存储在out中的二进制图像写入文件。我还更改了我的disp语句,将字符串写入comparison,因为您已将其添加到函数中。这是在函数中返回的字符串,但作为副作用,我们还在该命名约定中将图像写入文件。


    玩得开心!