Data_Aug(数据增强)
Data_Aug(数据增强)
1 python+OpenCV (备用)
github:https://github.com/tranleanh/data-augmentation
wechat:https://mp.weixin.qq.com/s/UFx4AGNEF_qBTBNYsLfZXQ

import os import cv2 import numpy as np import random def file_lines_to_list(path): ''' ### Convert Lines in TXT File to List ### path: path to file ''' with open(path) as f: content = f.readlines() content = [(x.strip()).split() for x in content] return content def get_file_name(path): ''' ### Get Filename of Filepath ### path: path to file ''' basename = os.path.basename(path) onlyname = os.path.splitext(basename)[0] return onlyname def write_anno_to_txt(boxes, filepath): ''' ### Write Annotation to TXT File ### boxes: format [[obj x1 y1 x2 y2],...] filepath: path/to/file.txt ''' txt_file = open(filepath, "w") for box in boxes: print(box[0], int(box[1]), int(box[2]), int(box[3]), int(box[4]), file=txt_file) txt_file.close() def cutout(img, gt_boxes, amount=0.5): ''' ### Cutout ### img: image gt_boxes: format [[obj x1 y1 x2 y2],...] amount: num of masks / num of objects ''' out = img.copy() ran_select = random.sample(gt_boxes, round(amount*len(gt_boxes))) for box in ran_select: x1 = int(box[1]) y1 = int(box[2]) x2 = int(box[3]) y2 = int(box[4]) mask_w = int((x2 - x1)*0.5) mask_h = int((y2 - y1)*0.5) mask_x1 = random.randint(x1, x2 - mask_w) mask_y1 = random.randint(y1, y2 - mask_h) mask_x2 = mask_x1 + mask_w mask_y2 = mask_y1 + mask_h cv2.rectangle(out, (mask_x1, mask_y1), (mask_x2, mask_y2), (0, 0, 0), thickness=-1) return out def colorjitter(img, cj_type="b"): ''' ### Different Color Jitter ### img: image cj_type: {b: brightness, s: saturation, c: constast} ''' if cj_type == "b": # value = random.randint(-50, 50) value = np.random.choice(np.array([-50, -40, -30, 30, 40, 50])) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) h, s, v = cv2.split(hsv) if value >= 0: lim = 255 - value v[v > lim] = 255 v[v <= lim] += value else: lim = np.absolute(value) v[v < lim] = 0 v[v >= lim] -= np.absolute(value) final_hsv = cv2.merge((h, s, v)) img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR) return img elif cj_type == "s": # value = random.randint(-50, 50) value = np.random.choice(np.array([-50, -40, -30, 30, 40, 50])) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) h, s, v = cv2.split(hsv) if value >= 0: lim = 255 - value s[s > lim] = 255 s[s <= lim] += value else: lim = np.absolute(value) s[s < lim] = 0 s[s >= lim] -= np.absolute(value) final_hsv = cv2.merge((h, s, v)) img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR) return img elif cj_type == "c": brightness = 10 contrast = random.randint(40, 100) dummy = np.int16(img) dummy = dummy * (contrast/127+1) - contrast + brightness dummy = np.clip(dummy, 0, 255) img = np.uint8(dummy) return img def noisy(img, noise_type="gauss"): ''' ### Adding Noise ### img: image cj_type: {gauss: gaussian, sp: salt & pepper} ''' if noise_type == "gauss": image=img.copy() mean=0 st=0.7 gauss = np.random.normal(mean,st,image.shape) gauss = gauss.astype('uint8') image = cv2.add(image,gauss) return image elif noise_type == "sp": image=img.copy() prob = 0.05 if len(image.shape) == 2: black = 0 white = 255 else: colorspace = image.shape[2] if colorspace == 3: # RGB black = np.array([0, 0, 0], dtype='uint8') white = np.array([255, 255, 255], dtype='uint8') else: # RGBA black = np.array([0, 0, 0, 255], dtype='uint8') white = np.array([255, 255, 255, 255], dtype='uint8') probs = np.random.random(image.shape[:2]) image[probs < (prob / 2)] = black image[probs > 1 - (prob / 2)] = white return image def filters(img, f_type = "blur"): ''' ### Filtering ### img: image f_type: {blur: blur, gaussian: gaussian, median: median} ''' if f_type == "blur": image=img.copy() fsize = 9 return cv2.blur(image,(fsize,fsize)) elif f_type == "gaussian": image=img.copy() fsize = 9 return cv2.GaussianBlur(image, (fsize, fsize), 0) elif f_type == "median": image=img.copy() fsize = 9 return cv2.medianBlur(image, fsize) def randomcrop(img, gt_boxes, scale=0.5): ''' ### Random Crop ### img: image gt_boxes: format [[obj x1 y1 x2 y2],...] scale: percentage of cropped area ''' # Crop image height, width = int(img.shape[0]*scale), int(img.shape[1]*scale) x = random.randint(0, img.shape[1] - int(width)) y = random.randint(0, img.shape[0] - int(height)) cropped = img[y:y+height, x:x+width] resized = cv2.resize(cropped, (img.shape[1], img.shape[0])) # Modify annotation new_boxes=[] for box in gt_boxes: obj_name = box[0] x1 = int(box[1]) y1 = int(box[2]) x2 = int(box[3]) y2 = int(box[4]) x1, x2 = x1-x, x2-x y1, y2 = y1-y, y2-y x1, y1, x2, y2 = x1/scale, y1/scale, x2/scale, y2/scale if (x1<img.shape[1] and y1<img.shape[0]) and (x2>0 and y2>0): if x1<0: x1=0 if y1<0: y1=0 if x2>img.shape[1]: x2=img.shape[1] if y2>img.shape[0]: y2=img.shape[0] new_boxes.append([obj_name, x1, y1, x2, y2]) return resized, new_boxes if __name__ == "__main__": # Load Image and Its Annotation img_name = "tr03-14-18-1-FRONT" img_path = f"data/{img_name}.jpg" anno_apth = f"data/{img_name}.txt" image = cv2.imread(img_path) gt_boxes = file_lines_to_list(anno_apth) # Create Output Folder dir_path = f"outputs" if not os.path.exists(dir_path): os.makedirs(dir_path) # Cutout cutout = cutout(image, gt_boxes, amount=0.5) cv2.imwrite(f"{dir_path}/{img_name}_cutout.jpg", cutout) # ColorJitter b_img = colorjitter(image, cj_type="b") s_img = colorjitter(image, cj_type="s") c_img = colorjitter(image, cj_type="c") cv2.imwrite(f"{dir_path}/{img_name}_brightness.jpg", b_img) cv2.imwrite(f"{dir_path}/{img_name}_saturation.jpg", s_img) cv2.imwrite(f"{dir_path}/{img_name}_contrast.jpg", c_img) # Adding Noise gaussn_img = noisy(image, noise_type="gauss") sp_img = noisy(image, noise_type="sp") cv2.imwrite(f"{dir_path}/{img_name}_gaussnoise.jpg", gaussn_img) cv2.imwrite(f"{dir_path}/{img_name}_spnoise.jpg", sp_img) # Filtering blur_img = filters(image, f_type = "blur") gaussf_img = filters(image, f_type = "gaussian") median_img = filters(image, f_type = "median") cv2.imwrite(f"{dir_path}/{img_name}_blur.jpg", blur_img) cv2.imwrite(f"{dir_path}/{img_name}_gaussblur.jpg", gaussf_img) cv2.imwrite(f"{dir_path}/{img_name}_median.jpg", median_img) # Random Crop rancrop, new_boxes = randomcrop(image, gt_boxes, scale=0.5) cv2.imwrite(f"{dir_path}/{img_name}_rancrop.jpg", rancrop) filepath = f"{dir_path}/{img_name}_rancrop.txt" write_anno_to_txt(new_boxes, filepath) print("Generating Done!")
2 imague模块(推荐)
文档参考:
Doc:https://imgaug.readthedocs.io/en/latest/source/installation.html
Github:https://github.com/aleju/imgaug
示例:

