简体   繁体   English

在二维 NumPy 数组中查找重叠矩形的中心

[英]Finding the centers of overlapping rectangles in 2d NumPy array

I have a 2D NumPy array with several potentially overlapping rectangles of variable size.我有一个 2D NumPy 数组,其中有几个可能重叠的可变大小的矩形。 How can I compute the coordinates of the centers of each rectangle?如何计算每个矩形中心的坐标? In the attached image, my objective is to compute the coordinates of the red dots.在附图中,我的目标是计算红点的坐标。

The array is all zeros, except for the pixels that indicate the rectangle borders, which have value one.该数组全为零,但指示矩形边框的像素除外,其值为 1。 In the example image, the black pixels have value zero, and the white pixels have value one.在示例图像中,黑色像素的值为 0,白色像素的值为 1。

在此处输入图像描述

Search the image row by row, starting from the (0, 0) corner.从 (0, 0) 角开始逐行搜索图像。 The first nonzero pixel that you encounter must be the top left corner of a rectangle.您遇到的第一个非零像素必须是矩形的左上角。 Follow the pixels to the right until you hit the top right corner, then down, then left, and finally up again.按照像素向右移动,直到到达右上角,然后向下,然后向左,最后再次向上。 If you end up at the same pixel as where you started, it was a full rectangle.如果您最终的像素与开始的像素相同,则它是一个完整的矩形。

Keep track of all pixels that were identified as being part of a rectangle, so that you won't trace them again.跟踪所有被识别为矩形一部分的像素,这样您就不会再次跟踪它们。

Edit: A requirement for this algorithm is that the corners of different rectangles don't touch each other.编辑:此算法的要求是不同矩形的角不相互接触。 With 3-pixel-wide borders, the algorithm will trace the outer pixels of the rectangle.对于 3 像素宽的边框,该算法将跟踪矩形的外部像素。 It will also attempt to trace the two 1-pixel wide rectangles inside the outer one, but these are discarded.它还将尝试跟踪外部矩形内的两个 1 像素宽的矩形,但这些矩形被丢弃。

import numpy as np
import matplotlib.pyplot as plt

def search_rectangles(img):
    """Search rectangles in 2D boolean image array.
    
    Return: rectangles - array shape (n, 3, 2) for n rectangles.
       rectangles[i, 0, :] represents the top left corner [i, j]
       recnangles[i, 1, :] represents the bottom right corner [i, j]
       rectangles[i, 2, :] represents the center (rounded as integer).
    """
    
    seen = np.zeros_like(img, dtype=np.bool)
    ny, nx = img.shape
    rectangles = []
    
    for i in range(ny):
        for j in range(nx):
            if img[i, j] == 0 or seen[i, j]:
                continue
            # new rectangle pixel; assume it's the top left corner.
            # follow it clockwise.
            didjs = [(0, 1), (1, 0), (0, -1), (-1, 0)]
            ii, jj = i, j
            corners = np.array([[i, j], [-1, -1], [-1, -1]])
            for k, (di, dj) in enumerate(didjs):
                if k == 2:
                    # opposite corner
                    corners[1, :] = [ii, jj]
                while img[ii+di, jj+dj]:
                    ii += di
                    jj += dj
                    seen[ii, jj] = True
            if (ii, jj) == (i, j):
                corners[2, :] = np.around(corners[:2, :].mean(axis=1))
                rectangles.append(corners)
    
    return np.array(rectangles)

def draw_rectangle(img, i0, i1, j0, j1):
    """Draw rectangle with 3px border width."""
    img[i0:i1+1, j0:j0+3] = 1
    img[i0:i1+1, j1-2:j1+1] = 1
    img[i0:i0+3, j0:j1+1] = 1
    img[i1-2:i1+1, j0:j1+1] = 1


# test case
img = np.zeros((100, 150), dtype=np.uint8)
draw_rectangle(img, 10, 40, 20, 50)
draw_rectangle(img, 15, 34, 25, 44)
draw_rectangle(img, 20, 70, 70, 90)
draw_rectangle(img, 50, 90, 75, 120)

plt.close('all')
plt.imshow(img)
print(search_rectangles(img))

Output: Output:

重叠的矩形

[[[ 10  20]
  [ 40  50]
  [ 15  45]]

 [[ 15  25]
  [ 34  44]
  [ 20  39]]

 [[ 20  70]
  [ 70  90]
  [ 45  80]]

 [[ 50  75]
  [ 90 120]
  [ 62 105]]]

It depends on the information you have.这取决于您拥有的信息。

If you have the coordinates of the bottom left and top right corners, then the center will be the average between the two.如果你有左下角和右上角的坐标,那么中心将是两者之间的平均值。

If you have one corner and the dimensions, then you can just move from the corner to the center using half the dimensions.如果您有一个角和尺寸,那么您可以使用一半尺寸从角移动到中心。

import numpy as np

# Bottom left and top right
bl = np.array([1, 0])
tr = np.array([2, 1])

center = np.mean((bl, tr), axis = 0)

# Bottom left corner and dimensions

bl = np.array([1, 0])
dimensions = np.array([1, 1])

center = bl + 0.5 * dimensions

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM