我正在使用EMGU和c#进行图像模板匹配。EMGU查找匹配的方法有点慢,所以我尝试遍历图像(2D数组)来查找匹配。它工作得很好,非常快。但由于某种原因,它会在同一位置找到多个匹配的相同模板,并在其上绘制多次。例如,如果在我的图像中有4个给定模板的匹配,它将为这4个匹配的每个匹配区域绘制10个矩形,因此矩形厚度增加并且总匹配计数永远不会正确。
代码如下:
for (int y = 0; y < Matches.Data.GetLength(0); y++)
{
for (int x = 0; x < Matches.Data.GetLength(1); x++)
{
if (Matches.Data[y, x, 0] >= Threshold) //Set at 0.9
{
Rectangle r = new Rectangle(new Point(x, y), template.Size);
CvInvoke.Rectangle(imgres, r, new MCvScalar(255, 0, 0), 1, LineType.EightConnected, 0);
listBox1.Items.Add(r.Size); // more than 80 rectangles are drawn for 4 matches
}
}
}
如何在找到每个匹配项一次后停止迭代?
可以使用break;但这在嵌套循环中会很快变得混乱。
让我们从到循环快,它们的结构是这样的:
for (declaration; condition; execute after)
{
// code block
}
由于中间部分是一个简单的条件,您可以添加另一个条件,表明它已完成(或仍在搜索)。在这个例子中只是一个布尔值:
bool stillSearching = true;
for (int i = 0; i < 100 && stillSearching; i++)
{
if (i > 50) //You found your match
{
stillSearching = false;
}
}
这将简单地计数到51,然后如果设置boolean到假.然后返回for循环,执行i++.然后检查这两个条件:我& lt;100仍然是正确的stillSearching是假的
由于&&整个条件为false然后循环停止
编辑:因为我不确定你需要满足什么条件,所以我只添加一个if
bool searching = true;
for (int y = 0; y < Matches.Data.GetLength(0) && searching; y++)
{
for (int x = 0; x < Matches.Data.GetLength(1) && searching; x++)
{
if (Matches.Data[y, x, 0] >= Threshold)
{
Rectangle r = new Rectangle(new Point(x, y), template.Size);
CvInvoke.Rectangle(imgres, r, new MCvScalar(255, 0, 0), 1, LineType.EightConnected, 0);
listBox1.Items.Add(r.Size);
}
if ( /*your condtion here*/ )
{
searching = false;
}
}
}
使用return
语句
为了保持整洁,将循环和操作保持在单独的短方法中。
for (int y = 0; y < Matches.Data.GetLength(0); y++)
{
for (int x = 0; x < Matches.Data.GetLength(1); x++)
{
if (Matches.Data[y, x, 0] >= Threshold)
{
DoSomethingWithMatch(x, y);
return;
}
}
}
另外,出于性能原因,不应该在循环中访问c#属性。首先将Matches.Data
保存在一个变量中,然后遍历该变量。
你可以使用break
跳出循环,但它只能让你跳出最近的循环。解决这个问题的方法是设置flag来指示是否应该跳出外部循环。考虑以下内容:
for (int y = 0; y < Matches.Data.GetLength(0); y++)
{
bool matchFound = false;
for (int x = 0; x < Matches.Data.GetLength(1); x++)
{
if (Matches.Data[y, x, 0] >= Threshold) //Set at 0.9
{
Rectangle r = new Rectangle(new Point(x, y), template.Size);
CvInvoke.Rectangle(imgres, r, new MCvScalar(255, 0, 0), 1, LineType.EightConnected, 0);
listBox1.Items.Add(r.Size); // more than 80 rectangles are drawn for 4 matches
matchFound = true;
break;
}
}
if(matchFound)
{
break;
}
}