数据翻转,需要把bbox相应的坐标值也进行交换

代码:

import random
from torchvision.transforms import functional as Fclass Compose(object):"""组合多个transform函数"""def __init__(self, transforms):self.transforms = transformsdef __call__(self, image, target):for t in self.transforms:image, target = t(image, target)return image, targetclass ToTensor(object):"""将PIL图像转为Tensor"""def __call__(self, image, target):image = F.to_tensor(image)return image, targetclass RandomHorizontalFlip(object):"""随机水平翻转图像以及bboxes"""def __init__(self, prob=0.5):self.prob = probdef __call__(self, image, target):if random.random() < self.prob:height, width = image.shape[-2:]image = image.flip(-1)  # 水平翻转图片bbox = target["boxes"]# bbox: xmin, ymin, xmax, ymaxbbox[:, [0, 2]] = width - bbox[:, [2, 0]]  # 翻转对应bbox坐标信息target["boxes"] = bboxreturn image, target

对图像及其对应的标注文件(XML格式)进行数据增强,并将增强后的图像和标注文件保存到指定的目录中

  • root:XML文件所在的目录路径。

  • image_id:XML文件的名称(不包含扩展名)。

代码:

import xml.etree.ElementTree as ET
import pickle
import os
from os import getcwd
import numpy as np
from PIL import Image
import shutil
import matplotlib.pyplot as pltimport imgaug as ia
from imgaug import augmenters as iaaia.seed(1)def read_xml_annotation(root, image_id):in_file = open(os.path.join(root, image_id))tree = ET.parse(in_file)root = tree.getroot()bndboxlist = []for object in root.findall('object'):  # 找到root节点下的所有country节点bndbox = object.find('bndbox')  # 子节点下节点rank的值xmin = int(bndbox.find('xmin').text)xmax = int(bndbox.find('xmax').text)ymin = int(bndbox.find('ymin').text)ymax = int(bndbox.find('ymax').text)# print(xmin,ymin,xmax,ymax)bndboxlist.append([xmin, ymin, xmax, ymax])# print(bndboxlist)bndbox = root.find('object').find('bndbox')return bndboxlist# (506.0000, 330.0000, 528.0000, 348.0000) -> (520.4747, 381.5080, 540.5596, 398.6603)
def change_xml_annotation(root, image_id, new_target):new_xmin = new_target[0]new_ymin = new_target[1]new_xmax = new_target[2]new_ymax = new_target[3]in_file = open(os.path.join(root, str(image_id) + '.xml'))  # 这里root分别由两个意思tree = ET.parse(in_file)xmlroot = tree.getroot()object = xmlroot.find('object')bndbox = object.find('bndbox')xmin = bndbox.find('xmin')xmin.text = str(new_xmin)ymin = bndbox.find('ymin')ymin.text = str(new_ymin)xmax = bndbox.find('xmax')xmax.text = str(new_xmax)ymax = bndbox.find('ymax')ymax.text = str(new_ymax)tree.write(os.path.join(root, str("%06d" % (str(id) + '.xml'))))def change_xml_list_annotation(root, image_id, new_target, saveroot, id):in_file = open(os.path.join(root, str(image_id) + '.xml'))  # 这里root分别由两个意思tree = ET.parse(in_file)elem = tree.find('filename')elem.text = (id + '.jpg')xmlroot = tree.getroot()index = 0for object in xmlroot.findall('object'):  # 找到root节点下的所有country节点bndbox = object.find('bndbox')  # 子节点下节点rank的值# xmin = int(bndbox.find('xmin').text)# xmax = int(bndbox.find('xmax').text)# ymin = int(bndbox.find('ymin').text)# ymax = int(bndbox.find('ymax').text)new_xmin = new_target[index][0]new_ymin = new_target[index][1]new_xmax = new_target[index][2]new_ymax = new_target[index][3]xmin = bndbox.find('xmin')xmin.text = str(new_xmin)ymin = bndbox.find('ymin')ymin.text = str(new_ymin)xmax = bndbox.find('xmax')xmax.text = str(new_xmax)ymax = bndbox.find('ymax')ymax.text = str(new_ymax)index = index + 1tree.write(os.path.join(saveroot, id + '.xml'))def mkdir(path):# 去除首位空格path = path.strip()# 去除尾部 \ 符号path = path.rstrip("\\")# 判断路径是否存在# 存在     True# 不存在   FalseisExists = os.path.exists(path)# 判断结果if not isExists:# 如果不存在则创建目录# 创建目录操作函数os.makedirs(path)print(path + ' 创建成功')return Trueelse:# 如果目录存在则不创建,并提示目录已存在print(path + ' 目录已存在')return Falseif __name__ == "__main__":IMG_DIR = "VOCdevkit/VOC2007/JPEGImages3"XML_DIR = "VOCdevkit/VOC2007/Annotations3"AUG_XML_DIR = "VOCdevkit/VOC2007/Annotations"  # 存储增强后的XML文件夹路径try:shutil.rmtree(AUG_XML_DIR)except FileNotFoundError as e:a = 1mkdir(AUG_XML_DIR)AUG_IMG_DIR = "VOCdevkit/VOC2007/JPEGImages"  # 存储增强后的影像文件夹路径try:shutil.rmtree(AUG_IMG_DIR)except FileNotFoundError as e:a = 1mkdir(AUG_IMG_DIR)AUGLOOP = 8  # 每张影像增强的数量boxes_img_aug_list = []new_bndbox = []new_bndbox_list = []# 影像增强seq = iaa.Sequential([iaa.Flipud(0.5),  # vertically flip 20% of all imagesiaa.Fliplr(0.5),  # 镜像iaa.Multiply((1.2, 1.5)),  # change brightness, doesn't affect BBsiaa.GaussianBlur(sigma=(0, 3.0)),  # iaa.GaussianBlur(0.5),iaa.Affine(translate_px={"x": 15, "y": 15},scale=(0.8, 0.95),rotate=(-30, 30))  # translate by 40/60px on x/y axis, and scale to 50-70%, affects BBs])for root, sub_folders, files in os.walk(XML_DIR):for name in files:bndbox = read_xml_annotation(XML_DIR, name)shutil.copy(os.path.join(XML_DIR, name), AUG_XML_DIR)shutil.copy(os.path.join(IMG_DIR, name[:-4] + '.jpg'), AUG_IMG_DIR)for epoch in range(AUGLOOP):seq_det = seq.to_deterministic()  # 保持坐标和图像同步改变,而不是随机# 读取图片img = Image.open(os.path.join(IMG_DIR, name[:-4] + '.jpg'))# sp = img.sizeimg = np.asarray(img)# bndbox 坐标增强for i in range(len(bndbox)):bbs = ia.BoundingBoxesOnImage([ia.BoundingBox(x1=bndbox[i][0], y1=bndbox[i][1], x2=bndbox[i][2], y2=bndbox[i][3]),], shape=img.shape)bbs_aug = seq_det.augment_bounding_boxes([bbs])[0]boxes_img_aug_list.append(bbs_aug)# new_bndbox_list:[[x1,y1,x2,y2],...[],[]]n_x1 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x1)))n_y1 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y1)))n_x2 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x2)))n_y2 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y2)))if n_x1 == 1 and n_x1 == n_x2:n_x2 += 1if n_y1 == 1 and n_y2 == n_y1:n_y2 += 1if n_x1 >= n_x2 or n_y1 >= n_y2:print('error', name)new_bndbox_list.append([n_x1, n_y1, n_x2, n_y2])# 存储变化后的图片image_aug = seq_det.augment_images([img])[0]path = os.path.join(AUG_IMG_DIR,str("%06d" % (len(files)*epoch))+ name[:-4] + '.jpg')image_auged = bbs.draw_on_image(image_aug, thickness=0)Image.fromarray(image_auged).save(path)# 存储变化后的XMLchange_xml_list_annotation(XML_DIR, name[:-4], new_bndbox_list, AUG_XML_DIR,str("%06d" % (len(files)*epoch))+ name[:-4])print(str("%06d" % (len(files)*epoch))+ name[:-4] + '.jpg')new_bndbox_list = []

