网上没找到C#版的去重算法,全都是Python的,也无法验证是否有效,直接自己写一个。
原理很简单,如下图所示:
如果重合距离为1,则最佳匹配结果(绿色)周围最多可能有8个重复对象;
如果重合距离为2,则最佳匹配结果(绿色)周围最多可能有24个重复对象;
以此类推。。。
所以通过判断循环匹配结果A附近指定距离nearDist是否有其他匹配结果B、C、D,有的话则跳过,从而筛选出真正的匹配结果。 通过nearDist调整筛选范围,单位为像素。
请注意此算法只经过简单验证,实际使用可能需要继续完善。
using Point = OpenCvSharp.Point;
public void MatchFilter(Mat mat, double score, out double[] scores, out Point[] poss, double nearDist = 3)
{
List<double> scores1 = new List<double>();
List<double> scores2 = new List<double>();
List<Point> poss1 = new List<Point>();
List<Point> poss2 = new List<Point>();
while (true)
{
Point minloc, maxloc;
double minval, maxval;
Cv2.MinMaxLoc(mat, out minval, out maxval, out minloc, out maxloc, null);
if (maxval >= score)
{
scores1.Add(maxval);
poss1.Add(maxloc);
Cv2.FloodFill(mat, maxloc, new Scalar());
}
else
{
break;
}
//Thread.Sleep(5);
}
List<int> compared = new List<int>();
for (int i = 0; i < poss1.Count; i++)
{
if (compared.Contains(i))
{
continue;
}
Point p = poss1[i];
scores2.Add(scores1[i]);
poss2.Add(poss1[i]);
for (int j = i + 1; j < poss1.Count; j++)
{
//if (Math.Abs(poss1[j].X - p.X) <= nearDist && poss1[j].Y == p.Y)
//{
// compared.Add(j);
//}
//else if (Math.Abs(poss1[j].Y - p.Y) <= nearDist && poss1[j].X == p.X)
//{
// compared.Add(j);
//}
if (Math.Abs(poss1[j].X - p.X) <= nearDist && Math.Abs(poss1[j].Y - p.Y) <= nearDist - 1)
{
compared.Add(j);
}
else if (Math.Abs(poss1[j].Y - p.Y) <= nearDist && Math.Abs(poss1[j].X - p.X) <= nearDist - 1)
{
compared.Add(j);
}
}
}
scores = scores2.ToArray();
poss = poss2.ToArray();
}