状态类算法复杂排序输出

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

👇 

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

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

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,一经查实,立即删除!

相关文章

golang ssh demo

密码登入: package mainimport ("fmt""golang.org/x/crypto/ssh" )func main() {// 目标服务器地址targetAddr := "ip:22"// 创建 SSH 客户端连接sshConfig := &ssh.ClientConfig{User: "root",Auth: []ssh.AuthMethod{ssh.Pass…

大三上oracle数据库期末复习

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

WordPress(11)给文章添加预计阅读时长

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、文件配置二、代码块1.引入库2.配置 single.php三、效果图前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了…

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),该网络可以实现对超高分辨率照片的快速局部修饰。该网络主要由两个组件组成:一…

javascript中的正则表达式的相关知识积累

01-javascript中的正则表达式用符号/作为正则表达式的开始符和结束符 javascript中的正则表达式用符号/作为正则表达式的开始符和结束符。 即javascript的正则表达式如下所示&#xff1a; /正则表达式/02-^&#xff1a;匹配字符串的开始 ^: 该符号表示匹配字符串的开始。这个…

你知道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&…

《微信小程序开发从入门到实战》学习三十九

4.2 云开发JSON数据库 4.2.10 查询数组和对象 1.匹配记录中的嵌套字段 db.collection(testOne).add({data:{style:{color:red}}}) db.collection(testOne).add({data:{style:{color:blue}}}) 插入两天记录&#xff0c;如果希望查询style.color为blue的记录&#xff0c;有两种…

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…

vue el-cascader 省市区封装及使用

使用了 Element UI 中的 el-cascader 组件&#xff0c;并对其进行了进一步封装和定制 创建组件index.vue (src/components/addressCascader/index.vue) <template><div><el-cascaderv-if"showca"size"large":props"props":optio…