zoukankan      html  css  js  c++  java
  • 【Tool】Augmentor和imgaug——python图像数据增强库

    Augmentor和imgaug——python图像数据增强库

    Tags: ComputerVision Python


    介绍两个图像增强库:Augmentor和imgaug,Augmentor使用比较简单,只有一些简单的操作。 imgaug实现的功能更多,可以对keypoint, bounding box同步处理,比如你现在由一些标记好的数据,只有同时对原始图片和标记信息同步处理,才能有更多的标记数据进行训练。我在segmentation和detection任务经常使用imgaug这个库。

    Augmentor

    http://augmentor.readthedocs.io/en/master/index.html
    Augmentor 是管道化的图像增强库,每一个增强操作都是逐步叠加在图像上。此外对于输入的图像,可以选择按照一定的概率进行增强,比如只随机对一半图像进行旋转。

    rotate(probability=0.5, max_left_rotation=5, max_right_rotation=10)
    

    可以实现的操作有, rotate, crop, perspective skew(视角倾斜), elastic distortions(弹性变换), sheering(坐标轴倾斜), mirroring(镜像)

    可以使用Augumentor.Pipeline()创建一个实例,调用各种方法向pipeline添加方法, status()可以显示当前pipeline的状态,在status中每个操作都有一个对应的index, remove_operation(index)移除一个操作, 最后调用sample(nums)得到nums个augument后的图像。

    import Augmentor
    p = Augmentor.Pipeline("/path/to/images/")
    p.status()
    p.remove_operation(0)
    

    rotate

    • rotate() 旋转,非90度旋转会带来padding或者裁剪
    • rotate90()
    • rotate180()
    • rotate270()
    • rotate_random_90() 随机旋转,90, 180, 270

    resize

    crop

    • crop_centre()
    • crop_by_size()
    • crop_random()

    sheer

    + sheer()

    mirroring

    • flip_left_right()
    • flip_top_bottom()
    • flip_random()

    elastic distortion

    • random_distortion()
      Before
      before.jpg
      After
      after.jpg
      弹性变换是在计算机视觉任务中经常使用的一种变换,比较有名的Segmentation Model U-Net就使用了elastic deformation来对自己的数据做Augmentation.最后取得了较好的效果.

    imgaug

    http://imgaug.readthedocs.io/en/latest/index.html

    安装

    依赖

    • numpy
    • scipy
    • scikit-image (pip install -U + scikit-image)
    • six (pip install -U six)
    • OpenCV (i.e. cv2 must be available in python). The library is mainly tested in OpenCV 2, but seems to also work in OpenCV 3.
    pip install git+https://github.com/aleju/imgaug
    

    或者

    pip install imgaug
    

    前者安装github最新版本,后者安装pypi版本。 

    basic

    Keypoint

    keypoint.jpg

    Bounding Boxes

    这个部分做object detection的人应该经常用到。

    imgaug支持:

    • 将bounding boxes作为对象表示
    • 增强boundiing boxes
    • 在图像上画bounding boxes
    • boxing boxes移动, 映射, 计算IoU

    Before
    box1.jpg
    After

    box.jpg

    由于VOC_PASCAL是在分割和检测领域常见的数据集,这里给出一个使用VOC_PASCAL标记格式进行数据增强的例子。
    标记格式:

    <?xml version="1.0" ?>
    <annotation>
    <folder>Pictures</folder>
    <filename>bndbox.jpg</filename>
    <path>/home/redtea/Pictures/bndbox.jpg</path>
    <source>
        <database>Unknown</database>
    </source>
    <size>
        <width>1200</width>
        <height>1200</height>
        <depth>3</depth>
    </size>
    
    <segmented>0</segmented>
        <object>
        <name>cat</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>49</xmin>
            <ymin>647</ymin>
            <xmax>599</xmax>
            <ymax>1125</ymax>
        </bndbox>
    </object>
        <object>
        <name>dog</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>678</xmin>
            <ymin>547</ymin>
            <xmax>1159</xmax>
            <ymax>1159</ymax>
        </bndbox>
    </object>
    </annotation>
    
    import xml.etree.ElementTree as ET 
    import pickle
    import  os
    from os import getcwd
    import numpy as np
    from PIL import Image
    import cv2
    
    import imgaug as ia 
    from imgaug import augmenters as iaa
    
    ia.seed(1)
    
    def read_xml_annotation(root,image_id):
    	in_file = open(os.path.join(root,image_id))
    	tree = ET.parse(in_file)
    	root = tree.getroot()
    
    	bndbox = root.find('object').find('bndbox')
    
    	xmin = int(bndbox.find('xmin').text)
    	xmax = int(bndbox.find('xmax').text)
    	ymin = int(bndbox.find('ymin').text)
    	ymax = int(bndbox.find('ymax').text)
    
    	return (xmin, ymin, xmax, ymax)
    
    def change_xml_annotation(root, image_id, new_target):
    	
    	new_xmin = new_target[0]
    	new_ymin = new_target[1]
    	new_xmax = new_target[2]
    	new_ymax = new_target[3]
    
    	in_file = open(os.path.join(root, str(image_id)+'.xml')) #这里root分别由两个意思
    	tree = ET.parse(in_file)
    	xmlroot = tree.getroot() 
    	object = xmlroot.find('object')
    	bndbox = object.find('bndbox')
    	xmin = bndbox.find('xmin')
    	xmin.text = str(new_xmin)
    	ymin = bndbox.find('ymin')
    	ymin.text = str(new_ymin)
    	xmax = bndbox.find('xmax')
    	xmax.text = str(new_xmax)
    	ymax = bndbox.find('ymax')
    	ymax.text = str(new_ymax)
    	tree.write(os.path.join(root,str(image_id)+"_aug"+'.xml'))
    
    
    
    
    
    if __name__ == "__main__":
    
    	cmd = os.getcwd()
    	image_id = "bndbox"
    	img = Image.open(os.path.join(cmd, str(image_id)+'.jpg'))
    	img = np.array(img)
    
    	bndbox = read_xml_annotation(cmd, str(image_id)+'.xml')
    
    	bbs = ia.BoundingBoxesOnImage([
    	   ia.BoundingBox(x1=bndbox[0], y1=bndbox[1], x2=bndbox[2], y2=bndbox[3])
    	], shape=img.shape)
    	seq = iaa.Sequential([
    	iaa.Flipud(0.5), # vertically flip 20% of all images
    	   iaa.Multiply((1.2, 1.5)), # change brightness, doesn't affect BBs
    	   iaa.Affine(
    	       translate_px={"x": 10, "y": 10},
    	       scale=(0.8, 0.95),
    	       rotate=(-10,10)
    	    ) # translate by 40/60px on x/y axis, and scale to 50-70%, affects BBs
    	])
    	seq_det = seq.to_deterministic() # 保持坐标和图像同步改变,而不是随机
    	image_aug = seq_det.augment_images([img])[0]
    	bbs_aug = seq_det.augment_bounding_boxes([bbs])[0]
    
    	before  = bbs.bounding_boxes[0]
    	after = bbs_aug.bounding_boxes[0]
    	print("BB : (%.4f, %.4f, %.4f, %.4f) -> (%.4f, %.4f, %.4f, %.4f)" % (
            before.x1, before.y1, before.x2, before.y2,
            after.x1, after.y1, after.x2, after.y2)
        )
    
    	image_before = bbs.draw_on_image(img, thickness=2)
    	image_after = bbs_aug.draw_on_image(image_aug, thickness=2)
    	Image.fromarray(image_before).save("before.jpg")
    	Image.fromarray(image_after).save('after.jpg')
    
    	new_bndbox = []
    	new_bndbox.append(int(bbs_aug.bounding_boxes[0].x1))
    	new_bndbox.append(int(bbs_aug.bounding_boxes[0].y1))
    	new_bndbox.append(int(bbs_aug.bounding_boxes[0].x2))
    	new_bndbox.append(int(bbs_aug.bounding_boxes[0].y2))
    	
    	# 修改xml tree 并保存
    	change_xml_annotation(cmd, image_id, new_bndbox)
    
    

    SxPAl.jpg

    SxawJ.jpg

    这个包好像不能画出倾斜的bounding box, 我的read xml程序只能读取第一个bounding box,懒得修改了。

    总之我觉得如果你Augmentor不能满足你就可以使用imgaug,但是有一点需要注意!imgaug中一些变换会给边缘区域带来黑色填充块,如果这些黑色填充块对你的模型有影响的话,就需要特殊处理!!

  • 相关阅读:
    SpringMVC-------1.spriingMVC简介和简单案例
    MyBatis-----7.pageHelper分页助手
    MyBatis-----4.实现关联表查询
    MyBatis-----6.逆向工程(generator)
    MyBatis-----1.MyBatis简介和使用
    MyBatis-----2.通过映射接口实现CRUD
    Spring-2
    Spring-1
    php调用阿里云手机归属地查询
    php身份证验证
  • 原文地址:https://www.cnblogs.com/vincentcheng/p/9186540.html
Copyright © 2011-2022 走看看