代码结构解读:

1. 导入模块
import xml.etree.ElementTree as ET
import pickle
import os
from os import getcwd
import numpy as np
from PIL import Image
import shutil
import matplotlib.pyplot as pltimport imgaug as ia
from imgaug import augmenters as iaa
  • xml.etree.ElementTree:用于解析和操作XML文件。

  • numpyPIL:用于图像处理。

  • imgaug:用于图像增强。

  • 其他模块用于文件操作和路径管理。

2. 数据增强的随机种子
  • 设置随机种子,确保每次运行代码时增强操作的一致性。

ia.seed(1)
3. 读取XML标注文件
def read_xml_annotation(root, image_id):in_file = open(os.path.join(root, image_id))tree = ET.parse(in_file)root = tree.getroot()bndboxlist = []for object in root.findall('object'):bndbox = object.find('bndbox')xmin = int(bndbox.find('xmin').text)xmax = int(bndbox.find('xmax').text)ymin = int(bndbox.find('ymin').text)ymax = int(bndbox.find('ymax').text)bndboxlist.append([xmin, ymin, xmax, ymax])return bndboxlist
  • 输入:XML文件所在的目录和文件名。

  • 功能:解析XML文件,提取所有目标对象的边界框坐标。

  • 输出:边界框列表,每个边界框用 [xmin, ymin, xmax, ymax] 表示。

