状态类算法复杂排序输出

对于目标检测任务中对某一类的检测结果进行输出的时候,一般都是无序的,很明显这样子很难满足的我们的需求,我们更喜欢他是这样子输出的:

状态类算法复杂排序输出_第1张图片

 

我们可以看到——”按顺序输出结果“中的字段是完美的和上面图片中的识别结果一一对应的,这其实也很容易做到。

我们只需要把这些个矩形框一个个抽出来,放在一张白纸上面,如下图所示:

NOTE:下图是模拟的复杂样例,并非上图中的矩形框抽出来。

状态类算法复杂排序输出_第2张图片

红色箭头代表的就是正确的排序方式,看到这里有一些朋友可能已经有了思路,我这边使用了数据结构算法中的图论算法,我们可以把上面四个箭头当作四层, 每一层从根节点也就是最左边的矩形框出发进行连边操作,每一次连边必须满足以下要求:

  • 连边的矩形框与上一个节点的Iou!=0
  • 连边的矩形框的质心必须处于上一个节点质心的右边
  • 连边的矩形框的质心必须与上一个节点的质心有着距离最近的关系。

根据这些约束条件,我们可以选取最左上的节点当作第一层的根节点,开始我们的连边操作:

当最有一个节点的最右边已经没有了节点的时候,至此我们结束了第一层搜索,删掉第一层连接的所有矩形框,进入第二层搜索。由于删掉了第一层所有的矩形框,第二层的第一个节点又变成了最左上角的节点,选取她开始第二轮的遍历连边操作。

以此类推,我们便完成了所有排序的工作:

状态类算法复杂排序输出_第3张图片

放上一些彩蛋图: 

状态类算法复杂排序输出_第4张图片

参考实现代码如下:

from collections import deque
import math

def draw(points):
    import matplotlib.pyplot as plt

    # 中心点坐标
    # points = [(67.0, 72.0), (172.5, 70.0), (274.5, 79.5), (380.0, 79.0), (489.5, 149.5), (73.5, 241.0), 
    #           (185.0, 249.0), (386.5, 239.0), (604.5, 128.5), (719.5, 151.0), (209.5, 403.0), (374.0, 393.0), 
    #           (180.5, 562.0), (288.5, 568.5), (394.5, 573.5)]
    # 提取 x 和 y 坐标
    x_coords, y_coords = zip(*points)

    # 创建一个散点图
    plt.scatter(x_coords, y_coords, marker='o', color='blue')

    # 添加坐标标签
    for i, point in enumerate(points):
        plt.annotate(f"{i, point}", (x_coords[i], y_coords[i]), textcoords="offset points", xytext=(0,10), ha='center', fontsize=8)

    # 设置图的标题和坐标轴标签
    plt.title("centre plot")
    plt.xlabel("X")
    plt.ylabel("Y")

    # 设置坐标轴原点为左上角
    plt.gca().invert_yaxis()

    # 显示图
    plt.grid()
    plt.show()
    plt.savefig("switch_sort.jpg",dpi=300)


def convert_to_center(xmin, ymin, xmax, ymax):
    center_x = (xmin + xmax) / 2.0
    center_y = (ymin + ymax) / 2.0
    return (int(center_x),int(center_y))

def cal_dist(point1, point2):
    x1, y1 = point1
    x2, y2 = point2
    distance = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
    return distance

def cal_xIou(ret1, ret2):
    x1,y1 = convert_to_center(*ret1)
    x2,y2 = convert_to_center(*ret2)
    xmin1,ymin1,xmax1,ymax1 = ret1
    xmin2,ymin2,xmax2,ymax2 = ret2
    # print(ymin1, ymin2, ymax1, ymax2)
    if ymax1 < ymin2 or ymax2 < ymin1:
        return False
    else:
        return True

# def find_right_shortestPoint(centres_coordinates, now_point):
#     shortest_dist = float('inf')
#     for iter_point in centres_coordinates:
#         dist = cal_dist(now_point, iter_point)
#         if dist < shortest_dist and dist != 0:
#             if now_point[1] < iter_point[1]:
#                 return iter_point
#     return ValueError("找不到距离最近的框,是不是总共只有一个框!")

