深度学习 之 数据增广(包含源码及注释文件更改)
数据增广:平移,水平/垂直翻转,旋转,缩放,剪切,对比度,色彩抖动,噪声
#coding=utf-8
#######################################################################
# 数据增广,包括:平移,水平/垂直翻转,旋转,缩放,剪切,对比度,噪声 #
# 2021/3/8 13:40 #
#######################################################################import os
import cv2
import copy
import json
import skimage
import numpy as np
from random import choiceclass DataAugment:def __init__(self, debug=False):self.debug=debugprint("Data augment...")# 基础变换矩阵def basic_matrix(self, translation): return np.array([[1,0,translation[0]],[0,1,translation[1]],[0,0,1]]) # translation = center = [width/2, height/2]# 基础变换矩阵def adjust_transform_for_image(self, img, trans_matrix): transform_matrix=copy.deepcopy(trans_matrix) # deep copyprint("trans_matrix is \n", trans_matrix)# ################# trans_matrix ################# 平移: # [1, 0, a]# transform_matrix = [0, 1, b] # [0, 0, 1]## 垂直反转:# [1, 0, 0]# flip_matrix = [0, -1, 0]# [0, 0, 1]## 水平反转:# [-1, 0, 0]# flip_matrix = [ 0, 1, 0]# [ 0, 0, 1]## 旋转a度(顺):# [cos(a), -sin(a), 0]# rotate_matrix = [sin(a), cos(a), 0]# [ 0 , 0 , 1]## 图片缩放:# [ a, 0, 0]# scale_matrix = [ 0, b, 0]# [ 0, 0, 1]## 图片错切:# [ 1, a, 0]# crop_matrix = [ b, 1, 0]# [ 0, 0, 1]height, width, channels = img.shapetransform_matrix[0:2, 2] *= [width, height]print("transform_matrix is \n", transform_matrix)# ################# trans_matrix ################# 平移: # [1, 0, aw]# transform_matrix = [0, 1, bh] # [0, 0, 1]## 垂直反转:# [1, 0, 0]# flip_matrix = [0, -1, 0]# [0, 0, 1]## 水平反转:# [-1, 0, 0]# flip_matrix = [ 0, 1, 0]# [ 0, 0, 1]## 旋转a度(顺):# [cos(a), -sin(a), 0]# rotate_matrix = [sin(a), cos(a), 0]# [ 0 , 0 , 1]## 图片缩放:# [ a, 0, 0]# scale_matrix = [ 0, b, 0]# [ 0, 0, 1]## 图片错切:# [ 1, a, 0]# crop_matrix = [ b, 1, 0]# [ 0, 0, 1]center = np.array((0.5 * width, 0.5 * height))transform_matrix = np.linalg.multi_dot([self.basic_matrix(center), transform_matrix, self.basic_matrix(-center)])# ################# trans_matrix ################# 平移: 沿x轴平移aw个像素,沿y轴平移bh个像素# [1, 0, aw]# transform_matrix = [0, 1, bh] # [0, 0, 1]## 垂直反转:# [1, 0, 0]# flip_matrix = [0, -1, h]# [0, 0, 1]## 水平反转:# [-1, 0, w]# flip_matrix = [ 0, 1, 0]# [ 0, 0, 1]## 旋转a度(顺):以(w/2, h/2)为中心,顺时针旋转a度# [cos(a), -sin(a), w/2-(w/2)cos(a)+(h/2)sin(a)]# rotate_matrix = [sin(a), cos(a), h/2-(h/2)cos(a)-(w/2)sin(a)]# [ 0 , 0 , 1 ]## 图片缩放:沿x轴放大a个像素,沿y轴放大b个像素# [ a, 0, w/2-(w/2)*a]# scale_matrix = [ 0, b, h/2-(h/2)*b]# [ 0, 0, 1 ]## 图片错切:# [ 1, a, -(h/2)*a]# crop_matrix = [ b, 1, -(w/2)*b]# [ 0, 0, 1 ]print("transform_matrix np.linalg.multi_dot is \n", transform_matrix, '\n') return transform_matrix# 仿射变换def apply_transform(self, img, transform): output = cv2.warpAffine(img, transform[:2, :], dsize=(img.shape[1], img.shape[0]),flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_TRANSPARENT, borderValue=0,)# ################################ borderMode ############################################ [1] cv2.BORDER_CONSTANT 填充边界时使用常数填充# [2] cv2.BORDER_REPLICATE: 使用边界最接近的像素填充,也就是用边缘像素填充# [3] cv2.BORDER_REFLECT, 反射法,是指对图像的像素两边进行复制# [4] cv2.BORDER_REFLECT101: 反射法,把边缘的像素作为轴,对称的复制# [5] cv2.BORDER_WRAP: 用另一边的像素进行填充# [6] cv2.BORDER_TRANSPARENTreturn output# 应用变换def apply(self, img, trans_matrix): tmp_matrix=self.adjust_transform_for_image(img, trans_matrix)out_img=self.apply_transform(img, tmp_matrix) if self.debug:self.show(out_img)return tmp_matrix, out_img# 生成范围矩阵def random_vector(self, min, max): min=np.array(min)max=np.array(max)print(min.shape,max.shape)assert min.shape==max.shapeassert len(min.shape) == 1return np.random.uniform(min, max)# 可视化def show(self, img): cv2.imshow("outimg",img)cv2.waitKey()# 平移变换def random_transform(self, img, min_translation, max_translation): factor=self.random_vector(min_translation,max_translation)trans_matrix=np.array([[1, 0, factor[0]],[0, 1, factor[1]],[0, 0, 1]])tmp_matrix, out_img=self.apply(img,trans_matrix)return tmp_matrix, trans_matrix, out_img# 水平或垂直翻转def random_flip(self, img, factor): # 垂直: factor=[1.0, -1.0]# 水平: factor=[-1.0, 1.0]flip_matrix = np.array([[factor[0], 0, 0],[0, factor[1], 0],[0, 0, 1]])_, out_img=self.apply(img,flip_matrix)return flip_matrix, out_img# 随机旋转(顺)def random_rotate(self, img, factor): # 除了以下方法,还可以考虑cv2.getRotationMatrix2D这个函数angle=np.random.randint(factor[0],factor[1])print("angle : {}°".format(angle))angle = np.pi / 180.0 * angle rotate_matrix=np.array([[np.cos(angle), -np.sin(angle), 0], [np.sin(angle), np.cos(angle), 0], [0, 0, 1]]) # 顺时针_, out_img=self.apply(img,rotate_matrix) return angle, rotate_matrix, out_img# 随机缩放def random_scale(self, img, min_translation, max_translation): factor=self.random_vector(min_translation, max_translation)scale_matrix = np.array([[factor[0], 0, 0],[0, factor[1], 0],[0, 0, 1]])_, out_img=self.apply(img,scale_matrix)return factor, scale_matrix, out_img# 随机剪切,包括横向和众向剪切def random_shear(self, img, factor): angle = np.random.uniform(factor[0], factor[1])print("fc:{}".format(angle))crop_matrix = np.array([[1, factor[0], 0], [factor[1], 1, 0], [0, 0, 1]])_, out_img=self.apply(img,crop_matrix)return angle, crop_matrix, out_img# 设置对比度和亮度def brightness_contrast_ratio(self, im):brightness = [0.6, 0.7, 0.8, 0.9, 1.0]contrast_ratio = [1.5, 1.6, 1.7, 1.8]a = choice(contrast_ratio)b = choice(brightness)print(f"brightness is {b}, contrast is {a}")img = np.array(im)mean = np.mean(img)temp = img - meanimg = temp * a + mean * bif self.debug:self.show(img)return img# 随机噪声def random_noise(self, im):noise_img = skimage.util.random_noise(im, mode='gaussian', var=0.01) # 原图像素为float,skimage操作后控制在[0,1]内,返回时需扩大到[0,255] img = noise_img * 255 if self.debug:self.show(img)return imgclass DataAugmen_Json:def __init__(self, readPath, savePath): self.width = Noneself.height = Noneself.shapes = Noneself.json_file = Noneself.read_path = readPathself.save_path = savePathprint("Change json...")# 读取json文件,并存放在类变量中def openjson(self, name):path = os.path.join(self.read_path, name)with open(path, 'r') as f:self.json_file = json.load(f) self.width = self.json_file['imageWidth']self.height = self.json_file['imageHeight']self.shapes = self.json_file['shapes']# 保存修改后的json文件def savejson(self, name):path = os.path.join(self.save_path, name)with open(path, 'w') as f:json.dump(self.json_file, f)# 图片平移操作,修改相应标注点坐标def random_transform_json(self, trans_matrix):newShapes = [] x_offset, y_offset = trans_matrix[0:2, 2]for shape in self.shapes:tempdic = {"label": shape['label'], "group_id": shape['group_id'], "shape_type": "polygon", "flags": {}}newpoints = []for point in shape['points']:x = point[0] + x_offsety = point[1] + y_offset
# x = width if x > width else x
# y = height if y > height else ynewpoints.append([x, y])tempdic['points'] = newpointsnewShapes.append(tempdic)self.json_file['shapes'] = newShapes# 图片翻转操作,修改相应标注点坐标def random_flip_json(self, factor):newShapes = []for shape in self.shapes:tempdic = {"label": shape['label'], "group_id": shape['group_id'], "shape_type": "polygon", "flags": {}}newpoints = []for point in shape['points']:if factor == (-1.0, 1.0) :x = self.width - point[0]y = point[1]elif factor == (1.0, -1.0):x = point[0]y = self.height - point[1] newpoints.append([x, y])tempdic['points'] = newpointsnewShapes.append(tempdic)self.json_file['shapes'] = newShapes# 图片旋转操作,修改相应标注点坐标def random_rotate_json(self, angle):"""点point1绕点point2旋转angle后的点======================================在平面坐标上,任意点P(x1,y1),绕一个坐标点Q(x2,y2)旋转θ角度后,新的坐标设为(x, y)的计算公式:x= (x1 - x2)*cos(θ) - (y1 - y2)*sin(θ) + x2 ;y= (x1 - x2)*sin(θ) + (y1 - y2)*cos(θ) + y2 ;======================================将图像坐标(x,y)转换到平面坐标(x`,y`):x`=xy`=height-y:param point1::param point2: base point (基点):param angle: 旋转角度,正:表示逆时针,负:表示顺时"""newShapes = []cx, cy = self.width/2, self.height/2for shape in self.shapes:tempdic = {"label": shape['label'], "group_id": shape['group_id'], "shape_type": "polygon", "flags": {}}newpoints = []for point in shape['points']:x1 = point[0]y1 = point[1]# 将图像坐标转换到平面坐标y1 = self.height - y1cy = self.height - cy# # 逆时针
# x = (x1 - cx) * np.cos(angle) - (y1 - cy) * np.sin(angle) + cx
# y = (x1 - cx) * np.sin(angle) + (y1 - cy) * np.cos(angle) + cy# 顺时针x = (x1 - cx) * np.cos(angle) + (y1 - cy) * np.sin(angle) + cxy = -1*(x1 - cx) * np.sin(angle) + (y1 - cy) * np.cos(angle) + cy# 将平面坐标转换到图像坐标y = self.height - y newpoints.append([x, y])tempdic['points'] = newpointsnewShapes.append(tempdic)self.json_file['shapes'] = newShapes# 图片缩放操作,修改相应标注点坐标def random_scale_json(self, factor):newShapes = []w, h = self.width/2, self.height/2for shape in self.shapes:tempdic = {"label": shape['label'], "group_id": shape['group_id'], "shape_type": "polygon", "flags": {}}newpoints = []for point in shape['points']: x = point[0] * factor[0] + w * (1-factor[0])y = point[1] * factor[1] + h * (1-factor[1]) newpoints.append([x, y])tempdic['points'] = newpointsnewShapes.append(tempdic)self.json_file['shapes'] = newShapes# 图片错切操作,修改相应标注点坐标def random_shear_json(self, factor):newShapes = []w, h = self.width/2, self.height/2for shape in self.shapes:tempdic = {"label": shape['label'], "group_id": shape['group_id'], "shape_type": "polygon", "flags": {}}newpoints = []for point in shape['points']: x = point[0] + point[1] * factor[0] - h * factor[0]y = point[1] + point[0] * factor[1] - w * factor[1] newpoints.append([x, y])tempdic['points'] = newpointsnewShapes.append(tempdic)self.json_file['shapes'] = newShapes# 设置对比度和亮度, 不需要修改标注文件def brightness_contrast_ratio_json(self):pass# 随机噪声, 不需要修改标注文件def random_noise_json(self):passif __name__=="__main__":daPic = DataAugment(debug=True)daJson = DataAugmen_Json(readPath='E:/Desktop/images', savePath='E:/Desktop/augment')img=cv2.imread("E:/Desktop/images/0001.jpg")# a = np.array([[1,0,0],[0,1,0],[0,0,1]])
# print(a[0:2, 2])
# min=np.array((0.1,0.1))
# print(min)
# max=np.array((0.2,0.2))
# print(max)
# print(np.random.uniform(min, max))# 平移测试
# trans_matrix, _, outimg=daPic.random_transform(img,(0.1,0.1),(0.2,0.2)) #(-0.3,-0.3),(0.3,0.3)
# cv2.imwrite('E:/Desktop/augment/0001.jpg', outimg)
# daJson.openjson('0001.json')
# daJson.random_transform_json(trans_matrix)
# daJson.savejson('test.json')# 翻转测试
# factor = (-1.0, 1.0) # 垂直: (1.0, -1.0) ; 水平:(-1.0, 1.0)
# _, outimg = daPic.random_flip(img, factor)
# cv2.imwrite('E:/Desktop/augment/0001.jpg', outimg)
# daJson.openjson('0001.json')
# daJson.random_flip_json(factor)
# daJson.savejson('test.json')# 旋转变换测试
# angle, _, outimg = daPic.random_rotate(img, (10, 350)) # 在10°到350°之间顺时针旋转
# cv2.imwrite('E:/Desktop/augment/0001.jpg', outimg)
# daJson.openjson('0001.json')
# daJson.random_rotate_json(angle)
# daJson.savejson('test.json')# 缩放变换测试
# factor, _, outimg = daPic.random_scale(img, (1.2, 1.2), (1.3,1.3))
# cv2.imwrite('E:/Desktop/augment/0001.jpg', outimg)
# print(f"factor is {factor}")
# daJson.openjson('0001.json')
# daJson.random_scale_json(factor)
# daJson.savejson('test.json')# 随机裁剪测试
# factor = (0.2,0.3)
# _, _, outimg = daPic.random_shear(img, factor)
# cv2.imwrite('E:/Desktop/augment/0001.jpg', outimg)
# daJson.openjson('0001.json')
# daJson.random_shear_json(factor)
# daJson.savejson('test.json')# 组合变换
# _, t1, _=daPic.random_transform(img, (-0.3,-0.3), (0.3,0.3))
# angle, t2, _=daPic.random_rotate(img, (10, 350))
# factor, t3, _=daPic.random_scale(img, (1.5,1.5), (1.7,1.7))
# tmp=np.linalg.multi_dot([t1,t2,t3])
# print("tmp:{}".format(tmp))
# out=daPic.apply(img, tmp)# 对比度和亮度测试
# outimg = daPic.brightness_contrast_ratio(img)
# cv2.imwrite('E:/Desktop/augment/0001.jpg', outimg)
# daJson.openjson('0001.json')
# daJson.brightness_contrast_ratio_json()
# daJson.savejson('test.json')# 高斯噪声测试
# outimg = daPic.random_noise(img)
# cv2.imwrite('E:/Desktop/augment/0001.jpg', outimg)
# daJson.openjson('0001.json')
# daJson.random_noise_json()
# daJson.savejson('test.json')
深度学习 之 数据增广(包含源码及注释文件更改)相关推荐
- 【深度学习】基于深度学习的数据增广技术一览
◎作者系极市原创作者计划特约作者Happy 周末在家无聊,偶然兴心想对CV领域常用的数据增广方法做个简单的调研与总结,重点是AI时代新兴的几种反响还不错的方法.各种第三方与官方实现代码等.那么今天由H ...
- 论文笔记 | 深度学习图像数据增广方法研究
1 背景 在许多领域,受限于数据获取难度大,标注成本高等原因,往往难以获得充足的训练数据,这样训练得到的深度学习模型往往存在过拟合的问题,进而导致模型泛化能力差,测试精度不高等. 数据扩充的作用:扩大 ...
- 基于深度学习的数据增广技术一览
周末在家无聊,偶然兴心想对CV领域常用的数据增广方法做个简单的调研与总结,重点是AI时代新兴的几种反响还不错的方法.各种第三方与官方实现代码等.那么今天由Happy来跟大家聊一聊深度学习中那些常用的数 ...
- 深度学习-MATLAB数据增广
图片数据增广 对文件夹及其子文件夹下的图片数据进行简单的增广,四个方面,翻转,平移,增加高斯噪声,对比度增强,保存在当前文件夹中,命名为图片原名+ -1.-2.-3.-4,代表四个类. p=genpa ...
- 深度学习图像数据增广方法总结
参考:Data Augmentation | How to use Deep Learning when you have Limited Data-Part 2 文章目录 1. 数据增广(Data ...
- 深度学习笔记 —— 数据增广
固定形状?卷积神经网络通常是一个固定的输入. 作用好不好是不一定的.很多时候觉得它有用是因为觉得测试集里会有图片跟这个效果是差不多的. 所以如何选择数据增强?可以从后往前推,想一下部署和测试集里面的图 ...
- 深度学习-计算机视觉--图像增广
图像增广 大规模数据集是成功应用深度神经网络的前提.图像增广(image augmentation)技术通过对训练图像做一系列随机改变,来产生相似但又不同的训练样本,从而扩大训练数据集的规模. 图像增 ...
- 李沐动手学深度学习V2-图像增广和代码实现
图像增广 大型数据集是成功应用深度神经网络的先决条件,因为解决了大型复杂网络的过拟合性. 图像增广在对训练图像进行一系列的随机变化之后,生成相似但不同的训练样本,从而扩大了训练集的规模. 此外,应用图 ...
- 李沐d2l《动手学深度学习》第二版——风格迁移源码详解
本文是对李沐Dive to DL<动手学深度学习>第二版13.12节风格迁移的源码详解,整体由Jupyter+VSCode完成,几乎所有重要代码均给出了注释,一看就懂.需要的同学可以在文末 ...
最新文章
- weblogic域,管理服务器,受管服务器,集群和机器的基本知识
- anaconda在ubuntu中安装后没有_你的大数据平台中病毒了!!!记一次HDP安装后中dr.who病毒并修复的过程...
- 在 asp.net mvc中的简单分页算法 (续)
- strnicmp,strncmpi方法
- Vue项目报错记录解决Property or method “item“ is not defined on the instance
- 程序员应该知道的二十三种设计模式
- Pyrex也许是一个好东西
- Java 0xffffffff隐式类型转换的坑
- LeetCode 26. 删除排序数组中的重复项
- 利用screen和nohup让Linux服务器后台运行程序
- 程序员如何才配拥有姓名?
- 论文翻译——Lattice indexing for spoken term detection
- 游戏筑基开发之一级指针、二级指针的使用情形(C语言)
- learning-oracle-how2j
- 如何使用MIME类型
- 简单测试ROS里面C++ 和 python 文件获取参数格式
- opc服务器保存在哪里怎么修改,客户端修改opc服务器的数据
- 论文解读:医学影像中的注意力机制
- 实时填报推送微信消息及审核(帆软报表)
- 转载:Session与JWT的使用