4. 更新单个XML标注文件
def change_xml_annotation(root, image_id, new_target):new_xmin, new_ymin, new_xmax, new_ymax = new_targetin_file = open(os.path.join(root, str(image_id) + '.xml'))tree = ET.parse(in_file)xmlroot = tree.getroot()object = xmlroot.find('object')bndbox = object.find('bndbox')xmin = bndbox.find('xmin')xmin.text = str(new_xmin)ymin = bndbox.find('ymin')ymin.text = str(new_ymin)xmax = bndbox.find('xmax')xmax.text = str(new_xmax)ymax = bndbox.find('ymax')ymax.text = str(new_ymax)tree.write(os.path.join(root, str("%06d" % (str(id) + '.xml'))))
  • 输入:XML文件所在的目录、文件名和新的边界框坐标。

  • 功能:更新XML文件中第一个目标对象的边界框坐标。

  • 输出:保存更新后的XML文件。

5. 更新多个XML标注文件
def change_xml_list_annotation(root, image_id, new_target, saveroot, id):in_file = open(os.path.join(root, str(image_id) + '.xml'))tree = ET.parse(in_file)elem = tree.find('filename')elem.text = (id + '.jpg')xmlroot = tree.getroot()index = 0for object in xmlroot.findall('object'):bndbox = object.find('bndbox')new_xmin = new_target[index][0]new_ymin = new_target[index][1]new_xmax = new_target[index][2]new_ymax = new_target[index][3]xmin = bndbox.find('xmin')xmin.text = str(new_xmin)ymin = bndbox.find('ymin')ymin.text = str(new_ymin)xmax = bndbox.find('xmax')xmax.text = str(new_xmax)ymax = bndbox.find('ymax')ymax.text = str(new_ymax)index += 1tree.write(os.path.join(saveroot, id + '.xml'))
  • 输入:原始XML目录、文件名、新的边界框列表、保存目录和新的文件名。

  • 功能:更新XML文件中所有目标对象的边界框坐标。

  • 输出:保存更新后的XML文件。

6. 创建目录
def mkdir(path):path = path.strip()path = path.rstrip("\\")isExists = os.path.exists(path)if not isExists:os.makedirs(path)print(path + ' 创建成功')return Trueelse:print(path + ' 目录已存在')return False
  • 输入:目标目录路径。

  • 功能:创建目录,如果目录已存在,则提示。

7. 主程序
if __name__ == "__main__":IMG_DIR = "VOCdevkit/VOC2007/JPEGImages3"XML_DIR = "VOCdevkit/VOC2007/Annotations3"AUG_XML_DIR = "VOCdevkit/VOC2007/Annotations"try:shutil.rmtree(AUG_XML_DIR)except FileNotFoundError as e:passmkdir(AUG_XML_DIR)AUG_IMG_DIR = "VOCdevkit/VOC2007/JPEGImages"try:shutil.rmtree(AUG_IMG_DIR)except FileNotFoundError as e:passmkdir(AUG_IMG_DIR)AUGLOOP = 8  # 每张影像增强的数量seq = iaa.Sequential([iaa.Flipud(0.5),  # 垂直翻转iaa.Fliplr(0.5),  # 水平翻转iaa.Multiply((1.2, 1.5)),  # 调整亮度iaa.GaussianBlur(sigma=(0, 3.0)),  # 高斯模糊iaa.Affine(translate_px={"x": 15, "y": 15},scale=(0.8, 0.95),rotate=(-30, 30))  # 平移、缩放、旋转])for root, sub_folders, files in os.walk(XML_DIR):for name in files:bndbox = read_xml_annotation(XML_DIR, name)shutil.copy(os.path.join(XML_DIR, name), AUG_XML_DIR)shutil.copy(os.path.join(IMG_DIR, name[:-4] + '.jpg'), AUG_IMG_DIR)for epoch in range(AUGLOOP):seq_det = seq.to_deterministic()img = Image.open(os.path.join(IMG_DIR, name[:-4] + '.jpg'))img = np.asarray(img)for i in range(len(bndbox)):bbs = ia.BoundingBoxesOnImage([ia.BoundingBox(x1=bndbox[i][0], y1=bndbox[i][1], x2=bndbox[i][2], y2=bndbox[i][3]),], shape=img.shape)bbs_aug = seq_det.augment_bounding_boxes([bbs])[0]n_x1 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x1)))n_y1 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y1)))n_x2 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x2)))n_y2 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y2)))if n_x1 == 1 and n_x1 == n_x2:n_x2 += 1if n_y1 == 1 and n_y2 == n_y1:n_y2 += 1if n_x1 >= n_x2 or n_y1 >= n_y2:print('error', name)new_bndbox_list.append([n_x1, n_y1, n_x2, n_y2])image_aug = seq_det.augment_images([img])[0]path = os.path.join(AUG_IMG_DIR, str("%06d" % (len(files) * epoch)) + name

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

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

