2

私は次のものを持っていますが、ソース画像ですべての一致を見つける方法がわかりません。

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

すべての試合ではなく、最良の試合の概要を説明できます。どうにかしてすべての試合を取得する必要があります。

4

3 に答える 3

2

C++ から変換して OpenCvSharp ラッパーを使用すると、minMaxLoc 行を置き換える上記のコードがうまくいきました。

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);
        }
    }
}
于 2015-04-16T20:37:05.000 に答える
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);
  }
}
于 2012-09-08T07:23:52.250 に答える
1

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

}

これが役立つと思われる場合は、投票してください。ありがとう

于 2016-07-13T06:00:19.257 に答える