def find_shortestPoint(bboxes, centres_coordinates, backup_centres_coordinates, now_point, seen):
    shortest_dist = float('inf')
    target=(-1,-1)
    for iter_point in centres_coordinates:
        if iter_point in seen:
            continue
        # print(now_point, iter_point)
        if now_point[0] < iter_point[0]:
            dist = cal_dist(now_point, iter_point)
            # print(dist)
            if dist < shortest_dist and dist != 0:

                nowPoint_idx = backup_centres_coordinates.index(now_point)
                iterPoint_idx = backup_centres_coordinates.index(iter_point)
                nowBbox = bboxes[nowPoint_idx]
                iterBbox = bboxes[iterPoint_idx]

                # print(nowBbox, iterBbox)
                if not cal_xIou(nowBbox, iterBbox):
                    continue
                shortest_dist = dist
                target = iter_point          
    return target

def main_layers(bboxes):
    #[ [xmin,ymin,xmax,ymax]]
    backup_bboxes = bboxes.copy()
    centres_coordinates = []
    for bbox in bboxes:
        centre = convert_to_center(*bbox)
        centres_coordinates.append(centre)
    length_data = len(bboxes)
    backup_centres_coordinates = centres_coordinates.copy()
    # backup_centres_coordinates = centres_coordinates.copy()
    max_h, max_w = 0, 0
    for cc in centres_coordinates:
        max_h = max(max_h, cc[0])
        max_w = max(max_h, cc[1])

    # draw(centres_coordinates)   
    
    grap = [[0 for _ in range(int(max_w + 10))] for _ in range(int(max_h) + 10)]
    for cen in centres_coordinates:
        cen_x, cen_y = int(cen[0]), int(cen[1])
        grap[cen_x][cen_y] = 1
    
    result = {

    }
    queue = []
    seen = set()
    start_point = min(centres_coordinates, key=lambda point: (point[0], -point[1]))
    queue.append(start_point)
    seen.add(start_point)
    layer = 1
    iter_idx = 1
    print("Now Layer:{} start point:{}".format(layer, start_point))
 
    while iter_idx <= length_data:
        now_point = queue[-1]
        iter_point = find_shortestPoint(backup_bboxes, centres_coordinates, backup_centres_coordinates,now_point, seen)
        judge=True
        if iter_point[0]==-1:
            judge = False
        
        if judge:
            queue.append(iter_point)
            iter_idx += 1
            seen.add(iter_point)
        else:
            result[layer] = queue
            if iter_idx == length_data:
                break
            layer += 1
            for q in queue:
                # print(q)    
                # print(centres_coordinates)
                # backup_bboxes.remove(centres_coordinates.index(q))
                centres_coordinates.remove(q)
                
            queue = []
            seen = set()
            start_point = min(centres_coordinates, key=lambda point: (point[0], -point[1]))
            queue.append(start_point)
            seen.add(start_point)
            iter_idx += 1
            print("Now Layer:{} start point:{}".format(layer, start_point))

    sorted_dict = dict(sorted(result.items(),key=lambda item: item[1][0][1]))
    for key in sorted_dict:
        print(key, sorted_dict[key])
    return sorted_dict

使用方法:

bboxes = [[box[0], box[1], box[0]+box[2], box[1]+box[3]] for box in used_res]
                    sorted_dict = main_layers(bboxes)
                    centres_coordinates = []
                    for bbox in bboxes:
                        centre = convert_to_center(*bbox)
                        centres_coordinates.append(centre)

                    sorted_used_res = []
                    for layer in sorted_dict:
                        for iter_column in sorted_dict[layer]:
                            iter_index = centres_coordinates.index(iter_column)
                            sorted_used_res.append(used_res[iter_index])

你可能感兴趣的:(projects算法工程师,算法,python,开发语言)