转载+记录数据增广的八种常用方式
在圖像的深度學習中,為了豐富圖像訓練集,提高模型的泛化能力,一般會對圖像進行數據增強。常用的方式有:旋轉、剪切、改變圖像色差、扭曲圖像特征、改變圖像尺寸、增加圖像噪聲(高斯噪聲、鹽膠噪聲)。
思考:對于人臉的數據增廣來說,其是對稱的,所以鏡像旋轉pass,然后剪切后的部分人臉應用價值不高,大多數人臉識別都會將人臉對齊,所以多種形式的剪切沒有意義,但將人臉從背景中剪切出來再進行識別對于facenet來說很有用。(ps:個人愚見,歡迎討論)
# -*- coding:utf-8 -*-
"""數據增強
1. 翻轉變換 flip
2. 隨機修剪 random crop
3. 色彩抖動 color jittering
4. 平移變換 shift
5. 尺度變換 scale
6. 對比度變換 contrast
7. 噪聲擾動 noise
8. 旋轉變換/反射變換 Rotation/reflection
author: XiJun.Gong
date:2016-11-29
"""
from PIL import Image, ImageEnhance, ImageOps, ImageFile
import numpy as np
import random
import threading, os, time
import logging
logger = logging.getLogger(__name__)
ImageFile.LOAD_TRUNCATED_IMAGES = True
class DataAugmentation:
"""
包含數據增強的八種方式
"""
def __init__(self):
pass
@staticmethod
def openImage(image):
return Image.open(image, mode="r")
@staticmethod
def randomRotation(image, mode=Image.BICUBIC):
"""
對圖像進行隨機任意角度(0~360度)旋轉
:param mode 鄰近插值,雙線性插值,雙三次B樣條插值(default)
:param image PIL的圖像image
:return: 旋轉轉之后的圖像
"""
random_angle = np.random.randint(1, 360)
return image.rotate(random_angle, mode)
@staticmethod
def randomCrop(image):
"""
對圖像隨意剪切,考慮到圖像大小范圍(68,68),使用一個一個大于(36*36)的窗口進行截圖
:param image: PIL的圖像image
:return: 剪切之后的圖像
"""
image_width = image.size[0]
image_height = image.size[1]
crop_win_size = np.random.randint(40, 68)
random_region = (
(image_width - crop_win_size) >> 1, (image_height - crop_win_size) >> 1, (image_width + crop_win_size) >> 1,
(image_height + crop_win_size) >> 1)
return image.crop(random_region)
@staticmethod
def randomColor(image):
"""
對圖像進行顏色抖動
:param image: PIL的圖像image
:return: 有顏色色差的圖像image
"""
random_factor = np.random.randint(0, 31) / 10. # 隨機因子
color_image = ImageEnhance.Color(image).enhance(random_factor) # 調整圖像的飽和度
random_factor = np.random.randint(10, 21) / 10. # 隨機因子
brightness_image = ImageEnhance.Brightness(color_image).enhance(random_factor) # 調整圖像的亮度
random_factor = np.random.randint(10, 21) / 10. # 隨機因1子
contrast_image = ImageEnhance.Contrast(brightness_image).enhance(random_factor) # 調整圖像對比度
random_factor = np.random.randint(0, 31) / 10. # 隨機因子
return ImageEnhance.Sharpness(contrast_image).enhance(random_factor) # 調整圖像銳度
@staticmethod
def randomGaussian(image, mean=0.2, sigma=0.3):
"""
對圖像進行高斯噪聲處理
:param image:
:return:
"""
def gaussianNoisy(im, mean=0.2, sigma=0.3):
"""
對圖像做高斯噪音處理
:param im: 單通道圖像
:param mean: 偏移量
:param sigma: 標準差
:return:
"""
for _i in range(len(im)):
im[_i] += random.gauss(mean, sigma)
return im
# 將圖像轉化成數組
img = np.asarray(image)
img.flags.writeable = True # 將數組改為讀寫模式
width, height = img.shape[:2]
img_r = gaussianNoisy(img[:, :, 0].flatten(), mean, sigma)
img_g = gaussianNoisy(img[:, :, 1].flatten(), mean, sigma)
img_b = gaussianNoisy(img[:, :, 2].flatten(), mean, sigma)
img[:, :, 0] = img_r.reshape([width, height])
img[:, :, 1] = img_g.reshape([width, height])
img[:, :, 2] = img_b.reshape([width, height])
return Image.fromarray(np.uint8(img))
@staticmethod
def saveImage(image, path):
image.save(path)
def makeDir(path):
try:
if not os.path.exists(path):
if not os.path.isfile(path):
# os.mkdir(path)
os.makedirs(path)
return 0
else:
return 1
except Exception, e:
print str(e)
return -2
def imageOps(func_name, image, des_path, file_name, times=5):
funcMap = {"randomRotation": DataAugmentation.randomRotation,
"randomCrop": DataAugmentation.randomCrop,
"randomColor": DataAugmentation.randomColor,
"randomGaussian": DataAugmentation.randomGaussian
}
if funcMap.get(func_name) is None:
logger.error("%s is not exist", func_name)
return -1
for _i in range(0, times, 1):
new_image = funcMap[func_name](image)
DataAugmentation.saveImage(new_image, os.path.join(des_path, func_name + str(_i) + file_name))
opsList = {"randomRotation", "randomCrop", "randomColor", "randomGaussian"}
def threadOPS(path, new_path):
"""
多線程處理事務
:param src_path: 資源文件
:param des_path: 目的地文件
:return:
"""
if os.path.isdir(path):
img_names = os.listdir(path)
else:
img_names = [path]
for img_name in img_names:
print img_name
tmp_img_name = os.path.join(path, img_name)
if os.path.isdir(tmp_img_name):
if makeDir(os.path.join(new_path, img_name)) != -1:
threadOPS(tmp_img_name, os.path.join(new_path, img_name))
else:
print 'create new dir failure'
return -1
# os.removedirs(tmp_img_name)
elif tmp_img_name.split('.')[1] != "DS_Store":
# 讀取文件并進行操作
image = DataAugmentation.openImage(tmp_img_name)
threadImage = [0] * 5
_index = 0
for ops_name in opsList:
threadImage[_index] = threading.Thread(target=imageOps,
args=(ops_name, image, new_path, img_name,))
threadImage[_index].start()
_index += 1
time.sleep(0.2)
if __name__ == '__main__':
threadOPS("/home/pic-image/train/12306train",
"/home/pic-image/train/12306train3")
?
總結
以上是生活随笔為你收集整理的转载+记录数据增广的八种常用方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习训练中关于数据处理方式--原始样
- 下一篇: 如何使用Soft-NMS实现目标检测并提