''' 该程序用于查看imgaug中的增广算法的作用效果 1. 修改代码第四行的 op 后的增广算法 2. 修改操作的图片的路径 3. 通过显示的图像可以观察到增广效果 4. 该效果是经过op 和 op_ 两种操作叠加而成的图片 5. op_ 操作为剪切和填充 6. 如果想单独看 op 效果可以将代码12行[op, op_]中的op_去掉 ''' from imgaug import augmenters as iaa import imgaug as ia import matplotlib.pyplot as plt import cv2 op = iaa.CoarseDropout(0.02, size_percent=0.15, per_channel=0.5) # 可修改成别的增广算法 op_ = iaa.CropAndPad( #剪切和填充 percent=(0, 0.2), pad_mode=["constant", "edge"], pad_cval=(0, 255) ) seq = iaa.Sequential([ op , op_]) imgList = [cv2.imread("images/001.jpg"),cv2.imread("images/002.jpg")] # 修改成图片路径 img_aug = seq.augment_images(imgList) plt.figure(figsize=(8,8)) plt.subplot(2,2,1) plt.imshow(cv2.cvtColor(imgList[0],cv2.COLOR_BGR2RGB)) plt.subplot(2,2,2) plt.imshow(cv2.cvtColor(img_aug[0],cv2.COLOR_BGR2RGB)) plt.subplot(2,2,3) plt.imshow(cv2.cvtColor(imgList[1],cv2.COLOR_BGR2RGB)) plt.subplot(2,2,4) plt.imshow(cv2.cvtColor(img_aug[1],cv2.COLOR_BGR2RGB)) plt.show()

