基于语义分割Ground Truth(GT)转换yolov5目标检测标签(路面积水检测例子)

news2024/12/27 18:41:43

基于语义分割Ground Truth(GT)转换yolov5目标检测标签(路面积水检测例子)

概述

许多目标检测的数据是通过直接标注或者公开平台获得,如果存在语义分割Ground Truth的标签文件,怎么样实现yolov5的目标检测格式转换呢?查遍全网没有很好的方法,因此使用opencv自己写了一个,检验效果还不错。

这里的例子是基于极市平台的路面积水检测给出的数据集完成,由于平台只给了分割的示例数据,因此想使用yolo进行目标检测,需要自己进行标签的转换.已有的数据集有原图和label,这里的label是PNG格式的图片,如下所示:

image-20230128163946548

image-20230128163907398

数据集包含原图片以及相对应分割后的图片(标注文件),标注文件的格式为PNG,并且为单通道灰度图。在本任务中,为了直观地观察输出的PNG图片,使用如下灰度值:

  1. 背景:0
  2. 积水:1

可以直接使用该数据集进行分割模型的训练和验证,例如unet、deeplab等模型

流程

由于分割图像相对目标检测具有更精细的标注,因此只需要三个步骤即可完成整体转换流程

1、找到图中的分割块(目标),并找到其最小矩形

2、得到的最小矩形进行坐标转换,OpenCV进行边缘检测,得到坐标

3、根据YOLO坐标归一化方法,完成坐标转换,并存储*.txt

注意事项:数据量比较大,转换的时候会使用批量转换。由于是使用边缘检测获取最小矩形框,因此在训练过程中会出现误差,影响不大。

读取图像

使用os读取文件夹下的标签图像,并使用OpenCV读取图片

path = "./mask/train/"
files = os.listdir(path)
for file in files:
    img = cv2.imread(path+file)

为了方便查看标签,可以先将标签可视化,原始分割标签是0,1,。。。,n的数字,所以在图像上看都是黑色的不明显,不同类别使用不同颜色显示出来,

#1->255####
print(img.shape)
for i in range(len(img)):
for j in range(len(img[0])):
if img[i][j] == 1:
img[i][j]print(file) = 255
print(img[i][j])
cv2.imwrite("./mask/{}".format(file),img)

#get_bbox

path = "./mask/ponding_sample_103.png"
img = cv2.imread(path)
img_w = img.shape[1]
img_h = img.shape[0]

转换并获取最小外接矩形

OpenCV常规读取是BGR格式,标签是单通道图形,需要转换为单通道的灰度图,方便后面检测,使用cv2.cvtColor转换为灰度图,或者读取时cv2.imread(path,0),0模式是灰度图。OpenCV给了很方便的边缘检测方法contours, hierarchy = cv.findContours( image, mode, method[, contours[, hierarchy[, offset]]] )

image:输入为二值图像,黑色为背景,白色为目标

单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;该函数会修改原图像,因此若想保留原图像在,则需拷贝一份,在拷贝图里修改。

mode

image-20230128165946856

method

image-20230128165954881

offset:轮廓点的偏移量,格式为tuple,如(-10,10)表示轮廓点沿X负方向偏移10个像素点,沿Y正方向偏移10个像素点

返回值
contours:轮廓点。列表格式,每一个元素为一个3维数组(其形状为(n,1,2),其中n表示轮廓点个数,2表示像素点坐标),表示一个轮廓

hierarchy:轮廓间的层次关系,为三维数组,形状为(1,n,4),其中n表示轮廓总个数,4指的是用4个数表示各轮廓间的相互关系。第一个数表示同级轮廓的下一个轮廓编号,第二个数表示同级轮廓的上一个轮廓的编号,第三个数表示该轮廓下一级轮廓的编号,第四个数表示该轮廓的上一级轮廓的编号。

通过cv2.minAreaRectcv2.contourArea获得每个目标的最小外接矩形

