imgaug Augment Polygons 对标注图片和polygons的数据增强

news/2024/11/26 7:15:14/

对于本地化进行图像的增强,大家都是非常好操作的。但是,对于标注信息一起增强,还是稍微有一些难度的,麻烦很多。

我是遇到一个数据集非常少的任务,只有40张图。就直接标记了去训练,发现几乎不拟合,当然这里使用的是yolo v8,而不是UNet。

于是,先本地化给增强到50倍数据集,然后再去训练,说不定是个好的方法。这里采用的就是imgaug的开源库,学习参考如下:

  1. imgaug 地址
  2. 官方文档
  3. Augment Polygons

一、单张实验下

1、首先,是采用labelme标注的一张图像,如下,是用labelme打开时候看到的内容:

在这里插入图片描述

imgaug查看原图和标记内容,如下:

import imageio
import imgaug as ia
import json
import numpy as np
from imgaug.augmentables.polys import Polygon, PolygonsOnImageclass LabelJson(object):def __init__(self, abs_path=None) -> None:super().__init__()self.abs_path = abs_pathself.read()def read(self):with open(self.abs_path, 'r', encoding='utf-8') as f:lj = json.load(f)self.wh = [lj.get('imageWidth'), lj.get('imageHeight')]shapes = lj.get('shapes')self.cls = [i.get('label') for i in shapes]  # '1305' if i.get('label') == '14' elsepoints = [i.get('points') for i in shapes]points = [np.array(i, dtype=np.int32).reshape((-1, 2)) for i in points]self.loc = pointsself.box = [[j[:, 0].min(), j[:, 1].min(), j[:, 0].max(), j[:, 1].max()] for j in points]self.img_name = lj.get('imagePath')self.is_pos = bool(self.cls)return selfimg_path = r"F:\tmp\png/catDog.jpg"
json_path = r'F:\tmp\png\catDog.json'
image = imageio.imread(img_path)
json_info = LabelJson(json_path)print(image.shape)ia.imshow(image)image_polys = np.copy(image)
for point in json_info.loc:meerkat = Polygon(point)image_polys = meerkat.draw_on_image(image_polys, alpha_face=0.2, size_points=7)ia.imshow(image_polys)

显示的图片内容:

在这里插入图片描述

2、开始进行第一次数据增强,不改变形状,加入高斯噪声等等操作

#  let's convert our polygons to an PolygonsOnImage instance:
psoi = ia.PolygonsOnImage([Polygon(point) for point in json_info.loc],shape=image.shape)import imgaug.augmenters as iaa
ia.seed(1)# add aug
aug = iaa.Sequential([iaa.AdditiveGaussianNoise(scale=10),iaa.CoarseDropout(0.1, size_px=8),iaa.AddToHueAndSaturation((-50, 50))
])image_aug, psoi_aug = aug(image=image, polygons=psoi)
ia.imshow(psoi_aug.draw_on_image(image_aug, alpha_face=0.2, size_points=7))

下面就是增强后的结果:

在这里插入图片描述

3、接下来进行第二次的增强,这次加入形状和位置调整。

# add aug 2
aug = iaa.Sequential([iaa.Affine(translate_percent={"x": 0.2, "y": 0.1}),iaa.Fliplr(1.0)
])image_aug, psoi_aug = aug(image=image, polygons=psoi)
ia.imshow(psoi_aug.draw_on_image(image_aug, alpha_face=0.2, size_points=7))

展示如下所示:

在这里插入图片描述

4、增强后的坐标,转化为labelme可以读取的json形式保存,再打开查看,这也是大多数我们需要做的目的。如下操作:

