如何在不必忽略异常的情况下搜索位图中的附近点?

时间:2014-02-15 03:06:50

标签: c# .net

private Point getNearestPointThatMatchesColorWithTolerance(Point i, Color color) {
    if (colorsMatchWithTolerance(haystack.GetPixel(i.X, i.Y), color)) {
        return i;
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 1, i.Y), color)) {
        return new Point(i.X + 1, i.Y);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 1, i.Y), color)) {
        return new Point(i.X - 1, i.Y);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X, i.Y - 1), color)) {
        return new Point(i.X, i.Y - 1);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X, i.Y + 1), color)) {
        return new Point(i.X, i.Y + 1);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 1, i.Y - 1), color)) {
        return new Point(i.X + 1, i.Y - 1);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 1, i.Y - 1), color)) {
        return new Point(i.X - 1, i.Y - 1);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 1, i.Y + 1), color)) {
        return new Point(i.X + 1, i.Y + 1);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 1, i.Y + 1), color)) {
        return new Point(i.X - 1, i.Y + 1);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 2, i.Y - 2), color)) {
        return new Point(i.X - 2, i.Y - 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 1, i.Y - 2), color)) {
        return new Point(i.X - 1, i.Y - 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X, i.Y - 2), color)) {
        return new Point(i.X, i.Y - 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 1, i.Y - 2), color)) {
        return new Point(i.X + 1, i.Y - 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 2, i.Y - 2), color)) {
        return new Point(i.X + 2, i.Y - 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 2, i.Y + 2), color)) {
        return new Point(i.X - 2, i.Y + 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 1, i.Y + 2), color)) {
        return new Point(i.X - 1, i.Y + 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X, i.Y + 2), color)) {
        return new Point(i.X, i.Y + 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 1, i.Y + 2), color)) {
        return new Point(i.X + 1, i.Y + 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 2, i.Y + 2), color)) {
        return new Point(i.X + 2, i.Y + 2);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 2, i.Y + 1), color)) {
        return new Point(i.X + 2, i.Y + 1);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 2, i.Y), color)) {
        return new Point(i.X + 2, i.Y);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X + 2, i.Y - 1), color)) {
        return new Point(i.X + 2, i.Y - 1);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 2, i.Y - 1), color)) {
        return new Point(i.X - 2, i.Y - 1);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 2, i.Y), color)) {
        return new Point(i.X - 2, i.Y);
    } else if (colorsMatchWithTolerance(haystack.GetPixel(i.X - 2, i.Y + 1), color)) {
        return new Point(i.X - 2, i.Y + 1);
    } else {
        return Point.Empty;
    }
}

此方法存在两个问题:

  1. 它有大量的代码重复。
  2. 我有时会收到ArgumentOutOfRange错误,因为传递给haystack.GetPixel()的参数超出了Bitmap haystack的范围。我可以添加边界检查,但这将对第1点中讨论的代码重复做出更多贡献。
  3. 如何在不忽略异常的情况下解决此问题?

2 个答案:

答案 0 :(得分:1)

只要找不到匹配项,您就可以准备一系列轮班,然后迭代它:

public int[][] _shifts = {
    new [] { 0, 0 },
    new [] { 1, 0 }, new [] { -1, 0 }, new [] { 0, -1 }, new [] { 0, 1 }
    // (...)
};

private Point getNearestPointThatMatchesColorWithTolerance(Point i, Color color)
{
    var match = _shifts.Select(s => new Point(i.X + s[0], i.Y + s[1]))
                       .FirstOrDefault(s => colorsMatchWithTolerance(haystack.GetPixel(s.X, s.y), color));
    return match ?? Point.Empty;
}

要解决异常问题,您可以使用Where条件轻松扩展它:

private Point getNearestPointThatMatchesColorWithTolerance(Point i, Color color)
{
    var maxX = haystack.GetMaxX();
    var maxY = haystack.GetMaxY();

    var match = _shifts.Select(s => new Point(i.X + s[0], i.Y + s[1]))
                       .Where(s => s.X >= 0 && s.X <= maxX)
                       .Where(s => s.Y >= 0 && s.Y <= maxY)
                       .FirstOrDefault(s => colorsMatchWithTolerance(haystack.GetPixel(s.X, s.Y), color));

    return match ?? Point.Empty;
}

答案 1 :(得分:1)

请尝试以下方法。它避免了代码重复和ArgumentOutOfRange异常。逻辑检查从上下/左右顺序中心点的距离增加点。

private Point getNearestPointThatMatchesColorWithTolerance(Point i, Color color) {

    for (int distance = 0; distance <= 2; distance++)
    {
        for (int x = i.X - distance; x <= i.X + distance; x++)
        {
            for (int y = i.Y - distance; y <= i.Y + distance; y++)
            {
                if (x < 0 || y < 0 || x >= haystack.Width || y >= haystack.Height)
                {
                    continue;
                }

                if (distance == 0 || i.Y - y == distance || y - i.Y == distance)
                {   // just borders need to be tested
                    if (colorsMatchWithTolerance(haystack.GetPixel(x, y), color))
                    {
                        return new Point(x, y);
                    }
                }
            }
        }
    }

    return Point.Empty;
}

请注意,无需预先构建数组,您可以轻松更改中心点的距离以找到匹配项。