2013-04-26 102 views
1

假設我有兩個幾乎相同的圖像,我想定位並突出顯示它們之間的差異並生成差異圖像。日常工作,但這個例程要求提供我不想要的顏色。這是我的代碼。發現圖像之間的差異

public class ImageTool 
{ 
    public static unsafe Bitmap GetDifferenceImage(Bitmap image1, Bitmap image2, Color matchColor) 
    { 
     if (image1 == null | image2 == null) 
      return null; 

     if (image1.Height != image2.Height || image1.Width != image2.Width) 
      return null; 

     Bitmap diffImage = image2.Clone() as Bitmap; 

     int height = image1.Height; 
     int width = image1.Width; 

     BitmapData data1 = image1.LockBits(new Rectangle(0, 0, width, height), 
              ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 
     BitmapData data2 = image2.LockBits(new Rectangle(0, 0, width, height), 
              ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 
     BitmapData diffData = diffImage.LockBits(new Rectangle(0, 0, width, height), 
               ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 

     byte* data1Ptr = (byte*)data1.Scan0; 
     byte* data2Ptr = (byte*)data2.Scan0; 
     byte* diffPtr = (byte*)diffData.Scan0; 

     byte[] swapColor = new byte[3]; 
     swapColor[0] = matchColor.B; 
     swapColor[1] = matchColor.G; 
     swapColor[2] = matchColor.R; 

     int rowPadding = data1.Stride - (image1.Width * 3); 

     // iterate over height (rows) 
     for (int i = 0; i < height; i++) 
     { 
      // iterate over width (columns) 
      for (int j = 0; j < width; j++) 
      { 
       int same = 0; 

       byte[] tmp = new byte[3]; 

       // compare pixels and copy new values into temporary array 
       for (int x = 0; x < 3; x++) 
       { 
        tmp[x] = data2Ptr[0]; 
        if (data1Ptr[0] == data2Ptr[0]) 
        { 
         same++; 
        } 
        data1Ptr++; // advance image1 ptr 
        data2Ptr++; // advance image2 ptr 
       } 

       // swap color or add new values 
       for (int x = 0; x < 3; x++) 
       { 
        diffPtr[0] = (same == 3) ? swapColor[x] : tmp[x]; 
        diffPtr++; // advance diff image ptr 
       } 
      } 

      // at the end of each column, skip extra padding 
      if (rowPadding > 0) 
      { 
       data1Ptr += rowPadding; 
       data2Ptr += rowPadding; 
       diffPtr += rowPadding; 
      } 
     } 

     image1.UnlockBits(data1); 
     image2.UnlockBits(data2); 
     diffImage.UnlockBits(diffData); 

     return diffImage; 
    } 
} 

調用像這樣:

Bitmap diff = ImageTool.GetDifferenceImage(image1, image2, Color.Pink); 
diff.MakeTransparent(Color.Pink); 
diff.Save("C:\\test-diff.png",ImageFormat.Png); 
  1. 有人只是指導我如何改變這種慣例,因爲我們沒有通過顏色時,我會打電話給GetDifferenceImage()方法的結果。

  2. 這種方式圖像比較是最好的技術,如果沒有,然後指導我如何開發一個例程,可以更快地獲得差異圖像。

  3. 獲取diff圖像後,我該如何合併diff圖像與image1。幫助我開發更快的合併例程。

+0

太多的問題,但他們不是很清楚:)你打算硬編碼函數內部的顏色,而不是傳遞它? – Egor4eg 2013-04-26 09:24:53

+0

我不想通過顏色或硬編碼,而是改變不依賴於顏色進行圖像比較的例程。我清楚了嗎? – Mou 2013-04-26 10:01:43

+0

據我可以看到,代碼比較2張圖片,併產生所有差異高亮顯示的結果圖片。要突出顯示的顏色將發送到該方法。如果您未傳遞或硬編碼顏色,方法將如何知道使用哪種顏色? – Egor4eg 2013-04-26 10:08:08

回答

5

如果兩幅圖像完全相同,則diff圖像爲黑色,對於差異較大的像素,diff圖像的亮度會增加。您可以更改算法,以便不用爲像素指定交換顏色,而是指定兩種顏色之間的差異。

// iterate over height (rows) 
    for (int i = 0; i < height; i++) 
    { 
     // iterate over width (columns) 
     for (int j = 0; j < width; j++) 
     { 
      // for each channel 
      for (int x=0; x<3; x++) 
      { 
       diffPtr[0] = Abs(data1Ptr[0]-data2Ptr[0]); 
       data1Ptr++; // advance image1 ptr 
       data2Ptr++; // advance image2 ptr 
       diffPtr++; // advance diff image ptr 
      } 
     } 

     // at the end of each column, skip extra padding 
     if (rowPadding > 0) 
     { 
      data1Ptr += rowPadding; 
      data2Ptr += rowPadding; 
      diffPtr += rowPadding; 
     } 
    } 

如何顯示/合併差異將取決於你將如何處理它。

+0

你希望我用你的代碼替換。你可以按照你的方式爲我的例程寫一個名爲GetDifferenceImage()的完整代碼。謝謝 – Mou 2013-04-27 14:21:44

+0

@Mou只需將代碼中的for循環替換爲上面的代碼,然後刪除matchColor參數並不再需要swapColor變量。 – denver 2013-04-27 20:54:09

+0

非常抱歉,我的代碼不幫助我。更好地運行你的代碼。只需要兩個非常接近的相同的PNG圖片,並將這兩個圖像與我們的代碼進行比較,然後查看產生的圖像即將到來。 – Mou 2013-04-28 17:42:38