img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
cnts,_ = cv2.findContours(img.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for i, contour in enumerate(cnts):
    area = cv2.contourArea(contour)  # 计算包围形状的面积
    rect = cv2.minAreaRect(contour)  # 检测轮廓最小外接矩形,得到最小外接矩形的(中心(x,y), (宽,高), 旋转角度)

转换yolo坐标

yolo的标签形式是四个点,四个点分别代表bbox的中心坐标(x,y)和宽、高,但是需要根据原图的长宽进行归一化,既x/原图宽,y/原图高,w/原图宽,h/原图高,根据计算并记录即可

boxs = []
for i, contour in enumerate(cnts):
        area = cv2.contourArea(contour)  # 计算包围形状的面积
        rect = cv2.minAreaRect(contour)  # 检测轮廓最小外接矩形,得到最小外接矩形的(中心(x,y), (宽,高), 旋转角度)
        temp =[0]
    temp = [0]
    temp.append(rect[0][0])
    temp.append(rect[0][1])
    temp.append(rect[1][0])
    temp.append(rect[1][1])
    temp[1] /= img_w
    temp[2] /= img_h
    temp[3] /= img_w
    temp[4] /= img_h
    # box = np.int0(cv2.boxPoints(rect))
    boxs.append(temp)   # 最后剩下的有用的框

注意:这里由于只有一个类别,因此我直接初始化写入的时候temp=[0],如果是多种目标对应修改即可

转存txt文件

存储在boxs数组中的数据就是需要保存的类别和对应的四个坐标

f = open("./labels/train2017/{}.txt".format(file.split(".")[0]), "w+")
for line in boxs:
    line = str(line)[1:-2].replace(",","")
    print(line)
    f.write(line+"\n")
f.close()

转换之后的txt标签如下图,可直接在yolov5中训练使用

image-20230128171139014
完整代码地址:https://github.com/magau123/CSDN/blob/master/GT2yolo.py

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

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

相关文章

【图论】求欧拉回路

前言 你的qq密码是否在圆周率中出现? 一个有意思的编码问题:假设密码是固定位数,设有nnn位,每位是数字0-9,那么这样最短的“圆周率”的长度是多少?或者说求一个最短的数字串定包含所有密码。 理论 一些…

acwing1264_动态求连续区间和

目录 算法分类: 问题描述 算法适用题目范围: 实现代码: 算法分类: 树状数组/线段树 问题描述 给定 n个数组成的一个数列,规定有两种操作,一是修改某个元素,二是求子数列 [a,b]的连续和。 …

1602_MIT 6.828试验环境搭建

全部学习汇总: GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 最近尝试看一下MIT的操作系统教程,找到了一个6.828的课程。看了一下网络上的介绍,看起来这个大家的认可度还是很高的。开动之前&#xff0c…

Android面经_111道安卓基础问题(四大组件BroadCast、内容提供者篇)

该文章涉及的内容主要是:BroadCast、内容提供者; Android基础问题——四大组件之BroadCast、ContentProvider 内容提供者1、BroadCast1.1、Android的广播分类1.2、Android的广播注册方式1.3、广播作用域2、内容提供者Content provider2.1、什么是内容提供…

Google Protobuf 实践使用开发

Android 敏捷开发助手 Lottie动画 轻松使用PNG、JPG等普通图片高保真转SVG图Android 完美的蒙层方案Android MMKV框架引入使用强大无匹的自定义下拉列表Google Protobuf 实践使用开发 Protobuf 实践使用前言Protobuf基本介绍Protobuf 使用配置protobuf 基本语法1. 基本使用2. …

JavaWeb-Ajax

JavaWeb-Ajax 3,Ajax 3.1 概述 AJAX (Asynchronous JavaScript And XML):异步的 JavaScript 和 XML。 我们先来说概念中的 JavaScript 和 XML,JavaScript 表明该技术和前端相关;XML 是指以此进行数据交换。 3.1.1 作用 AJAX…

用Python绘制傅里叶级数和泰勒级数逼近已知函数的动态过程

文章目录Taylor级数Fourier级数本文代码: Fourier级数和Taylor级数对原函数的逼近动画Taylor级数 级数是对已知函数的一种逼近,比较容易理解的是Taylor级数,通过多项式来逼近有限区间内的函数,其一般形式为 f(x)∑n0Nanxnf(x)\su…

Lua 运算符 - 较为特殊部分

Lua 运算符 - 较为特殊部分 参考至菜鸟教程。 算术运算符 操作符描述实例^乘幂A^2 输出结果 100-负号-A 输出结果 -10//整除运算符(>lua5.3)5//2 输出结果 2在 lua 中,/ 用作除法运算,计算结果包含小数部分,// 用作整除运算,计…

Shiro学习文档

Shiro Java安全框架 1.什么是权限管理 ​ 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。 权限管理…

oracle mysql postgresql opengauss 批量kill session

oracle alter system kill session sid,serial# immed; (根据v$session中查出sid和serial#进行替换) 这里提供一个常用脚本,支持跨实例kill会话 (替换&1条件或放到脚本调用都行) select alter system kill sessi…

Dubbo 简介

Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性&…

嵌入式工程师的2022 || 2023

因为一些个人关系,2022年初我从北京回到了石家庄。在找工作,包括后续的研发工作中,不同地点的经历在对比中我逐渐总结出了一些经验。关于“人”方面的感悟我就不赘述了,下面主要在这里总结一些找工作,做工作的经验&…

八、迁移学习和多任务学习

文章目录1、迁移学习2、多任务学习3、端到端学习THE END1、迁移学习 \qquad迁移学习是将某个任务学习到的知识(神经网络的参数信息)迁移到另外一个相似的任务中使用,从而重复利用相似任务学习共同之处,节省模型训练的时间,提高模型的训练效率…

一名普通22届本科毕业生|前端程序员|22年年终总结

文章目录22年上半年:最后的学生时光隔离实习币基金迷茫困惑难受不要去想人生意义读书景点环境的力量再次隔离返校入职前的学习22年下半年:上班工作生活总结本来准备在22年年末写的,奈何那段时间工作太忙没抽出时间。现在是23年的1月27日&…

paddleOCR代码工程的MD模式改造

一、下载cmake_3.22.3,用于生成vs工程 Index of /files/v3.22 下载完成,解压文件,打开cmake-gui.exe,即可使用: 二、下载Git(Git-2.36.0-64-bit.exe)并按照默认路径安装,cmake需调用…

使用Moment格式化时间出现时间差

诶嘿,很离奇。前些天后端老哥给我说我这时间展示不对。 我就奇了个大怪,就是取的这个字段嘛,怎么肥事😭 看半天发现是时间格式化出的问题。 原代码⬇️,看起来没毛病嘛,值打印出来也与接口里的这个时间一…

到底卡在了哪里,2023年再撒谎网慢就说不过去了

前言互联网下行带来灵魂追问。钱花哪去了?产出在哪里?动辄自建的遮羞布逐步显现,不过自建的成本可能还不是最大的负担,掣肘的可能是把不重要的事情当成了主业来做,比如:互联网比如数字化转型比如研发效率和…

Verilog HDL基本语法规则

⭐本专栏针对FPGA进行入门学习,从数电中常见的逻辑代数讲起,结合Verilog HDL语言学习与仿真,主要对组合逻辑电路与时序逻辑电路进行分析与设计,对状态机FSM进行剖析与建模。 🔥文章和代码已归档至【Github仓库&#xf…

10大面试必备的排序算法 Python 实现(附源码)

今天给大家分享一篇关于Python实现排序算法的文章,来自GitHub。 排序算法是《数据结构与算法》中最基本的算法之一。 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一…

STM32入门基础

GPIO <1>说明 引脚电平&#xff1a;0~3.3V&#xff0c;部分可达到5V(参考引脚定义&#xff0c;带FT的就可以) 同时 GPIO有两个模式 输出模式&#xff1a;进行端口高低电平的输出&#xff0c;用于驱动LED&#xff0c;蜂鸣器等 输入模式&#xff1a;读取端口高低电平…