图片数据增强,包括模糊,亮度,裁剪,旋转,平移,镜像 ,python ,LabelImg,LabelMe工具

图片数据增强,包括模糊,亮度,裁剪,旋转,平移,镜像 ,python ,LabelImg,LabelMe工具

  • 1 对象检测图片数据增强(使用labelImg工具)
  • 2 对象分割图片数据增强(使用labelMe工具)
      • 参考

    本屌打完标签之后,想着能不能找个python脚本找到对应的图片和xml文件帮我增强一下,然后用yolo去训练,效果应该会好一些,但是找了一圈后,发现网上大牛是有很多,但每个人都贴一点代码,没有稍微完整一点的,所以本屌决定动手用python整一个,以后打标签就少打一点了,只有天知道我打标签的痛苦,那么多零件要训练,真要命。
  好了,找了一圈后,还是找了一些demo,具体参考了一个github上的大牛,最后的参考给出了链接,我拿来瞎改了一下,能用吧,然后基于这个,自己又搞了一个基于labelMe标定的json数据的图片增强,因为最近的新项目要用。大概就是这样吧。



完整代码,我放在github上了:https://github.com/pureyangcry/tools


  希望对您有帮助!谢谢!

1 对象检测图片数据增强(使用labelImg工具)

  首先来张图片(网上找的,https://jingyan.baidu.com/article/574c52193e33f96c8d9dc1e4.html)

图片数据增强,包括模糊,亮度,裁剪,旋转,平移,镜像 ,python ,LabelImg,LabelMe工具_第1张图片
  对于这张图片,我们使用labelImg工具进行标注,会得到对应的xml文件,结果如下:

图片数据增强,包括模糊,亮度,裁剪,旋转,平移,镜像 ,python ,LabelImg,LabelMe工具_第2张图片
    现在我们要实现一些图片增强,比如模糊,亮度,裁剪,旋转,平移,镜像等变化,同时我们希望,标签也跟着变化,比如下面这样的结果:
图片数据增强,包括模糊,亮度,裁剪,旋转,平移,镜像 ,python ,LabelImg,LabelMe工具_第3张图片
    好的,大概我们就实现了,效果还行吧?会同时得到对应的新图片和xml文件结果。

  实现这个图片增强效果的部分代码如下:

# 加噪声
    def _addNoise(self, img):
        '''
        输入:
            img:图像array
        输出:
            加噪声后的图像array,由于输出的像素是在[0,1]之间,所以得乘以255
        '''
        # return cv2.GaussianBlur(img, (11, 11), 0)
        return random_noise(img, mode='gaussian', seed=int(time.time()), clip=True) * 255

    # 调整亮度
    def _changeLight(self, img):
        alpha = random.uniform(0.35, 1)
        blank = np.zeros(img.shape, img.dtype)
        return cv2.addWeighted(img, alpha, blank, 1 - alpha, 0)



保存xml的代码:
```javascript
 # 保持xml结果
    def save_xml(self, file_name, save_folder, img_info, height, width, channel, bboxs_info):
        '''
        :param file_name:文件名
        :param save_folder:#保存的xml文件的结果
        :param height:图片的信息
        :param width:图片的宽度
        :param channel:通道
        :return:
        '''
        folder_name, img_name = img_info  # 得到图片的信息

        E = objectify.ElementMaker(annotate=False)

        anno_tree = E.annotation(
            E.folder(folder_name),
            E.filename(img_name),
            E.path(os.path.join(folder_name, img_name)),
            E.source(
                E.database('Unknown'),
            ),
            E.size(
                E.width(width),
                E.height(height),
                E.depth(channel)
            ),
            E.segmented(0),
        )

        labels, bboxs = bboxs_info  # 得到边框和标签信息
        for label, box in zip(labels, bboxs):
            anno_tree.append(
                E.object(
                    E.name(label),
                    E.pose('Unspecified'),
                    E.truncated('0'),
                    E.difficult('0'),
                    E.bndbox(
                        E.xmin(box[0]),
                        E.ymin(box[1]),
                        E.xmax(box[2]),
                        E.ymax(box[3])
                    )
                ))

        etree.ElementTree(anno_tree).write(os.path.join(save_folder, file_name), pretty_print=True)

**完整程序请参考最上面,给出的github链接的DataAugForObjectDetection中的内容。**




2 对象分割图片数据增强(使用labelMe工具)

    还是那张图片,恩,牧羊犬还是小时候好看,长大了就丑了(初一小时候就很好看,哈哈)

  现在使用LabelMe工具来标注,不出意外会得到一个json文件,结果如下:

图片数据增强,包括模糊,亮度,裁剪,旋转,平移,镜像 ,python ,LabelImg,LabelMe工具_第4张图片
    现在我们来实现这个结果的增强,能力有限,目前只做到了模糊、亮度、平移、镜像等变化。

    效果如下:

图片数据增强,包括模糊,亮度,裁剪,旋转,平移,镜像 ,python ,LabelImg,LabelMe工具_第5张图片
    贴上部分代码:

  # 随机的改变点的值
    def _addRandPoint(self, img):
        percent = self.rand_point_percent
        num = int(percent * img.shape[0] * img.shape[1])
        for i in range(num):
            rand_x = random.randint(0, img.shape[0] - 1)
            rand_y = random.randint(0, img.shape[1] - 1)
            if random.randint(0, 1) == 0:
                img[rand_x, rand_y] = 0
            else:
                img[rand_x, rand_y] = 255
        return img

    # 平移
    def _shift_pic_bboxes(self, img, json_info):

        # ---------------------- 平移图像 ----------------------
        h, w, _ = img.shape
        x_min = w
        x_max = 0
        y_min = h
        y_max = 0

        shapes = json_info['shapes']
        for shape in shapes:
            points = np.array(shape['points'])
            x_min = min(x_min, points[:, 0].min())
            y_min = min(y_min, points[:, 1].min())
            x_max = max(x_max, points[:, 0].max())
            y_max = max(y_max, points[:, 0].max())

        d_to_left = x_min  # 包含所有目标框的最大左移动距离
        d_to_right = w - x_max  # 包含所有目标框的最大右移动距离
        d_to_top = y_min  # 包含所有目标框的最大上移动距离
        d_to_bottom = h - y_max  # 包含所有目标框的最大下移动距离

        x = random.uniform(-(d_to_left - 1) / 3, (d_to_right - 1) / 3)
        y = random.uniform(-(d_to_top - 1) / 3, (d_to_bottom - 1) / 3)

        M = np.float32([[1, 0, x], [0, 1, y]])  # x为向左或右移动的像素值,正为向右负为向左; y为向上或者向下移动的像素值,正为向下负为向上
        shift_img = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]))

        # ---------------------- 平移boundingbox ----------------------
        for shape in shapes:
            for p in shape['points']:
                p[0] += x
                p[1] += y
        return shift_img, json_info

    # 镜像
    def _filp_pic_bboxes(self, img, json_info):

        # ---------------------- 翻转图像 ----------------------
        h, w, _ = img.shape

        sed = random.random()

        if 0 < sed < 0.33:  # 0.33的概率水平翻转,0.33的概率垂直翻转,0.33是对角反转
            flip_img = cv2.flip(img, 0)  # _flip_x
            inver = 0
        elif 0.33 < sed < 0.66:
            flip_img = cv2.flip(img, 1)  # _flip_y
            inver = 1
        else:
            flip_img = cv2.flip(img, -1)  # flip_x_y
            inver = -1

        # ---------------------- 调整boundingbox ----------------------
        shapes = json_info['shapes']
        for shape in shapes:
            for p in shape['points']:
                if inver == 0:
                    p[1] = h - p[1]
                elif inver == 1:
                    p[0] = w - p[0]
                elif inver == -1:
                    p[0] = w - p[0]
                    p[1] = h - p[1]

        return flip_img, json_info

    保存对应的json文件代码:

    # 对图片进行字符编码
    def img2str(self, img_name):
        with open(img_name, "rb")as f:
            base64_data = str(base64.b64encode(f.read()))
        match_pattern = re.compile(r'b\'(.*)\'')
        base64_data = match_pattern.match(base64_data).group(1)
        return base64_data

    # 保存图片结果
    def save_img(self, save_path, img):
        cv2.imwrite(save_path, img)

    # 保持json结果

    def save_json(self, file_name, save_folder, dic_info):
        with open(os.path.join(save_folder, file_name), 'w') as f:
            json.dump(dic_info, f, indent=2)

完整代码请参考上面给出的github链接的DataAugForObjectSegmentation文件中的内容。

参考

[1] https://github.com/maozezhong/CV_ToolBox/blob/master/DataAugForObjectDetection

你可能感兴趣的:(深度学习-目标检测)