【问题标题】:'draw' a random rhombus (diamond) on a numpy array (testing harris corner detection)在 numpy 数组上“绘制”一个随机菱形(菱形)(测试哈里斯角检测)
【发布时间】:2021-03-22 07:53:48
【问题描述】:

我正在尝试为“harris_corner_detector”函数实现创建一个随机测试(非常普遍且略微不正确:在图像中找到角点的函数) 在测试中,我想在二进制 numpy 矩阵中创建随机简单的形状(很容易知道它们的角的坐标)(例如矩形、三角形、菱形(菱形)等......)并检查 harris 实现是否找到正确的角落。

我已经实现了一个随机“绘制”轴平行矩形的函数,但是当涉及到不平行于轴的形状时,我找不到有效的方法。

为了创建一个随机矩形,我在两个轴上随机选择一个起点和一个终点,然后更改这些边界内所有单元格的值,如下所示:

获取随机坐标:

    def _get_random_coords(self, start, end):
        x_start, y_start = np.random.randint(start, end, 2)
        x_end = np.random.randint(x_start + 7, end + 20)
        y_end = np.random.randint(y_start + 7, end + 20)
        return (x_start, x_end, y_start, y_end)

绘制随机矩形(背景值为 255,形状为 0):

mat = np.ones((1024, 1024)) * 255
mat[x_start: x_end, y_start: y_end] = np.zeros((x_end - x_start, y_end - y_start))

但是当谈到有效地绘制菱形时,我不知所措。我能想到的就是运行一个像这样创建钻石的循环:

    def _get_rhombus(self, size):
        rhombus = []
        for i in range(size):
            rhombus.append(np.zeros(i+1))
        for i in range(size - 1, 0, -1):
            rhombus.append(np.zeros(i))
        return np.array(rhombus)

然后另一个循环将其添加到更大的矩阵中。 但是这种方法在测试时效率非常低(我会画数百个,其中一些可能很大)。

还有更好的想法吗?或者 - 有没有更好的方法来测试这个?

提前致谢。

【问题讨论】:

  • 你可以创建一个随机的矩形,然后取其边的中点作为菱形的顶点。
  • 这是个好主意!但我仍然面临主要问题 - 有效地绘制它。 (除非我理解错了)

标签: python numpy testing draw corner-detection


【解决方案1】:

这里有很多问题,但主要问题是如何在给定角的情况下创建一个填充菱形的 numpy 数组。我会回答这个问题,并留下其他问题,例如创建随机菱形等。

要填充凸多边形,可以找到由后续角指定的线并填充该线的上方或下方,然后and所有填充区域一起。

import numpy as np
import matplotlib.pyplot as plt

# given two (non-vertical) points, A and B, 
# fill above or below the line connecting them
def fill(A, B, fill_below=True, xs=10, ys=12):

    # the equation for a line is y = m*x + b, so calculate
    # m and b from the two points on the line
    m = (B[1]-A[1])/(B[0]-A[0]) # m = (y2 - y1)/(x2 - x1) = slope
    b = A[1] - m*A[0]           # b = y1 - m*x1 = y intercept

    # for each points of the grid, calculate whether it's above, below, or on
    # the line. Since y = m*x + b, calculating m*x + b - y will give
    # 0 when on the line, <0 when above, and >0 when below
    Y, X = np.mgrid[0:ys, 0:xs] 
    L = m*X + b - Y

    # select whether, >=0 is True, or, <=0 is True, to determine whether to
    # fill above or below the line
    op = np.greater_equal if fill_below else np.less_equal
    return op(L, 0.0)

这是一个简单的低分辨率菱形

r = fill((0, 3), (3, 8), True) & \
fill((3, 8), (7, 4), True) & \
fill((7,4), (5,0), False) & \
fill((5,0), (0,3), False)
plt.imshow(r, cmap='Greys',  interpolation='nearest', origin='lower')

即上图是下面的填充和-ing在一起的结果:

fig, ax = plt.subplots(1, 4, figsize=(10, 3))
fill_params = [((0, 3), (3, 8), True), ((3, 8), (7, 4), True), ((7, 4), (5, 0), False), ((5, 0), (0, 3), False)]
for p, ax in zip(fill_params, ax):
    ax.imshow(fill(*p), cmap="Greys", interpolation='nearest', origin='lower')

或者,一个可以做高分辨率,它可以有多个侧面(虽然我认为它必须是凸面的)。

r = fill((0, 300), (300, 800), True, 1000, 1200) & \
fill((300, 800), (600,700), True, 1000, 1200) & \
fill((600, 700), (700, 400), True, 1000, 1200) & \
fill((700,400), (500,0), False, 1000, 1200) & \
fill((500,0), (100,100), False, 1000, 1200) & \
fill((100, 100), (0,300), False, 1000, 1200)
plt.imshow(r, cmap='Greys',  interpolation='nearest', origin='lower')

显然,有一些地方需要改进,比如不重复行的第二个点和新行的第一个点,但我想让这一切保持干净和简单(而且,为了让填充工作点只需要定义一条线而不需要是一个角,因此在某些情况下,这种更通用的方法可能更可取)。另外,目前需要指定是在线条上方还是下方填充,这可以通过多种方式计算,但在生成菱形时可能最容易。

【讨论】:

  • 这正是我想要的。真的很优雅,做工精良!我还没有完全理解它,但它工作得很好:) 现在我将慢慢回顾所有的实现,以更好地理解它并满足我的需要。非常感谢!
  • 太棒了。我在我的代码中添加了一些 cmets,希望能阐明它在做什么。
  • 我自己已经完成了,但我相信 cmets 会帮助那些偶然发现我的问题的人。非常感谢!
【解决方案2】:

虽然比已经发布的答案略逊一筹,但这是使用上下三角矩阵概念形成菱形的巧妙技巧

import numpy as np
import matplotlib.pyplot as plt

blank = np.zeros((10, 12))

anchorx, anchory = 2, 3
# better result for odd dimensions, because mid index exists
# can handle h != w but the rhombus would still fit to a square of dimension min(h, w) x min(h, w)
h, w = 7, 7

assert anchorx+h <= blank.shape[0], "Boundaries exceed, maintain 'anchorx+h <= blank.shape[0]' "
assert anchory+w <= blank.shape[1], "Boundaries exceed, maintain 'anchory+w <= blank.shape[1]' "

tri_rtc = np.fromfunction(lambda i, j: i >= j, (h // 2 + 1, w // 2 + 1), dtype=int)
tri_ltc = np.flip(tri_rtc, axis=1)

rhombus = np.vstack((np.hstack((tri_ltc, tri_rtc[:, 1:])), np.flip(np.hstack((tri_ltc, tri_rtc[:, 1:])), axis=0)[1:, :]))
blank[anchorx:anchorx+h, anchory:anchory+w] = rhombus

print(blank)
plt.imshow(blank)
plt.show()
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 0.]
 [0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 0. 0.]
 [0. 0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 1. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]

【讨论】:

  • 我也会调查一下!感谢您花时间发布您的解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-06
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多