当前位置: 首页 > news >正文

目标检测数据集图片及标签同步旋转角度

前言

在深度学习领域,尤其是目标检测任务中,数据集的质量直接影响模型的性能。为了提升模型的鲁棒性和对各种场景的适应能力,数据增强技术被广泛应用于图像数据集处理。旋转角度是常见的数据增强方法,通过对图像及其对应的标签(边界框)进行同步旋转,可以有效地增加模型对不同方向目标的识别能力。然而,在进行旋转变换时,除了图像本身需要旋转外,与之对应的标签(边界框)也需要进行同步更新。否则,标签位置的偏差将导致模型训练出现误差,甚至无法正确识别目标。

本篇文章将介绍如何在目标检测数据集中的图像和标签(边界框)同步旋转(仍为矩形)。通过同步旋转图像和标签,能够确保数据增强过程中图像与标签的一致性,从而提高模型训练的效果和准确性。

效果如图,倾斜旋转。

代码

import os
import cv2
import math
import shutil
import numpy as np
from lxml import etree, objectifyclass ImageXMLProcessor:def __init__(self, input_img_folder, input_xml_folder, output_img_folder, output_xml_folder, rotation_angle=5, scale=1):self.input_img_folder = input_img_folderself.input_xml_folder = input_xml_folderself.output_img_folder = output_img_folderself.output_xml_folder = output_xml_folderself.rotation_angle = rotation_angleself.scale = scaleos.makedirs(self.output_img_folder, exist_ok=True)os.makedirs(self.output_xml_folder, exist_ok=True)def rotate_img_bbox(self, img, bboxes, angle=5, scale=1.):w = img.shape[1]h = img.shape[0]rangle = np.deg2rad(angle)nw = (abs(np.sin(rangle) * h) + abs(np.cos(rangle) * w)) * scalenh = (abs(np.cos(rangle) * h) + abs(np.sin(rangle) * w)) * scalerot_mat = cv2.getRotationMatrix2D((nw * 0.5, nh * 0.5), angle, scale)rot_move = np.dot(rot_mat, np.array([(nw - w) * 0.5, (nh - h) * 0.5, 0]))rot_mat[0, 2] += rot_move[0]rot_mat[1, 2] += rot_move[1]rot_img = cv2.warpAffine(img, rot_mat, (int(math.ceil(nw)), int(math.ceil(nh))), flags=cv2.INTER_LANCZOS4)rot_bboxes = list()for bbox in bboxes:xmin = bbox[0]ymin = bbox[1]xmax = bbox[2]ymax = bbox[3]point1 = np.dot(rot_mat, np.array([(xmin + xmax) / 2, ymin, 1]))point2 = np.dot(rot_mat, np.array([xmax, (ymin + ymax) / 2, 1]))point3 = np.dot(rot_mat, np.array([(xmin + xmax) / 2, ymax, 1]))point4 = np.dot(rot_mat, np.array([xmin, (ymin + ymax) / 2, 1]))concat = np.vstack((point1, point2, point3, point4))concat = concat.astype(np.int32)rx, ry, rw, rh = cv2.boundingRect(concat)rx_min = rxry_min = ryrx_max = rx + rwry_max = ry + rhrot_bboxes.append([rx_min, ry_min, rx_max, ry_max])return rot_img, rot_bboxesdef save_xml(self, file_name, save_folder, img_info, height, width, channel, bboxs_info):folder_name, img_name = img_info  # 得到图片的信息E = objectify.ElementMaker(annotate=False)# 创建 XML 树结构anno_tree = E.annotation(E.folder(folder_name),E.filename(img_name),E.path(os.path.join(folder_name, img_name)),E.source(E.database('Unknown'),),E.size(E.width(width),E.height(height),E.depth(channel)),E.segmented(0),)labels, bboxs = bboxs_info  # 得到边框和标签信息for label, box in zip(labels, bboxs):anno_tree.append(E.object(E.name(label),E.pose('Unspecified'),E.truncated('0'),E.difficult('0'),E.bndbox(E.xmin(box[0]),E.ymin(box[1]),E.xmax(box[2]),E.ymax(box[3]))))os.makedirs(save_folder, exist_ok=True)file_path = os.path.join(save_folder, file_name)etree.ElementTree(anno_tree).write(file_path, pretty_print=True, xml_declaration=True, encoding="UTF-8")print(f"XML 文件已保存到: {file_path}")def update_bboxes_in_xml(self, xml_path, bboxes):tree = etree.parse(xml_path)root = tree.getroot()# 找到所有的 <object> 元素并更新对应的 <bndbox> 坐标obj_elements = root.findall("object")for idx, object_element in enumerate(obj_elements):# 获取原始的 bndboxbndbox_element = object_element.find("bndbox")if bndbox_element is not None:# 只有当 bbox 存在时才更新xmin_element = bndbox_element.find("xmin")ymin_element = bndbox_element.find("ymin")xmax_element = bndbox_element.find("xmax")ymax_element = bndbox_element.find("ymax")# 更新坐标if idx < len(bboxes):bbox = bboxes[idx]xmin_element.text = str(bbox[0])ymin_element.text = str(bbox[1])xmax_element.text = str(bbox[2])ymax_element.text = str(bbox[3])# 保存更新后的 XML 文件tree.write(xml_path, pretty_print=True, xml_declaration=True, encoding="UTF-8")print(f"XML 文件已更新并保存到: {xml_path}")def process(self):# 遍历输入文件夹中的所有图片和XML文件for img_file in os.listdir(self.input_img_folder):if img_file.endswith('.jpg') or img_file.endswith('.png'):  # 支持jpg/png格式# 获取对应的XML文件xml_file = os.path.splitext(img_file)[0] + '.xml'img_path = os.path.join(self.input_img_folder, img_file)xml_path = os.path.join(self.input_xml_folder, xml_file)if os.path.exists(xml_path):shutil.copy(xml_path, self.output_xml_folder)img = cv2.imread(img_path)height, width, channel = img.shapetree = etree.parse(xml_path)root = tree.getroot()labels = []bboxes = []for obj in root.findall('object'):label = obj.find('name').textxmin = int(obj.find('bndbox/xmin').text)ymin = int(obj.find('bndbox/ymin').text)xmax = int(obj.find('bndbox/xmax').text)ymax = int(obj.find('bndbox/ymax').text)labels.append(label)bboxes.append([xmin, ymin, xmax, ymax])rotated_img, rotated_bboxes = self.rotate_img_bbox(img, bboxes, self.rotation_angle, self.scale)output_img_path = os.path.join(self.output_img_folder, img_file)cv2.imwrite(output_img_path, rotated_img)output_xml_path = os.path.join(self.output_xml_folder, xml_file)self.save_xml(xml_file, self.output_xml_folder, ('folder_name', img_file), height, width, channel, (labels, rotated_bboxes))else:print(f"XML 文件不存在: {xml_path}")if __name__ == "__main__":input_img_folder = r"E:\data\x1"  # 输入图片文件夹input_xml_folder = r"E:\data\x2"  # 输入 XML 文件夹output_img_folder = r"E:\data\y1"  # 输出图片文件夹output_xml_folder = r"E:\data\y2"  # 输出 XML 文件夹rotation_angle = 5  # 旋转角度scale = 1 #图片尺寸,默认为1processor = ImageXMLProcessor(input_img_folder, input_xml_folder, output_img_folder, output_xml_folder, rotation_angle, scale)processor.process()

相关文章:

目标检测数据集图片及标签同步旋转角度

前言 在深度学习领域&#xff0c;尤其是目标检测任务中&#xff0c;数据集的质量直接影响模型的性能。为了提升模型的鲁棒性和对各种场景的适应能力&#xff0c;数据增强技术被广泛应用于图像数据集处理。旋转角度是常见的数据增强方法&#xff0c;通过对图像及其对应的标签&am…...

2025前端面试热门题目——计算机网络篇

计算机网络篇——面试 1. 到底什么是 TCP 连接? TCP 连接的定义 TCP&#xff08;传输控制协议&#xff09;是一个面向连接的传输层协议。TCP 连接是通过 三次握手 确立的可靠数据通信链路&#xff0c;保证了在不可靠网络&#xff08;如互联网&#xff09;上的数据传输的准确…...

LEAST-TO-MOST PROMPTING ENABLES COMPLEX REASONING IN LARGE LANGUAGE MODELS---正文

题目 最少到最多的提示使大型语言模型能够进行复杂的推理 论文地址&#xff1a;https://arxiv.org/abs/2205.10625 摘要 思路链提示在各种自然语言推理任务中表现出色。然而&#xff0c;它在需要解决比提示中显示的示例更难的问题的任务上表现不佳。为了克服这种由易到难的概括…...

Java开发经验——日志治理经验

摘要 本文主要介绍了Java开发中的日志治理经验&#xff0c;包括系统异常日志、接口摘要日志、详细日志和业务摘要日志的定义和目的&#xff0c;以及错误码规范和异常处理规范。强调了日志治理的重要性和如何通过规范化错误码和日志格式来提高系统可观测性和问题排查效率。 1. …...

使用复数类在C#中轻松绘制曼德布洛集分形

示例在 C# 中绘制曼德布洛特集分形解释了如何通过迭代以下方程来绘制曼德布洛特集&#xff1a; 其中 Z(n) 和 C 是复数。程序迭代此方程&#xff0c;直到 Z(n) 的大小至少为 2 或程序执行最大迭代次数。 该示例在单独的变量中跟踪数字的实部和虚部。此示例使用Complex类来更轻松…...

VSCode 启用免费 Copilot

升级VSCode到 1.96版本&#xff0c;就可以使用每个月2000次免费额度了&#xff0c;按照工作日每天近80次免费额度&#xff0c;满足基本需求。前两天一直比较繁忙&#xff0c;今天周六有时间正好体验一下。 引导插件安装GitHub Copilot - Visual Studio Marketplace Extension f…...

常见问题整理

DevOps 和 CICD DevOps 全称Development & Operation 一种实现开发和运维一体化的协同模式&#xff0c;提供快速交付应用和服务的能力 用于协作&#xff1a;开发&#xff0c;部署&#xff0c;质量测试 整体生命周期工作内容&#xff0c;最终实现持续继承&#xff0c;持续部…...

使用Vue创建前后端分离项目的过程(前端部分)

前端使用Vue.js作为前端开发框架&#xff0c;使用Vue CLI3脚手架搭建项目&#xff0c;使用axios作为HTTP库与后端API交互&#xff0c;使用Vue-router实现前端路由的定义、跳转以及参数的传递等&#xff0c;使用vuex进行数据状态管理&#xff0c;后端使用Node.jsexpress&#xf…...

【Springboot知识】Redis基础-springboot集成redis相关配置

文章目录 1. 添加依赖2. 配置Redis连接3. 配置RedisTemplate&#xff08;可选&#xff09;4. 使用RedisTemplate或StringRedisTemplate5. 测试和验证 集群配置在application.properties中配置在application.yml中配置 主从配置1. 配置Redis服务器使用配置文件使用命令行 2. 配置…...

网络安全概论——身份认证

一、身份证明 身份证明可分为以下两大类 身份验证——“你是否是你所声称的你&#xff1f;”身份识别——“我是否知道你是谁&#xff1f;” 身份证明系统设计的三要素&#xff1a; 安全设备的系统强度用户的可接受性系统的成本 实现身份证明的基本途径 所知&#xff1a;个…...

OpenHarmony-4.HDI 框架

HDI 框架 1.HDI介绍 HDI&#xff08;Hardware Device Interface&#xff0c;硬件设备接口&#xff09;是HDF驱动框架为开发者提供的硬件规范化描述性接口&#xff0c;位于基础系统服务层和设备驱动层之间&#xff0c;是连通驱动程序和系统服务进行数据流通的桥梁&#xff0c;是…...

leecode494.目标和

这道题目第一眼感觉就不像是动态规划&#xff0c;可以看出来是回溯问题&#xff0c;但是暴力回溯超时&#xff0c;想要用动态规划得进行一点数学转换 class Solution { public:int findTargetSumWays(vector<int>& nums, int target) {int nnums.size(),bagWeight0,s…...

在Spring中application 的配置属性(详细)

application 的配置属性。 这些属性是否生效取决于对应的组件是否声明为 Spring 应用程序上下文里的 Bean &#xff08;基本是自动配置 的&#xff09;&#xff0c;为一个不生效的组件设置属性是没有用的。 multipart multipart.enabled 开启上传支持&#xff08;默认&a…...

jvm符号引用和直接引用

在解析阶段中,符号引用和直接引用是Java类加载和内存管理中的重要概念,它们之间存在显著的区别。以下是对这两个概念的详细解析: 一、定义与特性 符号引用(Symbolic Reference) 定义:符号引用是编译器生成的用于表示类、方法、字段等的引用方式。特性: 独立性:符号引用…...

一文流:JVM精讲(多图提醒⚠️)

一文流系列是作者苦于技术知识学了-忘了,背了-忘了的苦恼,决心把技术知识的要点一笔笔✍️出来,一图图画出来,一句句讲出来,以求刻在🧠里。 该系列文章会把核心要点提炼出来,以求掌握精髓,至于其他细节,写在文章里,留待后续回忆。 目前进度请查看: :::info https:/…...

python 分段拟合笔记

效果图: 源代码: import numpy as np import cv2 import matplotlib.pyplot as plt from numpy.polynomial.polynomial import Polynomialdef nihe(x_points,y_points,p_id):# 按照 p_id 将 points 分成两组group_0_x = []group_0_y = []group_1_x = []group_1_y = []for i, …...

Mysql索引类型总结

按照数据结构维度划分&#xff1a; BTree 索引&#xff1a;MySQL 里默认和最常用的索引类型。只有叶子节点存储 value&#xff0c;非叶子节点只有指针和 key。存储引擎 MyISAM 和 InnoDB 实现 BTree 索引都是使用 BTree&#xff0c;但二者实现方式不一样&#xff08;前面已经介…...

数据结构——队列的模拟实现

大家好&#xff0c;上一篇博客我带领大家进行了数据结构当中的栈的模拟实现 今天我将带领大家实现一个新的数据结构————队列 一&#xff1a;队列简介 首先来认识一下队列&#xff1a; 队列就像我们上学时的排队一样&#xff0c;有一个队头也有一个队尾。 有人入队的话就…...

在window环境下安装openssl生成钥私、证书和签名,nodejs利用express实现ssl的https访问和测试

在生成我们自己的 SSL 证书之前&#xff0c;让我们创建一个简单的 Express应用程序。 要创建一个新的 Express 项目&#xff0c;让我们创建一个名为node-ssl -server 的目录&#xff0c;用终端cmd中进入node-ssl-server目录。 cd node-ssl-server 然后初始化一个新的 npm 项目…...

Redis 最佳实践

这是以前写下来的文章&#xff0c;发出来备份一下 Redis 在企业中的最佳实践可以帮助提高性能、可用性和数据管理效率。以下是一些推荐的做法&#xff1a; 选择合适的数据结构&#xff1a; 根据需求选择适当的 Redis 数据结构&#xff08;如 Strings、Lists、Sets、Hashes、So…...

5个理由告诉你为什么Karate是API测试自动化的终极解决方案

5个理由告诉你为什么Karate是API测试自动化的终极解决方案 【免费下载链接】karate Test Automation Made Simple 项目地址: https://gitcode.com/gh_mirrors/ka/karate Karate测试框架是一个革命性的开源工具&#xff0c;它将API测试、Mock服务、性能测试和UI自动化完美…...

android c++版opencv截图效果range1 range2

matmat(Range(0,500),Range(0,300));range1就是高度范围 0-500 range2就是宽度范围 0-300 后面的小图片就是切出来的原图片左上角的部分。...

2026年,天津市专业初高中辅导辅导班名声究竟几何?快来一探究竟!

在天津&#xff0c;初高中辅导市场竞争激烈&#xff0c;众多家长和学生都在寻找靠谱的辅导机构。2026年&#xff0c;方舟优学&#xff08;天津&#xff09;教育科技有限公司在这片市场中脱颖而出&#xff0c;下面我们就来深入了解一下它以及其他一些知名机构的情况。一、方舟优…...

如何快速实现跨平台输入法词库转换:开源工具的完整指南

如何快速实现跨平台输入法词库转换&#xff1a;开源工具的完整指南 【免费下载链接】imewlconverter ”深蓝词库转换“ 一款开源免费的输入法词库转换程序 项目地址: https://gitcode.com/gh_mirrors/im/imewlconverter 你是否曾经因为更换操作系统或输入法而丢失了多年…...

Open Liberty Docker镜像深度解析:企业级Java应用容器化部署实战

1. 项目概述&#xff1a;一个企业级Java应用服务器的开源镜像 如果你在Java企业级应用开发领域摸爬滚打过几年&#xff0c;尤其是和WebSphere家族的产品打过交道&#xff0c;那么“Liberty”这个名字你一定不陌生。它代表着一种轻量、快速、模块化的Java EE&#xff08;现在叫J…...

Linux下串口连接与CircuitPython开发实战指南

1. 项目概述&#xff1a;为什么串口是嵌入式开发的“生命线” 如果你玩过Arduino、树莓派Pico&#xff0c;或者正在捣鼓CircuitPython开发板&#xff0c;那么“串口”这个词对你来说一定不陌生。它就像一条看不见的数据管道&#xff0c;连接着你的电脑和那块小小的开发板。在W…...

Android定位模拟技术全解析:Xposed Hook实现位置伪造的完整指南

Android定位模拟技术全解析&#xff1a;Xposed Hook实现位置伪造的完整指南 【免费下载链接】FakeLocation Xposed module to mock locations per app. 项目地址: https://gitcode.com/gh_mirrors/fak/FakeLocation 在移动应用开发和测试领域&#xff0c;Android定位模拟…...

Cadence Allegro 17.4 新手避坑指南:从原理图库到网表输出的完整流程

Cadence Allegro 17.4 新手避坑指南&#xff1a;从原理图库到网表输出的完整流程 第一次打开Allegro 17.4时&#xff0c;那个漆黑的界面就像工程师职业生涯的暗黑副本——你以为只是画个电路图&#xff0c;系统却用各种报错教你重新做人。我见过太多新手在中文路径报错面前崩溃…...

通过 Taotoken CLI 工具一键配置开发环境中的多工具 API 端点

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 通过 Taotoken CLI 工具一键配置开发环境中的多工具 API 端点 在接入多个大模型服务时&#xff0c;开发者常常需要为不同的工具和 …...

Topit终极指南:如何在Mac上高效管理窗口置顶,提升多任务处理效率

Topit终极指南&#xff1a;如何在Mac上高效管理窗口置顶&#xff0c;提升多任务处理效率 【免费下载链接】Topit Pin any window to the top of your screen / 在Mac上将你的任何窗口强制置顶 项目地址: https://gitcode.com/gh_mirrors/to/Topit 在当今多任务工作环境中…...