2012-09-08 148 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); 
    }  

} 

如果您覺得這有幫助請投票同樣有用。 謝謝