import base64, os
from PIL import Image
import io
import json
import cv2
def base64encode_img(src_image):# src_image = Image.open(image_path)src_image = Image.fromarray(cv2.cvtColor(src_image, cv2.COLOR_BGR2RGB))output_buffer = io.BytesIO()src_image.save(output_buffer, format='JPEG')byte_data = output_buffer.getvalue()base64_str = base64.b64encode(byte_data).decode('utf-8')return base64_strdef savejson(points_list, clses_list, img_tmp, filename, save_dir):A = dict()listbigoption = []for cls, points in zip(clses_list, points_list):listobject = dict()listobject['points'] = pointslistobject['line_color'] = 'null'listobject['label'] = clslistobject['fill_color'] = 'null'listbigoption.append(listobject)A['imageData'] = base64encode_img(img_tmp)A['imagePath'] = filenameA['shapes'] = listbigoptionA['flags'] = {}print(A)saveJson_path = os.path.join(save_dir, 'json')os.makedirs(saveJson_path, exist_ok=True)suffix = os.path.splitext(filename)[-1]with open(saveJson_path + "/" + filename.replace(suffix, ".json"), 'w', encoding='utf-8') as f:json.dump(A, f, indent=2, ensure_ascii=False)image_aug, psoi_aug = aug(image=image, polygons=psoi)
print(psoi_aug)points_list = []
for pos in psoi_aug:print('pos:', pos)points = [list(xy.astype(np.float64)) for xy in pos]print('points:', points)points_list.append(points)image_augRGB = cv2.cvtColor(image_aug, cv2.COLOR_BGR2RGB)
savejson(points_list, json_info.cls, image_augRGB, os.path.basename(img_path), r'F:\tmp\png\aug')
# ia.imshow(psoi_aug.draw_on_image(image_aug, alpha_face=0.2, size_points=7))
ia.imshow(image_aug)
cv2.imwrite(os.path.join(r'F:\tmp\png\aug', os.path.basename(img_path)), image_augRGB)

直接保存的是BGR,需要转到RGB进行保存

在这里插入图片描述
增强后,存储到本地,用labelme再次打开查看,如下(暂未做小于0的截断处理):

在这里插入图片描述

加入截断操作,如下:

image_aug, psoi_aug = aug(image=image, polygons=psoi)
print(psoi_aug)
nw, nh, _ = image_aug.shapepoints_list = []
for pos in psoi_aug:print('pos:', pos)points = [list(xy.astype(np.float64)) for xy in pos]print('points:', points)for p in points:if p[0]<0:p[0] = 0elif p[0]>nh:p[0] = nhif p[1]<0:p[1] = 0elif p[1]>nw:p[1] = nwpoints_list.append(points)

展示如下:

在这里插入图片描述

数据增强,随机的产生2*4个图像,用于展示:

ia.seed(2)
aug = iaa.Sequential([iaa.OneOf([iaa.AdditiveGaussianNoise(scale=10),iaa.GaussianBlur(sigma=(0.0, 3.0)),]),iaa.Affine(rotate=(-20, 20), translate_percent=(-0.2, 0.2), scale=(0.8, 1.2),mode=["constant", "edge"], cval=0),  # 放射变换iaa.OneOf([iaa.Fliplr(0.5),    # 水平翻转iaa.Flipud(0.5),    # 上下翻转]),iaa.OneOf([iaa.GammaContrast((0.5, 2.0)),iaa.LinearContrast((0.8, 1.2), per_channel=0.5),]),iaa.AddToHueAndSaturation((-20, 20)),   # 通过随机值增加或减少色调和饱和度。iaa.Sometimes(0.75, iaa.Snowflakes())
])images_polys_aug = []
for _ in range(2*4):image_aug, psoi_aug = aug(image=image, polygons=psoi)image_polys_aug = psoi_aug.draw_on_image(image_aug, alpha_face=0.2, size_points=11)images_polys_aug.append(ia.imresize_single_image(image_polys_aug, 0.5))ia.imshow(ia.draw_grid(images_polys_aug, cols=2))

展示如下:
在这里插入图片描述

二、汇总

最后,做下汇总:

目标:根据采用labelme标注的pylygons标记信息,批量对图像和标注信息同时增强变换
步骤:

  1. 读取图像和json文件信息
  2. 增强操作
  3. 保存到本地
  4. 再次采用labelme,查看生成的结果,是否正常

代码如下:

