2016-07-12 4 views
0

Windows Forms에서 프로젝트를 작업하고 있는데 문제가 있습니다. 이 프로젝트에서는 스크린 샷과 파일의 이미지를 비교해야합니다. 나는 인터넷에서 비교를위한 좋은 방법을 발견하고 그것이 작동하는 것 같다. 예 : Facebook 로고를 사이트에서 cuted했고 데스크톱에 저장했습니다. 이 로고를 그 자체와 비교할 때 (이 스크린 샷을 로고와 비교하는 것보다)이 방법은 올바르게 작동합니다 (스크린 샷에는 로고가 포함되어 있다고 표시되지만 사이트에서 스크린 샷을 만들고 비교할 때 로고가 붙은이 스크린 샷에는 로고가 포함되어 있지 않습니다.스크린 샷과 이미지를 비교할 수 없습니다

것은 나는이 방법을 비교하여 사용하고 있습니다 :

public static Rectangle searchBitmap(Bitmap smallBmp, Bitmap bigBmp, double tolerance) 
{ 
    BitmapData smallData = 
     smallBmp.LockBits(new Rectangle(0, 0, smallBmp.Width, smallBmp.Height), 
      System.Drawing.Imaging.ImageLockMode.ReadOnly, 
      System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
    BitmapData bigData = 
    bigBmp.LockBits(new Rectangle(0, 0, bigBmp.Width, bigBmp.Height), 
      System.Drawing.Imaging.ImageLockMode.ReadOnly, 
      System.Drawing.Imaging.PixelFormat.Format24bppRgb); 

    int smallStride = smallData.Stride; 
    int bigStride = bigData.Stride; 

    int bigWidth = bigBmp.Width; 
    int bigHeight = bigBmp.Height - smallBmp.Height + 1; 
    int smallWidth = smallBmp.Width * 3; 
    int smallHeight = smallBmp.Height; 

    Rectangle location = Rectangle.Empty; 
    int margin = Convert.ToInt32(255.0 * tolerance); 

    unsafe 
    { 
     byte* pSmall = (byte*)(void*)smallData.Scan0; 
     byte* pBig = (byte*)(void*)bigData.Scan0; 

     int smallOffset = smallStride - smallBmp.Width * 3; 
     int bigOffset = bigStride - bigBmp.Width * 3; 
     bool matchFound = true; 

     for (int y = 0; y < bigHeight; y++) 
     { 
      for (int x = 0; x < bigWidth; x++) 
      { 
       byte* pBigBackup = pBig; 
       byte* pSmallBackup = pSmall; 

       //Look for the small picture. 
       for (int i = 0; i < smallHeight; i++) 
       { 
        int j = 0; 
        matchFound = true; 
        for (j = 0; j < smallWidth; j++) 
        { 
         //With tolerance: pSmall value should be between margins. 
         int inf = pBig[0] - margin; 
         int sup = pBig[0] + margin; 
         if (sup < pSmall[0] || inf > pSmall[0]) 
         { 
          matchFound = false; 
          break; 
         } 

         pBig++; 
         pSmall++; 
        } 

        if (!matchFound) break; 

        //We restore the pointers. 
        pSmall = pSmallBackup; 
        pBig = pBigBackup; 

        //Next rows of the small and big pictures. 
        pSmall += smallStride * (1 + i); 
        pBig += bigStride * (1 + i); 
       } 

       //If match found, we return. 
       if (matchFound) 
       { 
        location.X = x; 
        location.Y = y; 
        location.Width = smallBmp.Width; 
        location.Height = smallBmp.Height; 
        break; 
       } 
       //If no match found, we restore the pointers and continue. 
       else 
       { 
        pBig = pBigBackup; 
        pSmall = pSmallBackup; 
        pBig += 3; 
       } 
      } 

      if (matchFound) break; 

      pBig += bigOffset; 
     } 
    } 

    bigBmp.UnlockBits(bigData); 
    smallBmp.UnlockBits(smallData); 

    return location; 
} 

이 방법은 사각형 "위치"를 반환합니다. (location.Width == 0 || location.height == 0) 인 경우 스크린 샷에 이미지가 포함되지 않았다는 의미입니다. 무엇이 문제입니까?

+0

하나의 가능한 이유는 스크린 샷이 화면 해상도를 사용하기 때문에 스크린 샷 크기가 템플릿과 다를 수 있습니다. 코드에서 '로고'크기가 동일한 것으로 가정했습니다. – urlreader

+0

스크린 샷 크기는 템플릿보다 크지 만, 스크린 샷의 이미지를 인식 할 때보 다 (브라우저가 아닌) 이미지의 스크린 샷을 만들 때 있습니다. 반대편에서 브라우저에서 스크린 샷을 만들 때, 그를 인식 할 수 없습니다. –

+0

로고 크기 확인 1) 브라우저에서 스크린 샷; 2) 브라우저가 아닙니다. 매우 가능합니다. 크기는 같지 않습니다 (유사 할 수도 있음). 그래서 그들을 맞추기 위해서는 다음을 고려해야합니다. 1) 로고의 크기. 2) 작은 임계 값이있는 RGB와 일치하는 대신 가장자리와 같은 다른 기능을 사용하십시오 ... – urlreader

답변

0

스크린 샷에 경계선 주위에 빈 공간이 있으면 스크린 샷이 전체 화면이 아닌 한 이미지와 일치하지 않을 가능성이 큽니다.

+0

이 로고가 표시되는 곳을 대략 알고 있으므로 모든 스크린에 스크린 샷을 만들지 않고 데스크톱에서 사각형을 잘라냅니다. 그 Rectangle은 스크린 샷이며 이미지뿐만 아니라 배경 또는 다른 로고도 포함합니다. –

관련 문제