代码之家  ›  专栏  ›  技术社区  ›  Flash Thunder

用numpy对点数组进行排序

  •  0
  • Flash Thunder  · 技术社区  · 7 年前

    我得到了如下声明的一系列点:

    found = np.empty(img_rgb.shape[:2])
    

    它表示OpenCV模板匹配中的值。 由于我只保留了匹配中具有所需值的点,所以我在迭代之前重写了它:

    found2 = np.where(found)
    

    现在我像这样重复它:

    for pt in zip(*found2[::-1]):
        (x, y) = pt
    

    但是我如何对它进行排序,以便它在 found[x][y] 大堆

    我试过了 np.argsort() 但似乎没有一个合适的x,y索引。事实上,我猜它根本不按值排序。

    编辑:要清楚:

    img_rgb = cv2.imread(os.path.join(DATA_DIR, 'some.png'))
    
    (...)
    
    res = cv2.matchTemplate(img_gray, tmpl, cv2.TM_CCOEFF)
    loc = np.where(res > 230000)
    for pt in zip(*loc[::-1]):
       (x, y) = pt
       found[y][x] = -res[y][x]
    
    0 回复  |  直到 7 年前
        1
  •  2
  •   alkasm Anuj Gautam    7 年前
    res = cv2.matchTemplate(img_gray, tmpl, cv2.TM_CCOEFF)
    count = np.sum(res > 230000)
    y, x = np.unravel_index((-res).argsort(None), res.shape)
    for row, col in zip(y[:count], x[:count]):
        print(res[row, col], (row, col))
    

    每一行的解释:

    count = np.sum(res > 230000)
    

    获取要迭代的值的总数。

    y, x = np.unravel_index((-res).argsort(None), res.shape)
    

    在这里 argsort(None) 将线性索引返回到对其进行排序的数组中。但是我们需要(行、列)索引,而不是线性索引,所以我们使用 np.unravel_index() 获取2d索引。使用结果的负数从最大值排序到最小值,就像你在OP中做的那样。

    最后,我们可以迭代这些点:

    for row, col in zip(y[:count], x[:count]):
        print(res[row, col], (row, col))
    

    打印只是为了表明我们确实首先得到了最高值,并显示了相应值的(行、列)索引。


    例子:

    >>> import cv2
    >>> import numpy as np
    >>> img = np.uint8(255*np.random.rand(100, 100))
    >>> tmp = np.uint8(255*np.random.rand(10, 10))
    >>> res = cv2.matchTemplate(img, tmp, cv2.TM_CCOEFF)
    >>> count = np.sum(res > 100000)
    >>> y, x = np.unravel_index((-res).argsort(None), res.shape)
    >>> for row, col in zip(y[:count], x[:count]):
    >>>     print(res[row, col], (row, col))
    206337.11 (19, 12)
    177079.31 (76, 9)
    173258.67 (63, 15)
    ...
    100202.44 (56, 1)
    100098.41 (0, 48)
    100089.09 (68, 47)
    

    请注意,这些最终值是(行、列)顺序,也就是说,与(x、y)点顺序相反,所以可以根据需要进行交换。

        2
  •  1
  •   Paul Panzer    7 年前

    我不确定我是否正确理解你,但你想要这样的东西吗:

    found = np.random.randint(0, 10, (3, 4))
    found2 = np.where(found)
    found
    # array([[5, 6, 8, 6],
    #        [0, 7, 7, 3],
    #        [7, 6, 0, 5]])
    found2
    # (array([0, 0, 0, 0, 1, 1, 1, 2, 2, 2]), array([0, 1, 2, 3, 1, 2, 3, 0, 1, 3]))
    
    order = found[found2].argsort()
    x, y = found2[1][order], found2[0][order]
    found[y, x]
    # array([3, 5, 5, 6, 6, 6, 7, 7, 7, 8])
    

    这会对二维索引进行排序 found2 根据中各点的值 found 他们提到。

        3
  •  1
  •   fountainhead    7 年前

    解决方案:

    sorted_pts = sorted(zip(*loc), key=lambda t:res[t])
    print (sorted_pts)
    

    使用示例数据进行尝试:

    让我们以较小的规模采集一些样本数据(以 res 只是一个形状 (3,4) 数组,以及 4 作为 threshold ):

    import numpy as np
    
    res = np.arange(12).reshape(3,4)
    print (res)
    
    loc = np.where(res > 4)  # Dummy threshold == 4
    
    sorted_pts = sorted(zip(*loc), key=lambda t:res[t[0],t[1]])
    print (sorted_pts)
    

    输出:

    [[ 0  1  2  3]   # res
     [ 4  5  6  7]
     [ 8  9 10 11]]
    # sorted_pts
    [(1, 1), (2, 1), (3, 1), (0, 2), (1, 2), (2, 2), (3, 2)]
    

    注: (验证是否根据中的值对点进行了排序。) 物件 )

    [(1, 1), (2, 1), (3, 1), (0, 2), (1, 2), (2, 2), (3, 2)]
       |       |       |        |       |       |       |
       |       |       |        |       |       |       |
       V       V       V        V       V       V       V
       5       6       7        8       9       10      11