import imageio
import imgaug as ia
import numpy as np
from imgaug.augmentables.polys import Polygon, PolygonsOnImage
import imgaug.augmenters as iaaclass LabelJson(object):def __init__(self, abs_path=None) -> None:super().__init__()self.abs_path = abs_pathself.read()def read(self):with open(self.abs_path, 'r', encoding='utf-8') as f:lj = json.load(f)self.wh = [lj.get('imageWidth'), lj.get('imageHeight')]shapes = lj.get('shapes')self.cls = [i.get('label') for i in shapes]  # '1305' if i.get('label') == '14' elsepoints = [i.get('points') for i in shapes]points = [np.array(i, dtype=np.int32).reshape((-1, 2)) for i in points]self.loc = pointsself.box = [[j[:, 0].min(), j[:, 1].min(), j[:, 0].max(), j[:, 1].max()] for j in points]self.img_name = lj.get('imagePath')self.is_pos = bool(self.cls)return selfimport base64, os
from PIL import Image
import io
import json
import cv2
def base64encode_img(src_image):# src_image = Image.open(image_path)src_image = Image.fromarray(cv2.cvtColor(src_image, cv2.COLOR_BGR2RGB))output_buffer = io.BytesIO()src_image.save(output_buffer, format='JPEG')byte_data = output_buffer.getvalue()base64_str = base64.b64encode(byte_data).decode('utf-8')return base64_strdef savejson(points_list, clses_list, img_tmp, filename, save_dir):A = dict()listbigoption = []for cls, points in zip(clses_list, points_list):listobject = dict()listobject['points'] = pointslistobject['line_color'] = 'null'listobject['label'] = clslistobject['fill_color'] = 'null'listbigoption.append(listobject)A['imageData'] = base64encode_img(img_tmp)A['imagePath'] = filenameA['shapes'] = listbigoptionA['flags'] = {}suffix = os.path.splitext(filename)[-1]with open(save_dir + "/" + filename.replace(suffix, ".json"), 'w', encoding='utf-8') as f:json.dump(A, f, indent=2, ensure_ascii=False)def saveJsonImg_main(image_aug, psoi_aug, cls_list, img_path, num, save_dir):nw, nh, _ = image_aug.shapepoints_list = []for pos in psoi_aug:points = [list(xy.astype(np.float64)) for xy in pos]for p in points:if p[0] < 0:p[0] = 0elif p[0] > nh:p[0] = nhif p[1] < 0:p[1] = 0elif p[1] > nw:p[1] = nwpoints_list.append(points)image_augRGB = cv2.cvtColor(image_aug, cv2.COLOR_BGR2RGB)savejson(points_list, cls_list, image_augRGB, str(num)+'_'+os.path.basename(img_path), save_dir)# ia.imshow(psoi_aug.draw_on_image(image_aug, alpha_face=0.2, size_points=7))cv2.imwrite(os.path.join(save_dir, str(num)+'_'+os.path.basename(img_path)), image_augRGB)ia.seed(2)
aug = iaa.Sequential([iaa.OneOf([iaa.SaltAndPepper(0.01),iaa.AdditiveGaussianNoise(scale=5),iaa.GaussianBlur(sigma=(0.0, 3.0)),]),iaa.OneOf([iaa.Affine(rotate=(-20, 20), translate_percent=(-0.2, 0.2), scale=(0.8, 1.2),mode=["constant", "edge"], cval=0),  # 放射变换iaa.Affine(scale={"x": (0.5, 1.5), "y": (0.5, 1.5)}),iaa.Affine(translate_px={"x": (-20, 20), "y": (-20, 20)}),iaa.TranslateX(px=(-20, 20)),iaa.Rotate((-45, 45))]),iaa.OneOf([iaa.Fliplr(0.7),    # 水平翻转iaa.Flipud(0.7),    # 上下翻转]),iaa.OneOf([iaa.GammaContrast((0.5, 2.0)),iaa.LinearContrast((0.8, 1.2), per_channel=0.5),iaa.WithBrightnessChannels(iaa.Add((-50, 50))),     # Augmenter to apply child augmenters to brightness-related image channels.iaa.AddToHueAndSaturation((-20, 20)),   # 通过随机值增加或减少色调和饱和度。]),iaa.Sometimes(0.75, iaa.Snowflakes())
])def main():img_dir = r"./images"json_dir = r'./label'save_dir = r'./aug'for file in os.listdir(img_dir):img_path = os.path.join(img_dir, file)json_path = os.path.join(json_dir, file.replace('.jpg', '.json'))# read image and get json infoimage = imageio.imread(img_path)json_info = LabelJson(json_path)#  let's convert our polygons to an PolygonsOnImage instance:psoi = ia.PolygonsOnImage([Polygon(point) for point in json_info.loc],shape=image.shape)# one labelme image aug to 50 imagefor num in range(50):# augimage_aug, psoi_aug = aug(image=image, polygons=psoi)# save json and imagesaveJsonImg_main(image_aug, psoi_aug, json_info.cls, img_path, num, save_dir)if __name__ == '__main__':main()

至此结束,感兴趣的可以赶紧去学习下。如果恰好对你也有帮助,点个赞👍,再走啦。


http://www.ppmy.cn/news/49069.html

相关文章

Vivado布线和生成bit参数设置

本文主要介绍Vivado布线参数设置&#xff0c;基本设置方式和vivado综合参数设置基本一致&#xff0c;将详细说明如何设置布线参数以优化FPGA设计的性能&#xff0c;以及如何设置Vivado压缩BIT文件。 一、Vivado布线概述 Vivado布线是在FPGA设计中实现物理布局的关键步骤之一。…

2023年全国最新道路运输从业人员精选真题及答案58

百分百题库提供道路运输安全员考试试题、道路运输从业人员考试预测题、道路安全员考试真题、道路运输从业人员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 69.根据《公路水路行业安全生产风险管理暂行办法》&#xff0c;…

CollectionUtils常用方法

一些常用的 Apache Commons Collections 中 CollectionUtils 类中定义的方法&#xff1a; isEmpty()&#xff1a;检查集合是否为空。isNotEmpty()&#xff1a;检查集合是否非空。size()&#xff1a;返回集合中元素的数量。get()&#xff1a;获取集合中指定位置的元素。indexOf…

CSS——js 动态改变原生 radio、switch 的选中样式

导航 1. radio1-1. 业务场景&#xff1a;1-2. 效果&#xff1a;1-3. 问题点&#xff1a;1-4. 解决方案&#xff1a;1-5. 代码&#xff1a;1-5-1. HTML1-5-2. JS1-5-3. html 内容排版的 css1-5-4. 实现 radio 效果的 css 2. switch2-1. 业务场景&#xff1a;2-2. 效果&#xff1…

netty使用异常,nio使用DirectBuffer导致内存溢出

文章目录 报错信息解决总结 报错信息 业务场景&#xff1a;雷达作为客户端&#xff0c;平台作为服务端&#xff0c;采用TCP/IP协议的socket连接&#xff0c;数据包采用字节的二进制数据传输平台部署某市&#xff0c;接入了四五十个路口和相应的雷达&#xff0c;在运行一周左右…

如何创建高效的Prompt和ChatGPT等大语言模型AI对话

大语言模型&#xff0c;如OpenAI的GPT-4&#xff0c;是一种基于深度学习技术的自然语言处理工具&#xff0c;它可以理解自然语言并为用户提供有价值的回答。然而&#xff0c;要从大语言模型中获得高质量的回答&#xff0c;你需要学会如何高效地提问。本文将从原理出发&#xff…

医院体检PEIS系统源码

一、医院体检系统概述 1. 医院体检系统概述 目前&#xff0c;大多数的体检还停留在手工操作上&#xff0c;如单位体检时手工书写体检人员信息、医生手工书写体检结果、检验报告打印后进行手工粘贴等&#xff0c;这样造成极大的工作量&#xff0c;效率低下&#xff0c;而且极易…

新能源汽车和数字化转型

工业时代的代表产品是交通运输设备&#xff0c;核心桂冠是发动机。信息时代的代表产品是智能手机&#xff0c;核心桂冠是芯片。 汽车是个很有代表性产品&#xff0c;因为它既属于复杂高精密金属机械设备&#xff0c;又属于大规模使用的大件消费品。所以这100年来&#xff0c;汽…