""" #链接:https://www.cnblogs.com/xxmmqg/p/13062556.html #https://blog.csdn.net/lly1122334/article/details/88944589?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase """ #github :https://github.com/aleju/imgaug #Doc:https://imgaug.readthedocs.io/en/latest/source/examples_basics.html#a-standard-use-case from imgaug import augmenters as iaa import imgaug as ia import os import cv2 # 1定义多种增广操作,图片处理的不同操作 def img_operation_list(): # 将图像转换为HSV,然后将每个像素的H值增加10到50 op_1 = iaa.WithColorspace( to_colorspace="HSV", from_colorspace="RGB", children=iaa.WithChannels(0, iaa.Add((10, 50))) ) op_2 = iaa.WithChannels(0, iaa.Add((10,50))) # BGR中的B值随机增加10-50,因为cv2读取的图片为BGR顺序,下同 op_3 = iaa.WithChannels(1, iaa.Add((10,50))) # BGR中的G值随机增加10-50 op_4 = iaa.WithChannels(2, iaa.Add((10,50))) # BGR中的R值随机增加10-50 op_5 = iaa.WithChannels(0, iaa.Affine((10, 180))) # BGR中的B值随机旋转10-180° op_6 = iaa.WithChannels(1, iaa.Affine((10, 180))) # BGR中的G值随机旋转10-180° op_7 = iaa.WithChannels(2, iaa.Affine((10, 180))) # BGR中的R值随机旋转10-180° op_8 = iaa.Noop() # 无操作增广 # 用黑色像素替换每个图像的每5行 def img_func(images, random_state, parents, hooks): for img in images: img[::5] = 0 return images def keypoint_func(keypoints_on_images, random_state, parents, hooks): return keypoints_on_images op_9 = iaa.Lambda(img_func, keypoint_func) # 裁剪并填充 负则裁剪,正则填充 op_10 = iaa.CropAndPad(percent=(-0.2, 0.2)) op_11 = iaa.CropAndPad( percent=(0, 0.2), # 每边填充0至20% pad_mode=["constant", "edge"], # 填充方式为恒定值(constant)或边缘值(edge) pad_cval=(0, 255) # 若为恒定值,则从0-255中随机取值 ) op_12 = iaa.CropAndPad( px=((0, 30), (0, 10), (0, 30), (0, 10)), # 顶部填充0-30px,右侧0-10px,底部0-30px,左侧0-10px pad_mode=ia.ALL, pad_cval=(0, 255) ) op_13 = iaa.Fliplr() # 水平翻转所有图片 op_14 = iaa.Flipud(0.2) # 垂直反转图片20% # 每个图像生成16到128个超像素。 用平均像素颜色替换每个超像素的概率在10到50%之间(每个图像采样一次) op_15 = iaa.Superpixels(p_replace=(0.1, 0.5), n_segments=(16, 128)) # 将图像更改为灰度,并通过改变强度将其与原始图像叠加,有效地删除0到80%的颜色 op_16 = iaa.Grayscale(alpha=(0.0, 0.8)) op_17 = iaa.GaussianBlur(sigma=(0.0, 2.0)) # 高斯模糊,σ=0-2 # 在图像中添加-50到50之间的随机值。 #在50%的图像中,每个通道的值不同(3个采样值)。 #在剩下的50%图像中,所有通道的值都相同 op_18 = iaa.Add((-50, 50),per_channel=0.5) # 添加高斯噪音 # 每个像素从正态分布N(0,s)采样一次,s对每个图像采样并在0和0.1 * 255之间变化 op_19 = iaa.AdditiveGaussianNoise(scale=(0, 0.1*255)) # 丢弃2%的图像,但是在具有原始大小的50%的图像的较低分辨率版本上执行此操作,丢弃2x2个正方形。 # 此外,在50%的图像通道中执行此操作,以便仅将某些通道的信息设置为0,而其他通道保持不变 op_20 = iaa.CoarseDropout(0.02, size_percent=0.15, per_channel=0.5) operation_list = [op_1, op_7, op_8, op_9, op_10, op_11, op_12, op_13, op_14, op_16, op_17, op_18, op_19, op_20,] return operation_list # 2将图片分批 #说明:图片数据量大时,可调用此方法实现分批效果 def img_batchs_list(imgpath_file,batch_size=10): """ :param imgpath_file: 保存图片路径的txt文件 :param batch_size: 每个batch大小默认为10 :return: img_batchs:[[image1,image2,..image10],...] """ with open(imgpath_file) as img_info: batch_size = batch_size # 每个batch的大小 img_batchs = [] flag = 0 while True: if flag % batch_size == 0: img_batchs.append([]) img = img_info.readline().strip("\n") if(img == ""): break img_batchs[-1].append(img) flag += 1 if flag >=10000: # 避免进入死循环而必须重启项目 break if img_batchs[-1] == []: img_batchs.pop() return img_batchs # 3 数据增广 def data_augment(imagepath_text,NewImageDir,epochs=10,start_img_num=100): operation_list=img_operation_list() img_batchs=img_batchs_list(imagepath_text) print(img_batchs) img_name = start_img_num # 每张图片的名字,依次递增 with open(imagepath_text,"a") as img_text: for epoch in range(epochs): # 原始图片循环增广epochs*4次 for someof_n in [1, 1, 2, 2]: # 对应于SomeOf中的参数someof_n seq = iaa.SomeOf(someof_n, operation_list) # 使用的是SomeOf,区别于Sequential for batch_ind, img_batch in enumerate(img_batchs): img_batch = [cv2.imread(path) for path in img_batch] imgs_aug = seq.augment_images(img_batch) for i, save_img in enumerate(imgs_aug): save_img_path = fr"{NewImageDir}\{str(img_name)}.jpg" # 保存路径 cv2.imwrite(save_img_path, save_img) # 保存图片 img_text.write(save_img_path+" "+"\n") # 保存图像列表 print(save_img_path,"保存成功!") img_name += 1 print("Data augment Scccess!!") #收集图片路径,生成txt文件 def generate_imgpath_txt(imgpath_dir,target_file): image_name_list = sorted(os.listdir(imgpath_dir)) print("total image:", len(image_name_list)) with open(file=target_file, mode="w", encoding="utf-8") as f: for imgname in image_name_list: if not imgname.endswith("jpg"): continue img_path = os.path.join(imgpath_dir, imgname) f.write(img_path + "\n") print("success!!") if __name__ == '__main__': #1 生成图片路径文件 #测试 # imgpath_dir =r"D:\rsrc\code\script\images" # target_file =r"D:\rsrc\code\script\images\images.txt" # generate_imgpath_txt(imgpath_dir,target_file) imgpath_dir = r"D:\rsrc\data\coal-project\truck\shadunzi\JPEGImage" target_file = r"D:\rsrc\data\coal-project\truck\shadunzi\imgpath.txt" generate_imgpath_txt(imgpath_dir, target_file) # 2 数据增强处理 print("Data Enhancement............") imagepath_text=target_file start_img_num=16 #新增图片开始序号 epochs =5 # 原始图片增广epochs*4张 NewImageDir=r"D:\rsrc\data\coal-project\truck\shadunzi\JPEGImage" data_augment(imagepath_text,NewImageDir,epochs,start_img_num)
3 PP
飞浆数据增广参考:https://www.paddlepaddle.org.cn/tutorials/projectdetail/2412195
作者:华王
博客:https://www.cnblogs.com/huahuawang/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)