parser.add_argument('--p_gamma',
help='Ratio to randomly change gamma of an image',
type=float, default=1.0)
parser.add_argument('--gamma_vari',
help='Variation of gamma',
type=float, default=2.0)
args = parser.parse_args()
args.input_dir = args.input_dir.rstrip('http://xilinx.eetrend.com/')
args.output_dir = args.output_dir.rstrip('http://xilinx.eetrend.com/')
return args
'''
根據(jù)進(jìn)程數(shù)和要增加的目標(biāo)圖片數(shù),
生成每個進(jìn)程要處理的文件列表和每個文件要增加的數(shù)目
'''
def generate_image_list(args):
# 獲取所有文件名和文件總數(shù)
filenames = os.listdir(args.input_dir)
num_imgs = len(filenames)
# 計算平均處理的數(shù)目并向下取整
num_ave_aug = int(math.floor(args.num/num_imgs))
# 剩下的部分不足平均分配到每一個文件,所以做成一個隨機幸運列表
# 對于幸運的文件就多增加一個,湊夠指定的數(shù)目
rem = args.num - num_ave_aug*num_imgs
lucky_seq = [True]*rem + [False]*(num_imgs-rem)
random.shuffle(lucky_seq)
# 根據(jù)平均分配和幸運表策略,
# 生成每個文件的全路徑和對應(yīng)要增加的數(shù)目并放到一個list里
img_list = [
(os.sep.join([args.input_dir, filename]), num_ave_aug+1 if lucky else num_ave_aug)
for filename, lucky in zip(filenames, lucky_seq)
]
# 文件可能大小不一,處理時間也不一樣,
# 所以隨機打亂,盡可能保證處理時間均勻
random.shuffle(img_list)
# 生成每個進(jìn)程的文件列表,
# 盡可能均勻地劃分每個進(jìn)程要處理的數(shù)目
length = float(num_imgs) / float(args.num_procs)
indices = [int(round(i * length)) for i in range(args.num_procs + 1)]
return [img_list[indices[i]:indices[i + 1]] for i in range(args.num_procs)]
# 每個進(jìn)程內(nèi)調(diào)用圖像處理函數(shù)進(jìn)行擾動的函數(shù)
def augment_images(filelist, args):
# 遍歷所有列表內(nèi)的文件
for filepath, n in filelist:
img = cv2.imread(filepath)
filename = filepath.split(os.sep)[-1]
dot_pos = filename.rfind('.')
# 獲取文件名和后綴名
imgname = filename[:dot_pos]
ext = filename[dot_pos:]
print('Augmenting {} ...'.format(filename))
for i in range(n):
img_varied = img.copy()
# 擾動后文件名的前綴
varied_imgname = '{}_{:0>3d}_'.format(imgname, i)
# 按照比例隨機對圖像進(jìn)行鏡像
if random.random() < args.p_mirror:
# 利用numpy.fliplr(img_varied)也能實現(xiàn)
img_varied = cv2.flip(img_varied, 1)
varied_imgname += 'm'
# 按照比例隨機對圖像進(jìn)行裁剪
if random.random() < args.p_crop:
img_varied = ia.random_crop(
img_varied,
args.crop_size,
args.crop_hw_vari)
varied_imgname += 'c'
# 按照比例隨機對圖像進(jìn)行旋轉(zhuǎn)
if random.random() < args.p_rotate:
img_varied = ia.random_rotate(
img_varied,
args.rotate_angle_vari,
args.p_rotate_crop)
varied_imgname += 'r'
# 按照比例隨機對圖像進(jìn)行HSV擾動
if random.random() < args.p_hsv:
img_varied = ia.random_hsv_transform(
img_varied,
args.hue_vari,
args.sat_vari,
args.val_vari)
varied_imgname += 'h'
# 按照比例隨機對圖像進(jìn)行Gamma擾動
if random.random() < args.p_gamma:
img_varied = ia.random_gamma_transform(
img_varied,
args.gamma_vari)
varied_imgname += 'g'
# 生成擾動后的文件名并保存在指定的路徑
output_filepath = os.sep.join([
args.output_dir,
'{}{}'.format(varied_imgname, ext)])
cv2.imwrite(output_filepath, img_varied)
# 主函數(shù)
def main():
# 獲取輸入輸出和變換選項
args = parse_args()
params_str = str(args)[10:-1]
# 如果輸出文件夾不存在,則建立文件夾
if not os.path.exists(args.output_dir):
os.mkdir(args.output_dir)
print('Starting image data augmentation for {}
'
'with
{}
'.format(args.input_dir, params_str))
# 生成每個進(jìn)程要處理的列表
sublists = generate_image_list(args)
# 創(chuàng)建進(jìn)程
processes = [Process(target=augment_images, args=(x, args, )) for x in sublists]
# 并行多進(jìn)程處理
for p in processes:
p.start()
for p in processes:
p.join()
print(' Done!')
if __name__ == '__main__':
main()
為了排版方便,并沒有很遵守Python的規(guī)范(PEP8)。注意到除了前面提的三種類型的變化,還增加了鏡像變化,這主要是因為這種變換太簡單了,順手就寫上了。還有默認(rèn)進(jìn)程數(shù)用的是cpu_count()函數(shù),這個獲取的是cpu的核數(shù)。把這段代碼保存為run_augmentation.py,然后在命令行輸入:
>> python run_augmentation.py -h
或者
>> python run_augmentation.py --help
就能看到腳本的使用方法,每個參數(shù)的含義,還有默認(rèn)值。接下里來執(zhí)行一個圖片增加任務(wù):
>> python run_augmentation.py imagenet_samples more_samples 1000 --rotate_angle_vari 180 --p_rotate_crop 0.5
其中imagenet_samples為一些從imagenet圖片url中隨機下載的一些圖片,--rotate_angle_vari設(shè)為180方便測試全方向的旋轉(zhuǎn),--p_rotate_crop設(shè)置為0.5,讓旋轉(zhuǎn)裁剪對一半圖片生效。擾動增加后的1000張圖片在more_samples文件夾下,得到的部分結(jié)果如下:
評論
查看更多