状态类算法复杂排序输出

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

👇 

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

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

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

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

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

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

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

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

放上一些彩蛋图: 

🍉参考实现代码如下:

from collections import deque
import mathdef 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.0center_y = (ymin + ymax) / 2.0return (int(center_x),int(center_y))def cal_dist(point1, point2):x1, y1 = point1x2, y2 = point2distance = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)return distancedef cal_xIou(ret1, ret2):x1,y1 = convert_to_center(*ret1)x2,y2 = convert_to_center(*ret2)xmin1,ymin1,xmax1,ymax1 = ret1xmin2,ymin2,xmax2,ymax2 = ret2# print(ymin1, ymin2, ymax1, ymax2)if ymax1 < ymin2 or ymax2 < ymin1:return Falseelse: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):continueshortest_dist = disttarget = iter_point          return targetdef 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, 0for 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] = 1result = {}queue = []seen = set()start_point = min(centres_coordinates, key=lambda point: (point[0], -point[1]))queue.append(start_point)seen.add(start_point)layer = 1iter_idx = 1print("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=Trueif iter_point[0]==-1:judge = Falseif judge:queue.append(iter_point)iter_idx += 1seen.add(iter_point)else:result[layer] = queueif iter_idx == length_data:breaklayer += 1for 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 += 1print("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])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/190448.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大三上oracle数据库期末复习

1、创建表空间 2、创建用户 3、用户授权 oracle数据库逻辑存储结构&#xff1a; 1、表空间&#xff08;最大的逻辑存储单元&#xff09; 创建表空间 2、段 3、盘区&#xff08;最小的磁盘空间分配单元&#xff09; 4、数据块&#xff08;最小的数据读写单元&#xff09; 用…

thinkphp 5.1 对数据库查出来的字段进行预处理

比如数据库的设计是下面这样子&#xff1a; 我想展示的是这个样子&#xff1a; 前端可以处理。 Think PHP的处理方式&#xff1a; 定义属性 &#xff1a; $this->customize 任意值;//这里的之没有作用 <?phpnamespace app\hs\controller\shop;use app\daogou\mo…

分享4个工具,轻松搞定PDF和图像中提取文本

大型语言模型已经席卷了互联网&#xff0c;导致更多的人没有认真关注使用这些模型最重要的部分&#xff1a;高质量的数据&#xff01; 本文旨在提供一些有效从任何类型文档中提取文本的技术。 Python库 本文专注于Pytesseract、easyOCR、PyPDF2和LangChain库。实验数据是一个…

计算机网络TCP篇①

目录 一、TCP 基本信息 1.1、TCP 的头格式 1.2、什么是 TCP 1.3、什么是 TCP 连接 1.4、TCP 与 UDP 的区别 1.2、TCP 连接建立 1.2.1、TCP 三次握手的过程 1.2.2、为什么是三次握手&#xff1f;不是两次&#xff1f;四次&#xff1f;&#xff08;这个问题真是典中典&am…

深度学习实战63-利用自适应混合金字塔网络实现人脸皮肤美颜效果,快速部署与实现一键美颜功能

大家好,我是微学AI,今天给大家介绍一下深度学习实战63-利用自适应混合金字塔网络实现人脸皮肤美颜效果,快速部署与实现一键美颜功能。在本文中,我将介绍一种新颖的自适应混合金字塔网络(ABPN),该网络可以实现对超高分辨率照片的快速局部修饰。该网络主要由两个组件组成:一…

你知道Canary金丝雀版本的由来吗

Canary金丝雀版本是一种软件开发中常见的概念&#xff0c;它作为一种测试和试用版&#xff0c;旨在保护用户安全性和隐私&#xff0c;同时促进创新和改进。本文主要介绍Canary版本的由来。 随着技术的不断进步&#xff0c;软件开发变得越来越复杂且困难。为了满足用户需求并提…

【渗透】记录阿里云CentOS一次ddos攻击

文章目录 发现防御 发现 防御 流量清洗 使用高防

io基础入门

压缩的封装 参考&#xff1a;https://blog.csdn.net/qq_29897369/article/details/120407125?utm_mediumdistribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-120407125-blog-120163063.235v38pc_relevant_sort_base3&spm1001.2101.3001.…

【数据结构(五)】递归

