[深度学习] imgaug边界框增强笔记
imgaug边界框增强笔记主要是讲述基于imgaug库对目标检测图像的边界框进行图像增强。本文需要掌握imgaug库的基本使用,imgaug库的基本使用见[深度学习] imgaug库使用笔记。
文章目录
0 示例图像和标注文件
示例图像如图所示
# 对应的标注文件
!cat demo.xml
<?xml version="1.0" ?>
<annotation>
<folder>demo</folder>
<filename>demo.jpg</filename>
<path>demo.jpg</path>
<source>
<database>Unknown</database>
</source>
<size>
<width>640</width>
<height>424</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
<name>person</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>187</xmin>
<ymin>93</ymin>
<xmax>276</xmax>
<ymax>378</ymax>
</bndbox>
</object>
<object>
<name>horse</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>390</xmin>
<ymin>138</ymin>
<xmax>602</xmax>
<ymax>345</ymax>
</bndbox>
</object>
<object>
<name>dog</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>61</xmin>
<ymin>256</ymin>
<xmax>207</xmax>
<ymax>348</ymax>
</bndbox>
</object>
</annotation>
1 imgaug加载图像和标注数据
标注文件的数据信息需要从外部读取后放入imgaug的BoundingBox类中,本文标注文件的数据信息通过BeautifulSoup读取。BeautifulSoup学习文章见使用 Beautiful Soup。具体代码如下。
from bs4 import BeautifulSoup
import imgaug as ia
import imageio
from imgaug.augmentables.bbs import BoundingBox, BoundingBoxesOnImage
from imgaug import augmenters as iaa
# 打开标注文件
soup = BeautifulSoup(open('demo.xml'),"lxml")
# 导入图像
image = imageio.imread("demo.jpg")
# 用于存放标注文件边界框信息
bbsOnImg=[]
# 找到所有包含框选目标的节点
for objects in soup.find_all(name="object"):
# 获得当前边界框的分类名
object_name = str(objects.find(name="name").string)
# 提取坐标点信息
xmin = int(objects.xmin.string)
ymin = int(objects.ymin.string)
xmax = int(objects.xmax.string)
ymax = int(objects.ymax.string)
# 保存该边界框的信息
bbsOnImg.append(BoundingBox(x1=xmin, x2=xmax, y1=ymin, y2=ymax,label=object_name))
# 初始化imgaug的标选框数据
bbs = BoundingBoxesOnImage( bbsOnImg,shape=image.shape)
# 展示结果
ia.imshow(bbs.draw_on_image(image, size=2))
2 边界框增强
imgaug中的边界框增强有两种办法,一种是对整张图像增强,另外一种是根据边界框信息,图像部分区域增强。
2.1 整张图像增强
直接对整张图像进行增强,直接从imgaug增强效果示例中找示例代码,然后添加到iaa.Sequential()中叠加就可以实现图像增强。
# 增强效果
seq = iaa.Sequential([
iaa.GammaContrast(1.5),
iaa.Fliplr(1),
iaa.Cutout(fill_mode="constant", cval=255),
iaa.CoarseDropout(0.02, size_percent=0.15, per_channel=0.5),
])
# 输入增强前的图像和边框,得到增强后的图像和边框
image_aug, bbs_aug = seq(image=image, bounding_boxes=bbs)
# 可视化,size边框的宽度
ia.imshow(bbs_aug.draw_on_image(image_aug, size=2))
2.2 图像部分区域增强
imgaug可以只对边界框框选区域或者除边界框的区域进行图像增强,通过imgaug的BlendAlphaBoundingBoxes类实现。BlendAlphaBoundingBoxes类的接口说明如下:
classimgaug.augmenters.blend.BlendAlphaBoundingBoxes(labels, foreground=None, background=None, nb_sample_labels=None, seed=None, name=None, random_state='deprecated', deterministic='deprecated')
该类的常用参数为labels,foreground,background。labels表示对哪一类或哪几类的边界框进行处理,为None表示所有标签都处理。foreground设置对labels标注的边界框区域增强效果。background设置对除边界库区域增强效果。示例代码如下:
# demo1
seq = iaa.Sequential([
# background设置除了dog和person标选框之外的区域都涂黑
iaa.BlendAlphaBoundingBoxes(['dog','person'],background=iaa.Multiply(0.0)),
# 对整张图进行增强
#iaa.Cartoon()
])
# 输入增强前的图像和边框,得到增强后的图像和边框
image_aug, bbs_aug = seq(image=image, bounding_boxes=bbs)
# 可视化,size边框的宽度
ia.imshow(bbs_aug.draw_on_image(image_aug, size=2))
# demo2
seq = iaa.Sequential([
# label=None表示不选择特定标签,即对所以标签进行处理
iaa.BlendAlphaBoundingBoxes(None,foreground=iaa.Fog())
])
# 输入增强前的图像和边框,得到增强后的图像和边框
image_aug, bbs_aug = seq(image=image, bounding_boxes=bbs)
# 可视化,size边框的宽度
ia.imshow(bbs_aug.draw_on_image(image_aug, size=2))
# demo3
seq = iaa.Sequential([
# 前后景分别处理
iaa.BlendAlphaBoundingBoxes(["dog","person"],foreground=iaa.Fog(),background=iaa.Cartoon()),
# 整张图片增强效果
iaa.Fliplr(1)
])
# 输入增强前的图像和边框,得到增强后的图像和边框
image_aug, bbs_aug = seq(image=image, bounding_boxes=bbs)
# 可视化,size边框的宽度
ia.imshow(bbs_aug.draw_on_image(image_aug, size=2))
2.3 边界框超出图像范围解决办法
在[深度学习] imgaug库使用笔记中有提到不要图像旋转来增强边界框,很容易出现边界框超出图像范围,在imgaug中也提供了相应的解决办法, 通过clip_out_of_image函数即可解决。尽管这样,还是不建议使用图像旋转增强边界框。
seq = iaa.Sequential([
iaa.Affine(rotate=80)
])
# 输入增强前的图像和边框,得到增强后的图像和边框
image_aug, bbs_aug = seq(image=image, bounding_boxes=bbs)
# 可视化,size边框的宽度
ia.imshow(bbs_aug.draw_on_image(image_aug, size=2))
# 显示边界框结果,可以看到dog和horse的边界框范围超过图像。
bbs_aug
BoundingBoxesOnImage([BoundingBox(x1=133.4267, y1=60.3564, x2=429.5516, y2=197.4940, label=person), BoundingBox(x1=201.1759, y1=268.0866, x2=441.8446, y2=512.8110, label=horse), BoundingBox(x1=141.0913, y1=-35.4247, x2=257.0462, y2=124.3329, label=dog)], shape=(424, 640, 3))
# 删除超过图像范围的边界框范围
bbs_aug_clip =bbs_aug.clip_out_of_image()
# 可视化
ia.imshow(bbs_aug_clip.draw_on_image(image_aug, size=2))
bbs_aug_clip
BoundingBoxesOnImage([BoundingBox(x1=133.4267, y1=60.3564, x2=429.5516, y2=197.4940, label=person), BoundingBox(x1=201.1759, y1=268.0866, x2=441.8446, y2=424.0000, label=horse), BoundingBox(x1=141.0913, y1=0.0000, x2=257.0462, y2=124.3329, label=dog)], shape=(424, 640, 3))
3 保存增强图像和标注文件
xml标注文件保存参考python如何读取&生成voc xml格式标注信息。可自行修改相关代码。本文保存代码如下。
# xml文件生成代码
from lxml import etree
# ---- 创建标注
class CreateAnnotations:
# ----- 初始化
def __init__(self, flodername, filename):
self.root = etree.Element("annotation")
child1 = etree.SubElement(self.root, "folder")
child1.text = flodername
child2 = etree.SubElement(self.root, "filename")
child2.text = filename
child3 = etree.SubElement(self.root, "path")
child3.text = filename
child4 = etree.SubElement(self.root, "source")
child5 = etree.SubElement(child4, "database")
child5.text = "Unknown"
# ----- 设置size
def set_size(self, imgshape):
(height, witdh, channel) = imgshape
size = etree.SubElement(self.root, "size")
widthn = etree.SubElement(size, "width")
widthn.text = str(witdh)
heightn = etree.SubElement(size, "height")
heightn.text = str(height)
channeln = etree.SubElement(size, "depth")
channeln.text = str(channel)
# ----- 保存文件
def savefile(self, filename):
tree = etree.ElementTree(self.root)
tree.write(filename, pretty_print=True, xml_declaration=False, encoding='utf-8')
def add_pic_attr(self, label, xmin, ymin, xmax, ymax):
object = etree.SubElement(self.root, "object")
namen = etree.SubElement(object, "name")
namen.text = label
bndbox = etree.SubElement(object, "bndbox")
xminn = etree.SubElement(bndbox, "xmin")
xminn.text = str(xmin)
yminn = etree.SubElement(bndbox, "ymin")
yminn.text = str(ymin)
xmaxn = etree.SubElement(bndbox, "xmax")
xmaxn.text = str(xmax)
ymaxn = etree.SubElement(bndbox, "ymax")
ymaxn.text = str(ymax)
# 从imgaug中提取边界框信息并保存
foldername = "demo"
filename = "demo_aug.jpg"
# 创建保存类
anno = CreateAnnotations(foldername, filename)
#
anno.set_size(image_aug.shape)
# 循环提取
for index,bb in enumerate(bbs_aug_clip):
xmin = int(bb.x1)
ymin = int(bb.y1)
xmax = int(bb.x2)
ymax = int(bb.y2)
label = str(bb.label)
anno.add_pic_attr(label, xmin, ymin, xmax, ymax)
# 保存标注文件
anno.savefile("{}.xml".format(filename.split(".")[0]))
# 保存增强图像
imageio.imsave(filename, image_aug)
4 参考
[深度学习] imgaug边界框增强笔记的更多相关文章
- [深度学习] imgaug库使用笔记
imgaug是一款非常有用的python图像增强库,非常值得推荐应用于深度学习图像增强.其包含许多增强技术,支持图像分类,目标检测,语义分割,热图.关键点检测等一系列任务的图像增强.本文主要介绍img ...
- Coursera深度学习(DeepLearning.ai)编程题&笔记
因为是Jupyter Notebook的形式,所以不方便在博客中展示,具体可在我的github上查看. 第一章 Neural Network & DeepLearning week2 Logi ...
- deeplearning.ai 改善深层神经网络 week1 深度学习的实用层面 听课笔记
1. 应用机器学习是高度依赖迭代尝试的,不要指望一蹴而就,必须不断调参数看结果,根据结果再继续调参数. 2. 数据集分成训练集(training set).验证集(validation/develop ...
- deeplearning.ai 神经网络和深度学习 week4 深层神经网络 听课笔记
1. 计算深度神经网络的时候,尽量向量化数据,不要用for循环.唯一用for循环的地方是依次在每一层做计算. 2. 最常用的检查代码是否有错的方法是检查算法中矩阵的维度. 正向传播: 对于单个样本,第 ...
- 深度学习-Wasserstein GAN论文理解笔记
GAN存在问题 训练困难,G和D多次尝试没有稳定性,Loss无法知道能否优化,生成样本单一,改进方案靠暴力尝试 WGAN GAN的Loss函数选择不合适,使模型容易面临梯度消失,梯度不稳定,优化目标不 ...
- 深度学习-语言处理特征提取 Word2Vec笔记
Word2Vec的主要目的适用于词的特征提取,然后我们就可以用LSTM等神经网络对这些特征进行训练. 由于机器学习无法直接对文本信息进行有效的处理,机器学习只对数字,向量,多维数组敏感,所以在进行文本 ...
- 深度学习-生成对抗网络GAN笔记
生成对抗网络(GAN)由2个重要的部分构成: 生成器G(Generator):通过机器生成数据(大部分情况下是图像),目的是“骗过”判别器 判别器D(Discriminator):判断这张图像是真实的 ...
- 深度学习-DCGAN论文的理解笔记
训练方法DCGAN 的训练方法跟GAN 是一样的,分为以下三步: (1)for k steps:训练D 让式子[logD(x) + log(1 - D(G(z)) (G keeps still)]的值 ...
- 深度学习框架 Torch 7 问题笔记
深度学习框架 Torch 7 问题笔记 1. 尝试第一个 CNN 的 torch版本, 代码如下: -- We now have 5 steps left to do in training our ...
随机推荐
- 一文讲清楚 JVM Safe Point
大家好,我是树哥. 关于 Safe Point 是 JVM 中很关键的一个概念,但我估计有不少同学不是很懂.于是今天跟大家来深入聊聊 Safe Point,希望通过这篇文章能解答这样几个问题: 什么是 ...
- 代码随想录第十三天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素
第一题150. 逆波兰表达式求值 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 注意 两个整数之间的除法只保留整数部分. ...
- 会话跟踪技术 - Cookie 和 Session 快速上手 + 登陆注册案例
目录 1. 会话跟踪技术概述 2. Cookie 2.1 Cookie的概念和工作流程 2.2 Cookie的基本使用 2.3 Cookie的原理分析 2.4 Cookie的使用细节 2.4.1 Co ...
- 云原生时代的DevOps平台设计之道
开发人员与运维人员是 IT 领域很重要的两大人群,他们都会参与到各种业务系统的建设过程中去.DevOps 是近年间火爆起来的一种新理念,这种理念被很多人错误的解读为"由开发人员(Dev)学习 ...
- 【lwip】08-ARP协议一图笔记及源码实现
目录 前言 8.1 IP地址与MAC地址 8.2 ARP协议简介 8.3 ARP协议报文 8.4 ARP缓存表 8.4.1 ARP缓存表简介 8.4.2 LWIP中的缓存表 8.4.3 ARP缓存表数 ...
- SpringBoot 01: JavaConfig + @ImportResource + @PropertyResource
springboot的前置知识:通过注解创建对象和读取配置文件 1. JavaConfig 设计思想 使用java类作为xml配置文件的替代,是配置spring容器的纯java的方式 可以创建java ...
- 第一百零七篇:基本数据类型(undefined,null,boolean类型)
好家伙, 本篇内容为<JS高级程序设计>第三章学习笔记 1.数据类型 ECMAScript有6种简单数据类型(称为原始类型): Undefined, Null, Boolean, Numb ...
- 优秀的Kafka GUI客户端、可视化管理工具、监控工具
想要查看Topic里的消息却找不到软件,想要查看或更新Broker.Topic配置,想要监控Broker服务器状态?试试下面的Kafka GUI工具--Kafka Assistant 官网地址:htt ...
- .NET二叉树,递归和迭代遍历二叉树
代码随想录: https://programmercarl.com .NET中二叉树的定义 public class TreeNode { public int val; public TreeNod ...
- 基于python的数学建模---传染病六个模型
六个模型的区别 SI-Model import scipy.integrate as spi import numpy as np import matplotlib.pyplot as plt # ...