OpenCv: Finding multiple matches

心不动则不痛 提交于 2019-12-03 20:42:36

Using matchTemplate method, your output image will give you pixels values which represents how well your template is matched at this specific location. In you case, the lower the value, the best the match, since you used MatchTemplateMethod.SqDiff.

You problem is that when you use the minMaxLoc function, you get what you asks for, which is the best match in this case, the min).

All matches are the pixels whose value are under the threshold that you set up. Since I'm not used to csharp, here is how it would go in C++, you can do the translation:

// 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);
  }
}

Translating from C++ and using OpenCvSharp wrapper, the above code, replacing minMaxLoc lines, worked for 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);
        }
    }
}

here is the solution using Min_Max and Match_Template methods. hope it will help.

 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();

    }   

and here is the class which will help.

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);
    }     

}

if you find this helpful please vote is as useful. thanks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!