文章目录 1. 递归的概念2. 递归能解决什么问题3. 递归的规则4. 递归实际应用案例4.1. 迷宫问题4.2. 八皇后问题4.2.1. 思路分析4.2.1. 代码实现 1. 递归的概念 简单的说: 递归就是方法自己调用自己&#xff0c;每次调用时传入不同的变量。递归有助于编程者解决复杂的问题&…

数据结构 - 堆:TOP-K问题

问题描述 TOP-K问题&#xff1a;即求数据结合中前K个最大的元素或者最小的元素&#xff0c;一般情况下数据量都比较大 比如&#xff1a;专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等 对于Top-K问题&#xff0c;能想到的最简单直接的方式就是排序&#xff0c;但是&…

Linux部署elasticsearch集群

文章目录 一、集群规划二、安装前准备(所有节点操作)创建数据目录修改系统配置文件/etc/sysctl.conf创建用户组设置limits.conf 三、初始化配置(在节点1上操作)下载安装包解压安装包修改jvm.options文件下配置的所占内存修改集群配置文件elasticsearch.yml将安装包传到另外两个…

00后卷王真的很卷吗?

前言 都在传00后躺平、整顿职场&#xff0c;但该说不说&#xff0c;是真的卷&#xff0c;感觉我都要被卷废了... 前段时间&#xff0c;公司招了一个年轻人&#xff0c;其中有一个是00后&#xff0c;工作才一年多&#xff0c;直接跳槽到我们公司&#xff0c;薪资据说有18K&…

Linux学习——模拟实现mybash小程序

目录 一&#xff0c;跟正宗的bash见个面 二&#xff0c;实现一个山寨的bash 1.提示符 2.输入命令与回显命令 3.解析命令 4.执行命令 5.执行逻辑 三&#xff0c;全部代码 一&#xff0c;跟正宗的bash见个面 在这篇文章中&#xff0c;我会写一个myshell小程序。这个小程序…

logback-spring.xml详解

《springboot使用logback日志框架超详细教程》文中&#xff0c;filter中最重要的两个过滤器LevelFilter&#xff08;日志级别精确匹配&#xff09;、ThresholdFilter&#xff08;阈值过滤&#xff09; 的描述非常准确&#xff1a; springboot使用logback日志框架超详细教程_sp…

SQL Server数据库部署

数据库简介 使用数据库的必要性 使用数据库可以高效且条理分明地存储数据&#xff0c;使人们能够更加迅速、方便地管理数据。数据库 具有以下特点。 》可以结构化存储大量的数据信息&#xff0c;方便用户进行有效的检索和访问。 》 可以有效地保持数据信息的一致性&#xff0c…

【Casbin】一篇文章入门Casbin

Casbin Casbin模型基础&#xff08;PERM&#xff09;Policy定义Request定义MatchersEffect ACL模型RBAC模型Go语言实战使用前先下载casbin包新建一个Casbin enforcer判断是否能通过增加Policy删除Policy更新Policy获取Policy Casbin 权限管理在几乎每个系统中都是必备的模块。…

java设计模式学习之【桥接模式】

文章目录 引言桥接模式简介定义与用途&#xff1a;实现方式 使用场景优势与劣势桥接模式在Spring中的应用绘图示例代码地址 引言 想象你正在开发一个图形界面应用程序&#xff0c;需要支持多种不同的窗口操作系统。如果每个系统都需要写一套代码&#xff0c;那将是多么繁琐&am…

【vue-router】useRoute 和 useRouter 的区别

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

一起学docker系列之十四Dockerfile微服务实践

目录 1 前言2 创建微服务模块2.1 **创建项目模块**2.2 **编写业务代码** 3 编写 Dockerfile4 构建 Docker 镜像5 运行 Docker 容器6 测试微服务7 总结8 参考地址 1 前言 微服务架构已经成为现代软件开发中的一种重要方式。而 Docker 提供了一种轻量级、便携式的容器化解决方案…

ESP32和ESP8266的ESP-MESH

ESP32和ESP8266的ESP-MESH 功能介绍一、介绍ESP-MESH二、安装painlessMesh库三、ESP-MESH基本示例&#xff08;广播消息&#xff09;四、示范 功能介绍 了解如何使用ESP-MESH网络协议通过ESP32和ESP8266 NodeMCU板构建网状网络。 ESP-MESH允许多个设备&#xff08;节点&#x…