相关文章

DiffDet4SAR——首次将扩散模型用于SAR图像目标检测,来自2024 GRSL(ESI高被引1%论文)

一. 论文摘要 合成孔径雷达&#xff08;SAR&#xff09;图像中的飞机目标检测是一项具有挑战性的任务&#xff0c;由于离散的散射点和严重的背景杂波干扰。目前&#xff0c;基于卷积或基于变换的方法不能充分解决这些问题。 本文首次探讨了SAR图像飞机目标检测的扩散模型&#…

html案例:编写一个用于发布CSDN文章时,生成有关缩略图

CSDN博客文章缩略图生成器起因&#xff1a;之前注意到CSDN可以随机选取文章缩略图&#xff0c;但后来这个功能似乎取消了。于是我想调整一下缩略图的配色方案。html制作界面 界面分上下两块区域&#xff0c;上面是参数配置&#xff0c;下面是效果预览图。参数配置&#xff1a; …

lightgbm算法学习

主要组件 Boosting #mermaid-svg-1fiqPsJfErv6AV82 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-1fiqPsJfErv6AV82 .error-icon{fill:#552222;}#mermaid-svg-1fiqPsJfErv6AV82 .error-text{fill:#552222;stroke:#…

安卓基于 FirebaseAuth 实现 google 登录

安卓基于 FirebaseAuth 实现 google 登录 文章目录安卓基于 FirebaseAuth 实现 google 登录1. 前期准备1.1 创建 Firebase 项目1.2 将 Android 应用连接到 Firebase1.3 在 Firebase 控制台中启用 Google 登录2. 在 Android 应用中实现 Google 登录2.1 初始化 GoogleSignInClien…

李宏毅(Deep Learning)--(三)

一.前向传播与反向传播的理解&#xff1a;二.模型训练遇到的问题在模型训练中&#xff0c;我们可能会遇到效果不好的情况&#xff0c;那么我们应该怎么思考切入&#xff0c;找到问题所在呢&#xff1f;流程图如下&#xff1a;第一个就是去看训练的损失函数值情况。如果损失较大…

android studio 运行,偶然会导致死机,设置Memory Settings尝试解决

1、android studio导致死机 鼠标不能动&#xff0c;键盘没有反应&#xff0c;只能硬重启&#xff0c;但是内存并没有用完&#xff0c;cpu也不是100% 2、可能的原因 android studio内存设置的问题&#xff0c;为了限制占用内存&#xff0c;所以手工设置内存最小的一个&#x…

HTB 赛季8靶场 - Outbound

Rustscan扫描我们开局便拥有账号 tyler / LhKL1o9Nm3X2&#xff0c;我们使用rustscan进行扫描 rustscan -a 10.10.11.77 --range 1-65535 --scan-order "Random" -- -A Web服务漏洞探查 我们以账号tyler / LhKL1o9Nm3X2登录webmail&#xff0c;并快速确认版本信息。该…

动态组件和插槽

[Vue2]动态组件和插槽 动态组件和插槽来实现外部传入自定义渲染 组件 <template><!-- 回复的处理进度 --><div v-if"steps.length > 0" class"gain-box-header"><el-steps direction"vertical"><div class"l…

Unreal5从入门到精通之如何实现UDP Socket通讯

文章目录 一.前言二.什么是FSocket1. FSocket的作用2. FSocket关键特性三.创建Socket四.数据传输五.线程安全六.UDPSocketComponentUDPSocketComponent.hUUDPSocketComponent.cpp七.SocketTest测试八.最后一.前言 我们在开发UE 的过程中,会经常使用到Socket通讯,包括TCP,UD…

