2012-09-08 2 views
2

다음과 같은 내용이 있지만 원본 이미지에서 모든 일치 항목을 찾는 방법을 알아낼 수 없습니다.OpenCv : 복수 일치 찾기

static void Main() 
    { 
     using (var template = Cv.LoadImage(@"images\logo.png", LoadMode.GrayScale)) 
     using (var source = Cv.LoadImage(@"images\manyLogos.png", LoadMode.GrayScale)) 
     using (var sourceColour = Cv.LoadImage(@"images\manyLogos.png", LoadMode.Color)) 
     { 
      var width = source.Width - template.Width + 1; 
      var height = source.Height - template.Height + 1; 
      using (var result = Cv.CreateImage(Cv.Size(width, height), BitDepth.F32, 1)) 
      { 
       Cv.MatchTemplate(source, template, result, MatchTemplateMethod.SqDiff); 
       var THRESHOLD = 0.08D; 

       double minVal, maxVal; 
       CvPoint minLoc, maxLoc;      
       Cv.MinMaxLoc(result, out minVal, out maxVal, out minLoc, out maxLoc); 

       var outlineColor = (minVal > THRESHOLD) ? CvColor.Green : CvColor.Red; 
       Cv.Rectangle(sourceColour, Cv.Point(minLoc.X, minLoc.Y), Cv.Point(minLoc.X + template.Width, minLoc.Y + template.Height), outlineColor, 1, 0, 0); 
      } 

      using (var window = new CvWindow("Test")) 
      { 
       while (CvWindow.WaitKey(10) < 0) 
       { 
        window.Image = sourceColour; 
       } 
      } 
     } 
    } 

나는 모든 경기가 아닌 최선의 경기를 개설 할 수 있습니다. 어떻게 든 모든 경기를해야합니다.

답변

2

matchTemplate 메서드를 사용하면 출력 이미지가이 특정 위치에서 템플릿이 일치하는 정도를 나타내는 픽셀 값을 제공합니다. MatchTemplateMethod.SqDiff를 사용 했으므로 값이 낮을수록 일치하는 것이 가장 좋습니다.

당신은 minMaxLoc 함수를 사용할 때, 당신이 묻는 것을 얻을 수 있는데,이 경우 가장 적합합니다 (분).

모든 일치 항목은 설정 한 임계 값보다 작은 값의 픽셀입니다. 내가 CSHARP하는 데 사용하고 있지 않다 때문에 는, 여기 당신이 번역 할 수있는, C++로 갈 것입니다 방법입니다

// after your call to MatchTemplate 
float threshold = 0.08; 
cv::Mat thresholdedImage; 
cv::threshold(result, thresholdedImage, threshold, 255, CV_THRESH_BINARY); 
// the above will set pixels to 0 in thresholdedImage if their value in result is lower than the threshold, to 255 if it is larger. 
// in C++ it could also be written cv::Mat thresholdedImage = result < threshold; 
// Now loop over pixels of thresholdedImage, and draw your matches 
for (int r = 0; r < thresholdedImage.rows; ++r) { 
    for (int c = 0; c < thresholdedImage.cols; ++c) { 
    if (!thresholdedImage.at<unsigned char>(r, c)) // = thresholdedImage(r,c) == 0 
     cv::circle(sourceColor, cv::Point(c, r), template.cols/2, CV_RGB(0,255,0), 1); 
    } 
} 
2

C에서 번역 ++와 래퍼를 OpenCvSharp 사용하여, 위의 코드는, minMaxLoc 라인을 대체 근무 me :

double threshold=0.9 
var thresholdImage=Cv.CreateImage(newImageSize, BitDepth.F32,1); 
Cv.Threshold(result, thresholdImage, threshold, 255, ThresholdType.Binary); 
for (int r = 0; r < thresholdImage.GetSize().Height; r++) 
{ 
    for (int c = 0; c < thresholdImage.GetSize().Width; c++) 
    { 
     if (thresholdImage.GetRow(r)[c].Val0 > 0) 
     { 
      Cv.Rectangle(soruceColour, Cv.Point(c, r), Cv.Point(c + template.Width, r + template.Height), CvColor.Red, 1, 0, 0); 
     } 
    } 
} 
0

여기서는 Min_Max 및 Match_Template 방법을 사용하는 솔루션입니다. 도움이되기를 바랍니다.

public void multipleTemplateMatch(string SourceImages, string tempImage) 
    {    
     Image<Bgr, byte> image_source = new Image<Bgr, byte>(SourceImages); 
     Image<Bgr, byte> image_partial1 = new Image<Bgr, byte>(tempImage); 

     double threshold = 0.9; 
     ImageFinder imageFinder = new ImageFinder(image_source, image_partial1, threshold); 
     imageFinder.FindThenShow(); 

    } 

그리고 여기에 도움이되는 클래스가 있습니다.

class ImageFinder 
{ 
    private List<Rectangle> rectangles; 
    public Image<Bgr, byte> BaseImage { get; set; } 
    public Image<Bgr, byte> SubImage { get; set; } 
    public Image<Bgr, byte> ResultImage { get; set; } 
    public double Threashold { get; set; }   

    public List<Rectangle> Rectangles 
    { 
     get { return rectangles; } 
    } 

    public ImageFinder(Image<Bgr, byte> baseImage, Image<Bgr, byte> subImage, double threashold) 
    { 
     rectangles = new List<Rectangle>();    
     BaseImage = baseImage; 
     SubImage = subImage; 
     Threashold = threashold;    
    } 

    public void FindThenShow() 
    { 
     FindImage(); 
     DrawRectanglesOnImage(); 
     ShowImage(); 
    } 

    public void DrawRectanglesOnImage() 
    { 
     ResultImage = BaseImage.Copy(); 
     foreach (var rectangle in this.rectangles) 
     { 
      ResultImage.Draw(rectangle, new Bgr(Color.Blue), 1); 
     } 
    } 

    public void FindImage() 
    {   
     rectangles = new List<Rectangle>();   

     using (Image<Bgr, byte> imgSrc = BaseImage.Copy()) 
     { 
      while (true) 
      { 
       using (Image<Gray, float> result = imgSrc.MatchTemplate(SubImage, TemplateMatchingType.CcoeffNormed)) 
       { 
        double[] minValues, maxValues; 
        Point[] minLocations, maxLocations; 
        result.MinMax(out minValues, out maxValues, out minLocations, out maxLocations); 

        if (maxValues[0] > Threashold) 
        { 
         Rectangle match = new Rectangle(maxLocations[0], SubImage.Size); 
         imgSrc.Draw(match, new Bgr(Color.Blue), -1); 
         rectangles.Add(match); 
        } 
        else 
        { 
         break; 
        } 
       } 
      } 
     }   

    } 

    public void ShowImage() 
    { 
     Random rNo = new Random(); 
     string outFilename = "matched Templates" + rNo.Next();    
     CvInvoke.Imshow(outFilename, ResultImage); 
    }  

} 

도움이된다면 투표를 유용하게 사용하십시오. 감사합니다.