numpy 如何在YOLOP中对可行驶区域进行分组

b5buobof  于 2023-03-30  发布在  其他
关注(0)|答案(1)|浏览(76)

在YOLOP上,我可以毫无问题地检测车道和可行驶区域。数据来自 Torch 模型,并存储为2D numpy数组,如下所示:

[[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]
 [0 0 0 ... 0 0 0]]

这个2D numpy数组只存储对应于非可驱动区域和可驱动区域的0和1。
我的问题在这里开始了。我必须将这3个不同的可行驶区域的车道分成单独的组(数组),这样我就可以使用所需的可行驶区域only. For example...
因此,当我决定只显示drivableLane[0]时,应该会得到类似this.的输出
一开始我试着一个接一个地迭代整个2D数组并存储可行驶区域坐标,但这是一个坏主意,因为这个操作太慢了。我还想出了DBSCAN和BIRCH聚类算法,但最后,我搞砸了。
我会很感激听到一个想法!

wlwcrazw

wlwcrazw1#

给出您提供的示例图像:

from PIL import Image
import requests
from io import BytesIO
import numpy as np
import matplotlib.pyplot as plt

url = 'https://i.stack.imgur.com/zyzIJ.png'
response = requests.get(url)
img = Image.open(BytesIO(response.content))
img = np.array(img)
plt.imshow(img)
plt.show()

其中,我们将图像的RGB(A)值表示为numpy矩阵:

fig = plt.figure(figsize=(15, 5))
ax = plt.subplot(1, 3, 1)
plt.imshow(img[300:800, 300:600, :3])
ax.set_title('Zoom in')
ax = plt.subplot(1, 3, 2)
plt.imshow(img[400:600, 300:600, :3])
ax.set_title('Zoom in more')
ax = plt.subplot(1, 3, 3)
plt.imshow(img[450:550, 400:500, :3])
for r in range(10, img[450:550, 400:500, :3].shape[0] - 20, 20):
    for c in range(10, img[450:550, 400:500, :3].shape[1], 20):
        ax.text(r, c, str(np.round(np.mean(img[r, c, :]), decimals=0)))
ax.set_title('Perfect... now show the values')
plt.show()

你说的已经是01的了(这很棒!甚至更容易),我们可以根据不重叠的可行驶区域的rowcolumn索引来制作1的矩阵。
让我们在这里可视化它:

import numpy as np
import matplotlib.pyplot as plt
def draw_shape(ax, x, y, size, layers, layer_colors, layer_alpha, **kwargs):
    for layer in range(layers):
        for line in range(size + 1):
            ax.plot(np.ones(10)*x + line + layer, np.linspace(y + layer, y + size + layer, 10), color=[0, 0, 0], **kwargs)
            ax.plot(np.linspace(y + layer, y + size + layer, 10), np.ones(10)*x + line + layer, color=[0, 0, 0], **kwargs)
            if line < 3:
                for row in range(size):
                    ax.text(x + line + layer + (size / 2.5) - 1.0, y + layer + (size / 2) - 1.0 + row, '[' + str(row + x) + ', ' + str(line) + ']')
        ax.fill_between(range(layer, size + layer + 1), x + layer, x + size + layer, color=layer_colors[layer], alpha=layer_alpha)

fig = plt.figure(figsize=(17, 5))
ax = plt.subplot(1, 3, 1)
draw_shape(ax, 0, 0, 3, 1, [[1, 1, 1]], 1.0, lw=2.5, ls='-')
draw_shape(ax, 2.0, 2.0, 3, 1, [[1, 1, 1]], 1.0, lw=2.5, ls='-')
ax.axis('off')
ax = plt.subplot(1, 3, 2)
draw_shape(ax, 0, 0, 3, 1, [[1, 1, 1]], 1.0, lw=2.5, ls='-')
draw_shape(ax, 2.5, 2.5, 3, 1, [[1, 1, 1]], 1.0, lw=2.5, ls='-')
ax.axis('off')
ax = plt.subplot(1, 3, 3)
draw_shape(ax, 0, 0, 3, 1, [[1, 1, 1]], 1.0, lw=2.5, ls='-')
draw_shape(ax, 3.1, 3.1, 3, 1, [[1, 1, 1]], 1.0, lw=2.5, ls='-')
ax.axis('off')
plt.show

我们可以通过检查图像中的相邻位置是否也是可行驶区域(1)来区分边界:

for row in range(img.shape[0]):
    for col in range(img.shape[1]):
        if img[row, col] == 1.0:
            # here is where the rules go:
            # example: if there's at least one neighboring '1.0':
            if any([img[max(0, row - 1), col], img[row, max(0, col - 1)], img[max(0, row - 1), max(0, col - 1)], img[min(img.shape[0] - 1, row + 1), col], img[row, min(img.shape[1] - 1, col + 1)], img[min(img.shape[0] - 1, row + 1), min(img.shape[1] - 1, col + 1)]]):
                ...

我们还可以区分图像中可驾驶区域的边界(1)(或者如果你想拥有图像中“背景”或不可驾驶区域的矩阵):

for row in range(img.shape[0]):
    for col in range(img.shape[1]):
        if img[row, col] == 1.0:
            # here is where the rules go:
            # example: if there's at least one neighboring '1.0':
            if any([img[max(0, row - 1), col], img[row, max(0, col - 1)], img[max(0, row - 1), max(0, col - 1)], img[min(img.shape[0] - 1, row + 1), col], img[row, min(img.shape[1] - 1, col + 1)], img[min(img.shape[0] - 1, row + 1), min(img.shape[1] - 1, col + 1)]]):
                ...
        else:
            # get borders:
            if any([img[max(0, row - 1), col], img[row, max(0, col - 1)], img[max(0, row - 1), max(0, col - 1)], img[min(img.shape[0] - 1, row + 1), col], img[row, min(img.shape[1] - 1, col + 1)], img[min(img.shape[0] - 1, row + 1), min(img.shape[1] - 1, col + 1)]]):
                ...
            # get background:
            else:
                ...