UI前端大数据处理新趋势:基于边缘计算的数据处理与响应

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;前端大数据的 “云端困境” 与边缘计算的破局当用户在在线文档中实时协作…

Reading and Writing to a State Variable

本节是《Solidity by Example》的中文翻译与深入讲解&#xff0c;专为零基础或刚接触区块链开发的小白朋友打造。我们将通过“示例 解说 提示”的方式&#xff0c;带你逐步理解每一段 Solidity 代码的实际用途与背后的逻辑。Solidity 是以太坊等智能合约平台使用的主要编程语…

c# 深度解析:实现一个通用配置管理功能,打造高并发、可扩展的配置管理神器

文章目录深入分析 ConfigManager<TKey, TValue> 类1. 类设计概述2. 核心成员分析2.1 字段和属性2.2 构造函数3. 数据加载机制4. CRUD 操作方法4.1 添加数据4.2 删除数据4.3 更新数据4.4 查询数据4.5 清空数据5. 数据持久化6. 设计亮点7. 使用示例ConfigManager<TKey, …

运维打铁: Python 脚本在运维中的常用场景与实现

文章目录引言思维导图常用场景与代码实现1. 服务器监控2. 文件管理3. 网络管理4. 自动化部署总结注意事项引言 在当今的 IT 运维领域&#xff0c;自动化和效率是至关重要的。Python 作为一种功能强大且易于学习的编程语言&#xff0c;已经成为运维人员不可或缺的工具。它可以帮…

【零基础入门unity游戏开发——unity3D篇】3D光源之——unity反射和反射探针技术

文章目录 前言实现天空盒反射1、新建一个cube2、全反射材质3、增加环境反射分辨率反射探针1、一样把小球材质调成全反射2、在小球身上加添加反射探针3、设置静态物体4、点击烘培5、效果6、可以修改反射探针区域大小7、实时反射专栏推荐完结前言 当对象收到直接和间接光照后,它…

React Three Fiber 实现 3D 模型点击高亮交互的核心技巧

在 WebGL 3D 开发中&#xff0c;模型交互是提升用户体验的关键功能之一。本文将基于 React Three Fiber&#xff08;R3F&#xff09;和 Three.js&#xff0c;总结 3D 模型点击高亮&#xff08;包括模型本身和边框&#xff09;的核心技术技巧&#xff0c;帮助开发者快速掌握复杂…

卷积神经网络实战:MNIST手写数字识别

夜渐深&#xff0c;我还在&#x1f618; 老地方 睡觉了&#x1f64c; 文章目录&#x1f4da; 卷积神经网络实战&#xff1a;MNIST手写数字识别&#x1f9e0; 4.1 预备知识⚙️ 4.1.1 torch.nn.Conv2d() 三维卷积操作&#x1f4cf; 4.1.2 nn.MaxPool2d() 池化层的作用&#x1f4…

HarmonyOS应用无响应(AppFreeze)深度解析:从检测原理到问题定位

HarmonyOS应用无响应&#xff08;AppFreeze&#xff09;深度解析&#xff1a;从检测原理到问题定位 在日常应用使用中&#xff0c;我们常会遇到点击无反应、界面卡顿甚至完全卡死的情况——这些都可能是应用无响应&#xff08;AppFreeze&#xff09; 导致的。对于开发者而言&am…

湖北设立100亿元人形机器人产业投资母基金

湖北设立100亿元人形机器人产业投资母基金 湖北工信 2025年07月08日 12:03 湖北 &#xff0c;时长01:20 近日&#xff0c;湖北设立100亿元人形机器人产业投资母基金&#xff0c;重点支持人形机器人和人工智能相关产业发展。 人形机器人产业投资母基金由湖北省财政厅依托省政府…

时序预测 | Pytorch实现CNN-LSTM-KAN电力负荷时间序列预测模型

预测效果 代码主要功能 该代码实现了一个结合CNN&#xff08;卷积神经网络&#xff09;、LSTM&#xff08;长短期记忆网络&#xff09;和KAN&#xff08;Kolmogorov-Arnold Network&#xff09;的混合模型&#xff0c;用于时间序列预测任务。主要流程包括&#xff1a; 数据加…

OCR 识别:车牌识别相机的 “火眼金睛”

车牌识别相机在交通管理、停车场收费等场景中&#xff0c;需快速准确识别车牌信息。但实际环境中&#xff0c;车牌可能存在污渍、磨损、光照不均等情况&#xff0c;传统识别方式易出现误读、漏读。OCR 技术让车牌识别相机如虎添翼。它能精准提取车牌上的字符&#xff0c;不管是…