我有以下内容,但我无法弄清楚如何在源图像中找到所有匹配项。
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;
}
}
}
}
我可以概述最佳匹配,而不是所有比赛。我需要以某种方式获得所有比赛。
答案 0 :(得分:2)
使用matchTemplate方法,输出图像将为您提供像素值,表示模板在此特定位置的匹配程度。在你的情况下,因为你使用了MatchTemplateMethod.SqDiff,所以值越低,匹配越好。
你的问题是,当你使用minMaxLoc函数时,你会得到你要求的东西,这是最好的匹配,在这种情况下,min)。
所有匹配都是其值低于您设置的阈值的像素。 既然我不熟悉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);
}
}
答案 1 :(得分: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);
}
}
}
答案 2 :(得分: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);
}
}
如果您觉得有用,请投票同样有用。 谢谢