绘制连接不同级别边界框质心的线

发布于 2025-01-13 21:43:30 字数 1994 浏览 1 评论 0原文

我使用 Detectron2 训练了一个模型来检测建筑物图像上的窗户。 作为输出,我还得到每个窗口周围的边界框,其中包含右上角和左下角的 x、y 坐标。 输入图片这里的描述

我想从此输出中获取有关楼层数的信息。 这个想法是获取每个 bbox 的质心并在一条线上画一条连接质心的线。线路的数量意味着楼层的数量。查看所需的输出: 输入图片这里的描述

我获得了每个质心的x,y坐标,但不知道如何画线。请问,有什么想法吗?

 #for snapshot-10.png choose only bboxes for class 0 (fenster)
bbox = output['instances'][output['instances'].pred_classes==0].pred_boxes
box_cent = bbox.get_centers()
box_cent = box_cent.cpu().numpy()
#sort centroids by y-coordinates
box_cent[box_cent[:,1].argsort()]

按 y 坐标排序的输出为:

[[540.9429, 233.10698],
[406.09546, 236.09201],
[769.1001, 236.3072],
[655.85944, 236.33795],
[883.7689, 241.99356],
[998.5099, 244.86237],
[532.45764, 381.28082],
[653.0167, 386.0125],
[891.9795, 387.96347],
[1140.524, 388.55304],
[1008.31445, 390.77576],
[771.84033, 390.8385],
[390.84647, 394.80884],
[522.44476, 559.79565],
[899.99866, 560.30835],
[1022.31305, 562.9693],
[650.5117, 563.4512],
[772.411, 565.10144],
[1162.2795, 565.864],
[1269.4834, 566.28735],
[373.81348, 575.3587],
[907.84314, 768.63293],
[509.22638, 770.1798],
[643.81964, 770.6924],
[775.07874, 771.9369],
[234.46616, 775.37305],
[117.903625, 776.7884],
[350.1, 776.8995]]

UPD:我尝试了一个简单的解决方案,该解决方案对质心的 y 坐标进行聚类,但这里有一个特定的阈值。我想找到一种通用算法,可以计算楼层数,而不管窗户的高度或窗户之间的距离如何。这是我的尝试:

y_cent = []
for b in box_cent:
    (x, y) = (int(b[0]), int(b[1]))
    y_cent.append(y)

#group values of centroid y-coordinates
def cluster(array, maxdiff):
    tmp = array.copy()
    groups = []
    while len(tmp):
        # select seed
        seed = tmp.min()
        mask = (tmp - seed) <= maxdiff
        groups.append(tmp[mask, None])
        tmp = tmp[~mask]
    return groups

I trained a model with Detectron2 to detect windows on an image of building.
As output I also get bounding boxes around each window with x,y-coordinates of top-right and bottom-left corner.
enter image description here

I want to derive info about the number of floors from this output.
The idea is to get centroids of each bbox and to draw a line connecting centroids on one line. The number of lines means then the number of floors. See the desirable output:
enter image description here

I obtained x,y-coordinates of each centroid, but can't get how to draw lines. Please, any ideas?

 #for snapshot-10.png choose only bboxes for class 0 (fenster)
bbox = output['instances'][output['instances'].pred_classes==0].pred_boxes
box_cent = bbox.get_centers()
box_cent = box_cent.cpu().numpy()
#sort centroids by y-coordinates
box_cent[box_cent[:,1].argsort()]

The sorted by y-coordinates output is:

[[540.9429, 233.10698],
[406.09546, 236.09201],
[769.1001, 236.3072],
[655.85944, 236.33795],
[883.7689, 241.99356],
[998.5099, 244.86237],
[532.45764, 381.28082],
[653.0167, 386.0125],
[891.9795, 387.96347],
[1140.524, 388.55304],
[1008.31445, 390.77576],
[771.84033, 390.8385],
[390.84647, 394.80884],
[522.44476, 559.79565],
[899.99866, 560.30835],
[1022.31305, 562.9693],
[650.5117, 563.4512],
[772.411, 565.10144],
[1162.2795, 565.864],
[1269.4834, 566.28735],
[373.81348, 575.3587],
[907.84314, 768.63293],
[509.22638, 770.1798],
[643.81964, 770.6924],
[775.07874, 771.9369],
[234.46616, 775.37305],
[117.903625, 776.7884],
[350.1, 776.8995]]

UPD: I tried a simple solution which clusters y-coordinates of centroids, but there is a specific threshold here. And I would like to find an universal algorithm that counts the number of floors regardless of the height of the windows or the distance between them. Here's my try:

y_cent = []
for b in box_cent:
    (x, y) = (int(b[0]), int(b[1]))
    y_cent.append(y)

#group values of centroid y-coordinates
def cluster(array, maxdiff):
    tmp = array.copy()
    groups = []
    while len(tmp):
        # select seed
        seed = tmp.min()
        mask = (tmp - seed) <= maxdiff
        groups.append(tmp[mask, None])
        tmp = tmp[~mask]
    return groups

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

葬シ愛 2025-01-20 21:43:30

我尝试了一下,这就是我的想法。它不是世界上最好的算法,但它可以完成工作。但请记住,它仅在照片直立时才有效。

# you don't have to do that if the list is already sorted
windows = sorted(windows, key = lambda x: x[1]) 

thresshold = 30
floors_amount = 0

while windows:
    for w in windows[1:].copy():
        if w[1] - windows[0][1] > thresshold:
            break
        windows.remove(w)
    windows.remove(windows[0])
    floors_amount += 1

print(floors)

这会计算楼层数。如果您想绘制穿过这些点的线,您可以分别存储每个楼层的窗户:

windows = sorted(windows, key = lambda x: x[1])

thresshold = 30

floors = []

while windows:
    floors.append([windows[0]])
    for w in windows[1:].copy():
        if w[1] - windows[0][1] > thresshold:
            break
        floors.append(w)
        windows.remove(w)
    windows.remove(windows[0])

循环遍历楼层列表中的每个列表,并根据 x 坐标对列表进行排序,并为每个相邻的窗口绘制一条线cv2.line方法。 (https://python.engineering/python-opencv-cv2-line-method/ )

I gave it a try and here is what I came up with. It is not the best algorithm in the word, but it gets the job done. Keep in mind though that it only works when the photo is upright.

# you don't have to do that if the list is already sorted
windows = sorted(windows, key = lambda x: x[1]) 

thresshold = 30
floors_amount = 0

while windows:
    for w in windows[1:].copy():
        if w[1] - windows[0][1] > thresshold:
            break
        windows.remove(w)
    windows.remove(windows[0])
    floors_amount += 1

print(floors)

This counts the number of floors. If you want to draw lines going through those points you can store the windows of each floor separately:

windows = sorted(windows, key = lambda x: x[1])

thresshold = 30

floors = []

while windows:
    floors.append([windows[0]])
    for w in windows[1:].copy():
        if w[1] - windows[0][1] > thresshold:
            break
        floors.append(w)
        windows.remove(w)
    windows.remove(windows[0])

The loop though every list in the floors list and sort the list with respect to the x-coordinates and for every neighboring window draw a line with the cv2.line method. (https://python.engineering/python-opencv-cv2-line-method/)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文