例如,如果我们有0a矩阵,并用1填充左上角:

import numpy as np
a = np.reshape(np.zeros(16), [4, 4])
a[:2, :2] = 1.0

print(a)

[[1. 1. 0. 0.]
 [1. 1. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]

我们可以区分1和它们的邻居(0)的位置:

for row in range(a.shape[0]):
    for col in range(a.shape[1]):
        if a[row, col] == 1.0:
            if any([a[max(0, row - 1), col], a[row, max(0, col - 1)], a[max(0, row - 1), max(0, col - 1)], a[min(a.shape[0] - 1, row + 1), col], a[row, min(a.shape[1] - 1, col + 1)], a[min(a.shape[0] - 1, row + 1), min(a.shape[1] - 1, col + 1)]]):
                print('equals 1:', str(row), str(col))
        else:
            if any([a[max(0, row - 1), col], a[row, max(0, col - 1)], a[max(0, row - 1), max(0, col - 1)], a[min(a.shape[0] - 1, row + 1), col], a[row, min(a.shape[1] - 1, col + 1)], a[min(a.shape[0] - 1, row + 1), min(a.shape[1] - 1, col + 1)]]):
                print('Neighbor:', str(row), str(col))
            else:
                print('Background:', str(row), str(col))

a矩阵(0的)或“image”数组中获取这个“正方形对象”(1的)的位置(rowcolumn):

equals 1: 0 0
equals 1: 0 1
Neighbor: 0 2
Background: 0 3
equals 1: 1 0
equals 1: 1 1
Neighbor: 1 2
Background: 1 3
Neighbor: 2 0
Neighbor: 2 1
Neighbor: 2 2
Background: 2 3
Background: 3 0
Background: 3 1
Background: 3 2
Background: 3 3

现在,如果a有多个可驱动区域:

a = np.reshape(np.zeros(200), [10, 20])
a[:, 2:4] = 1.0
a[:, -4:-2] = 1.0
a[:2, 4] = 1.0
a[:3, -5] = 1.0

它看起来像print(a)

[[0. 0. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 1. 0. 0.]
 [0. 0. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 1. 0. 0.]
 [0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 1. 0. 0.]
 [0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0.]
 [0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0.]
 [0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0.]
 [0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0.]
 [0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0.]
 [0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0.]
 [0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0.]]

plt.imshow(a)

我们想把这些1分割成单独的list(这个例子使用嵌套的list而不是矩阵更容易表达),我们可以使some_lists_in_dict包含每个可驱动区域。(按顺序编号表示为strkeys中)和其valuesrowcolumnlist s;作为一个字典,每个“新的”可驾驶区域将被插入作为一个新的列表,在它被区分的顺序,和rowcolumn值将与所有可驾驶区域进行比较(附加到预先存在的list s,如果它is_part_of该可驾驶区域,或成为一个新的list为一个新的可驾驶区域):

some_lists_in_dict = {'0': []}

def is_part_of(x, y, some_list):
    r = [0, -1, 1]
    c = [0, -1, 1]
    if len(some_list) > 1:
        _x_list = [_x for group_x in some_list for _x in group_x][::2]
        _y_list = [_y for group_y in some_list for _y in group_y][1::2]
        for row in r:
            for col in c:
                if x + r[row] in _x_list and y + c[col] in _y_list:
                    return True
    else:
        _x_list = some_list[0][0]
        _y_list = some_list[0][1]
        for row in r:
            for col in c:
                if x + r[row] == _x_list and y + c[col] == _y_list:
                    return True
    return False

for row in range(a.shape[0]):
    for col in range(a.shape[1]):
        if a[row, col] == 1.0:
            if len(some_lists_in_dict[str(len(some_lists_in_dict.keys()) - 1)]) == 0:
                some_lists_in_dict[str(len(some_lists_in_dict.keys()) - 1)].append([row, col])
            else:
                if not any([is_part_of(row, col, some_lists_in_dict[str(_object)]) for _object, _ in some_lists_in_dict.items()]):
                    some_lists_in_dict[str(len(some_lists_in_dict.keys()))] = []
                    some_lists_in_dict[str(len(some_lists_in_dict.keys()) - 1)].append([row, col])
                else:
                    some_lists_in_dict[str(np.arange(0, len(some_lists_in_dict.keys()), 1)[[is_part_of(row, col, some_lists_in_dict[str(_object)]) for _object, _ in some_lists_in_dict.items()]][0])].append([row, col])

并且print(some_lists_in_dict)向我们表明,它正确地区分了两个可行驶区域:

{'0': [[0, 2], [0, 3], [0, 4], [1, 2], [1, 3], [1, 4], [2, 2], [2, 3], [3, 2], [3, 3], [4, 2], [4, 3], [5, 2], [5, 3], [6, 2], [6, 3], [7, 2], [7, 3], [8, 2], [8, 3], [9, 2], [9, 3]], '1': [[0, 15], [0, 16], [0, 17], [1, 15], [1, 16], [1, 17], [2, 15], [2, 16], [2, 17], [3, 16], [3, 17], [4, 16], [4, 17], [5, 16], [5, 17], [6, 16], [6, 17], [7, 16], [7, 17], [8, 16], [8, 17], [9, 16], [9, 17]]}

相关问题