常用9类图像数据增强处理方法(可应用于图像分类、目标检测等场景)-附Python源码

2023-05-16

本文将分享下我做图像识别项目工作过程中常用的关于图像分类数据处理方法,如有不当之处,欢迎大家指正。

图像数据增强

我们做项目过程中,经常会遇到某些类的图像数据出现严重不足,比如低于100张,我们就可以通过现有图像,经过数据增强算法来进行扩充,这里我主要介绍了:增加噪声、图像变暗/变亮、拉伸图像、旋转图像、水平翻转图像、裁切图像、颜色抖动等图像数据增强方式,供小伙伴们参考。

其实图像数据增强还有很多算法,比如图像变形、图像裁切组合、图像平移、直方图均衡化、gamma变换、滤波和随机噪声等等,小伙伴们在使用过程中可以多试下看哪种增强算法比较适用于自己的模型,再选择使用。

另外在某些图像分类、目标检测、生成对抗网络算法中,为了提高模型的泛化性能,也可以在参数里面设置选择是否进行数据增强,直接使用。

图像数据处理过程中,常用到两个比较强大的图像处理库,可以使用pip直接进行安装。
其中注意opencv库一直在更新,可以按照弹出来的提示,修改链接云里面有的版本进行安装。

pip3 install Pillow
pip3 install -i https://mirror.aliyun.com/pypi/simple opencv-python==3.4.2.16
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python==3.4.2.16
import cv2
from PIL import Image, ImageEnhance
import time
import numpy as np


class Image_enhance():
    def __init__(self,rootPath):
    	"""
        :param rootPath: 图像输入路径
        """
        self.rootPath = rootPath
        self.export_path_base = rootPath[:-4] #图像输出路径基
        self.image = cv2.imread(rootPath)
        self.class_name = rootPath.split("\\")[-2]

    def get_savename(self,operate_name):
        """
        :param operate_name: 图像使用的数据增强操作类名
        :return: 返回图像存储名
        """
        try:

            # 获取时间戳,用于区分图像
            now = time.time()
            tail_time = str(round(now * 1000000))[-4:]  # 时间戳尾数
            head_time = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
            # 时间标签
            label = str(head_time + tail_time) + '_' + str(operate_name)

            # 输出文件夹
            export_path_base = self.export_path_base
            # 子文件夹以“操作operate”命名
            out_path = export_path_base
            # 创建子文件夹
            # if not os.path.exists(out_path):
            #     os.mkdir(out_path)

            # 存储完整路径
            savename = out_path + '_' + label + ".jpg"

            return savename

        except Exception as e:
            print(e)


    def SaltAndPepper(self, percetage=0.2):
        """给图片增加椒盐噪声"""
        SP_NoiseImg = self.image.copy()
        SP_NoiseNum = int(percetage * self.image.shape[0] * self.image.shape[1])
        for i in range(SP_NoiseNum):
            randR = np.random.randint(0, self.image.shape[0] - 1)
            randG = np.random.randint(0, self.image.shape[1] - 1)
            randB = np.random.randint(0, 3)
            if np.random.randint(0, 1) == 0:
                SP_NoiseImg[randR, randG, randB] = 0
            else:
                SP_NoiseImg[randR, randG, randB] = 255
        percetage_name = str(percetage*100).replace('.','')
        operate_name = 'SaltAndPepper_' + percetage_name
        save_name = self.get_savename(operate_name)
        cv2.imwrite(save_name,SP_NoiseImg)
        print('{}做数据增强{} 完毕 '.format(self.class_name,operate_name))


    def addGaussianNoise(self, percetage=0.2):
        """给图片增加高斯噪声"""
        G_Noiseimg = self.image.copy()
        w = self.image.shape[1]
        h = self.image.shape[0]
        G_NoiseNum = int(percetage * self.image.shape[0] * self.image.shape[1])
        for i in range(G_NoiseNum):
            temp_x = np.random.randint(0, h)
            temp_y = np.random.randint(0, w)
            G_Noiseimg[temp_x][temp_y][np.random.randint(3)] = np.random.randn(1)[0]
        percetage_name = str(percetage*100).replace('.','')
        operate_name = 'addGaussianNoise_' + percetage_name
        save_name = self.get_savename(operate_name)
        cv2.imwrite(save_name,G_Noiseimg)
        print('{}做数据增强{} 完毕 '.format(self.class_name,operate_name))

    def darker(self, percetage=0.87):
        """减低图片像素,是图片变昏暗"""
        image_darker = self.image.copy()
        w = self.image.shape[1]
        h = self.image.shape[0]
        # get darker
        for xi in range(0, w):
            for xj in range(0, h):
                image_darker[xj, xi, 0] = int(self.image[xj, xi, 0] * percetage)
                image_darker[xj, xi, 1] = int(self.image[xj, xi, 1] * percetage)
                image_darker[xj, xi, 2] = int(self.image[xj, xi, 2] * percetage)
        percetage_name = str(percetage*100).replace('.','')
        operate_name = 'darker_' + percetage_name
        save_name = self.get_savename(operate_name)
        cv2.imwrite(save_name,image_darker)
        print('{}做数据增强{} 完毕 '.format(self.class_name, operate_name))

    def brighter(self, percetage=1.07):
        """增强图片像素,使图片变亮"""
        image_brighter= self.image.copy()
        w = self.image.shape[1]
        h = self.image.shape[0]
        # get brighter
        for xi in range(0, w):
            for xj in range(0, h):
                image_brighter[xj, xi, 0] = np.clip(int(self.image[xj, xi, 0] * percetage), a_max=255, a_min=0)
                image_brighter[xj, xi, 1] = np.clip(int(self.image[xj, xi, 1] * percetage), a_max=255, a_min=0)
                image_brighter[xj, xi, 2] = np.clip(int(self.image[xj, xi, 2] * percetage), a_max=255, a_min=0)
        percetage_name = str(percetage*100).replace('.','')
        operate_name = 'brighter_' + percetage_name
        save_name = self.get_savename(operate_name)
        cv2.imwrite(save_name,image_brighter)
        print('{}做数据增强{} 完毕 '.format(self.class_name, operate_name))

    def rotate(self, angle=15, center=None, scale=1.0):
        """按指定角度旋转"""
        (h, w) = self.image.shape[:2]
        # If no rotation center is specified, the center of the image is set as the rotation center
        if center is None:
            center = (w / 2, h / 2)
        m = cv2.getRotationMatrix2D(center, angle, scale)
        rotate_image = cv2.warpAffine(self.image.copy(), m, (w, h))
        angle_name = str(angle).replace('.','')
        operate_name = 'rotate_' + angle_name
        save_name = self.get_savename(operate_name)
        cv2.imwrite(save_name,rotate_image)
        return save_name


    def flip(self):
        """水平翻转."""
        flipped_image = np.fliplr(self.image.copy())
        operate_name = 'flip_'
        save_name = self.get_savename(operate_name)
        cv2.imwrite(save_name,flipped_image)

    def deform(self):
        """图像拉伸."""
        try:
            operate = 'deform_'
            # 图像完整路径
            rootPath = self.rootPath

            with Image.open(rootPath) as image:
                w, h = image.size
                w = int(w)
                h = int(h)
                if not w == h:
                    # 拉伸成宽为w的正方形
                    out_ww = image.resize((int(w), int(w)))
                    operate_name_ww = operate + str(w)
                    savename_ww = self.get_savename(operate_name_ww)
                    out_ww.save(savename_ww, quality=100)
                    # 拉伸成宽为h的正方形
                    out_hh = image.resize((int(h), int(h)))
                    operate_name_hh = operate + str(h)
                    savename_hh = self.get_savename(operate_name_hh)
                    out_hh.save(savename_hh, quality=100)
                else:
                    pass

            # 日志
            # logger.info(operate)
        except Exception as e:
            # logger.error('ERROR %s', operate)
            # logger.error(e)
            print(e,"ERROR"+str(operate))

    def crop(self,choose):
        """提取四个角落和中心区域."""
        """:choose 指选择哪种操作,共可以选择五种切割操作"""
        try:
            operate = 'crop_'
            # 图像完整路径
            rootPath = self.rootPath

            with Image.open(rootPath) as image:
                w, h = image.size
                # 切割后尺寸
                scale = 0.875
                # 切割后长宽
                ww = int(w * scale)
                hh = int(h * scale)
                # 图像起点,左上角坐标
                x = y = 0

                # 切割左上角
                if choose =='lu':
                    x_lu = x
                    y_lu = y
                    out_lu = image.crop((x_lu, y_lu, ww, hh))
                    operate_lu_name =operate + 'lu'
                    savename_lu = self.get_savename(operate_lu_name)
                    out_lu.save(savename_lu, quality=100)
                # logger.info(operate + '_lu')

                # 切割左下角
                elif choose =='ld':
                    x_ld = int(x)
                    y_ld = int(y + (h - hh))
                    out_ld = image.crop((x_ld, y_ld, ww, hh))
                    operate_ld_name =operate + 'ld'
                    savename_ld = self.get_savename(operate_ld_name)
                    out_ld.save(savename_ld, quality=100)
                # logger.info(operate + '_ld')

                # 切割右上角
                elif choose =='ru':
                    x_ru = int(x + (w - ww))
                    y_ru = int(y)
                    out_ru = image.crop((x_ru, y_ru, w, hh))
                    operate_ru_name =operate + 'ru'
                    savename_ru = self.get_savename(operate_ru_name)
                    out_ru.save(savename_ru, quality=100)
                # logger.info(operate + '_ru')

                # 切割右下角
                elif choose == 'rd':
                    x_rd = int(x + (w - ww))
                    y_rd = int(y + (h - hh))
                    out_rd = image.crop((x_rd, y_rd, w, h))
                    operate_rd_name =operate + 'rd'
                    savename_rd = self.get_savename(operate_rd_name)
                    out_rd.save(savename_rd, quality=100)
                # logger.info(operate + '_rd')

                # 切割中心
                elif choose == 'ce':
                    x_ce = int(x + (w - ww) / 2)
                    y_ce = int(y + (h - hh) / 2)
                    out_ce = image.crop((x_ce, y_ce, ww, hh))
                    operate_ce_name =operate + 'center'
                    savename_ce = self.get_savename(operate_ce_name)
                    out_ce.save(savename_ce, quality=100)
                else:
                    xx = ['lu','ld','ru','rd','ce']
                    print('未剪切成功,请检查choose选择剪切的参数是否为{}中的一个'.format(xx))
                # logger.info('提取中心')
        except Exception as e:
            # logger.error('ERROR %s', 1)
            # logger.error(e)
            print(e,"ERROR"+str(operate))

    def image_color(self):
        """
        对图像进行颜色抖动
        """
        image = Image.open(self.rootPath)
        random_factor = np.random.randint(low=0, high=31) / 10.0  # 随机的扰动因子
        color_image = ImageEnhance.Color(image).enhance(random_factor)  # 调整图像的饱和度
        random_factor = np.random.randint(low=10, high=21) / 10.0
        bright_image = ImageEnhance.Brightness(color_image).enhance(random_factor)  # 调整图像的亮度
        random_factor = np.random.randint(low=10, high=21) / 10.0
        contrast_image = ImageEnhance.Contrast(bright_image).enhance(random_factor)  # 调整图像的对比度
        random_factor = np.random.randint(low=0, high=31) / 10.0
        sharp_image = ImageEnhance.Sharpness(contrast_image).enhance(random_factor)  # 调整图像的锐度
        operate_color_name = 'color_'
        savename_color = self.get_savename(operate_color_name)
        sharp_image.save(savename_color)

本文只供大家学习相关知识使用,不以任何商业盈利为目的,转载或分享请注明相关来源。如涉及到相关侵权,请联系我删除。
欢迎志同道合者互相交流学习,可以扫以下二维码添加我的个人微信。
个人微信号

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

常用9类图像数据增强处理方法(可应用于图像分类、目标检测等场景)-附Python源码 的相关文章

  • c++编译器配置错误问题clang: error: linker command failed with exit code 1 (use -v to see invocation)

    背景 xff1a ubuntu18 04系统 之前装其他程序的时候安装了一些软件 xff0c 不知道什么时候g 43 43 编译器从 usr bin c 43 43 组里面给删掉了 xff0c 默认的编译器成了clang 43 43 xff
  • apollo7.0------浅谈激光雷达运动补偿(二)--计算解析

    背景介绍 运动补偿相关介绍参考第一篇博客 xff1a apollo7 0 浅谈激光雷达运动补偿 龙性的腾飞的博客 CSDN博客 lidar运动补偿 本篇博客主要解释一下上篇博客中运动补偿的计算部分 xff0c 简单来说就是一个利用四元数球面
  • Matlab激光雷达相机联合标定经验分享

    一 背景介绍 联合标定是做多传感器融合的基础工作 xff0c 也是一个没有最好只有更好的研究方向 xff0c 相关论文也是层出不穷 xff0c 网上也有许多开源的工作 xff0c 包括Autoware的工具箱我也试过 xff0c 感觉标定效
  • 如何更改Ubuntu系统的输出为HDMI(耳机,扬声器)?

    由于需要用HDMI外接音频设备 xff0c 故想要改变电脑输出 xff0c 本人用的为Ubuntu14 04 开始在网上搜寻怎么更改 xff0c 查到需在声音设置里面更改音频输出为HDMI xff0c 可当我打开声音设置 xff0c 嗯 x
  • PPT中插入图片背景透明化小技巧

    新版的编辑器真不适应 xff0c 费劲 xff01 xff01 xff01 最近两天做开题答辩ppt xff0c 发现了ppt中处理图片背景的一个小技巧 xff0c 在此分享给大家 PPT一般会带有背景图片 xff0c 那种带浅色调logo
  • ROS发布Float32MultiArray消息C++/Python

    在ros下发布一个字符串消息或整数消息 xff0c 网上例程不少 xff0c ROSwiki上也有教程 xff0c 有时就需要一次发送不止一个数据 xff0c 这时候就得用到数组了 xff0c C 43 43 的也好找 xff0c 不过py
  • c++中string、char *、char[]相互转换

    一 string转char 主要有三种方法可以将str转换为char 类型 xff0c 分别是 xff1a data c str copy 其中 xff0c copy 可能会报安全性错误 xff0c 自行解决即可 3 1 data 方法 s
  • char数组与char指针

    转载来源 xff1a https www cnblogs com nzbbody p 3553222 html https blog csdn net jack 20 article details 78913202 一 0 的添加 存在的
  • linux下tcpdump的使用

    简介 用简单的话来定义tcpdump xff0c 就是 xff1a dump the traffic on a network xff0c 根据使用者的定义对网络上的数据包进行截获的包分析工具 tcpdump可以将网络中传送的数据包的 头
  • khadas vim3安装ros1

    khadas vim3 按照网上的方法可以正常安装ros2 xff0c 但是按照ros1则可能会有一些奇奇怪怪的问题导致按照失败 xff0c 不过在一位群友的帮助下 xff0c 找到了解决的方法 khadas vim3 将源换为下面 xff
  • 【Android】CMake添加多个c文件

    1 准备工作 先下相关的插件 xff0c 进入setting xff0c 勾选这LLDB NDK CMake三个 xff0c 点击OK后即可下载 2 Native C 43 43 工程 简单总结一下CMake使用的操作步骤 1 新建Nati
  • 什么是字节序(端序、低端字节序、高端字节序、网络字节序)

    前言 一个内容为12 xff08 字符串 xff09 的文本文件 xff0c 它的第一个字节是什么 xff08 小端序 xff09 xff1f 如果你的回答是0x32 xff0c 那你真的应该好好理解下字节序了 如下图所示 xff0c 我这
  • APM中电机输出分析

    一 APM类分析 老规矩 xff0c 先上类图 xff08 1 xff09 如图 xff08 1 xff09 所示 xff0c AP Motors是大部分电机类的父类 xff0c 是AC AttitudeControl姿态控制类的保护型成员
  • 解决安装ROS时出现的sudo rosdep init错误问题

    解决安装ROS时出现的sudo rosdep init错误问题 目前安装ROS时输入sudo rosdep init的命令时 xff0c 可能会出现以下的错误 xff1a ERROR cannot download default sour
  • JS实现HTTP请求头-Basic Authorization

    HTTP协议中的 Authorization 请求消息头含有服务器用于验证用户代理身份的凭证 xff0c 通常会在服务器返回401 Unauthorized 状态码以及WWW Authenticate 消息头之后在后续请求中发送此消息头 A
  • C语言Post和Get方法 ,拿过去直接用

    C语言post 和get 方法的实现 我自己实现的post 和get 请求方法 xff0c 可以直接使用在单片机上 xff0c 比如ESP32 上 xff0c OPl1000 上面 xff0c 下面直接上代码 span class toke
  • QT中图表类QChart系列之(1)-基本用法,画折线图、各个类之间的关系

    参考 xff1a https www cnblogs com yunhaisoft p 5180127 html 首先要注意3点 xff1a xff08 1 xff09 在 pro文件中添加 xff1a QT 43 61 charts xf
  • STM32使用FIFO实现USART串口发送中断

    fifo就不要造轮子了 xff0c 用现成的就行了 linux内核中有目前人类写出的基于c语言的最强FIFO xff0c 请自行搜索学习 巧夺天工的kfifo xff0c kfifo精妙无比 xff0c 实在是高 xff0c 其中用到的环回
  • c++的json读取操作

    使用的开源库是nlohmann json 后续操作也都是基于该开源库操作 本地json文件如下 xff1a 34 model config 34 34 model type 34 34 paddlex 34 34 model cfg fil
  • 三维重建了解

    一 三维重建方法 1 1 传统方法 RGBD D来源结构光或者TOF xff1a 缺点 xff0c 重建范围受限 xff0c 一般不能重建大模型 xff1b 比如 xff0c kinectFusion xff0c DynamicFusion

随机推荐

  • docker容器常用命令

    一 常用命令 显示本地镜像 xff1a docker images 显示已经启动的容器 xff1a docker ps a 从docker hub拉取镜像 reed98 airsim v0是镜像名 xff1a docker pull ree
  • ARM学习随笔(12)定时器查询方式和中断方式

    定时器详细讲解 百度文库 点击打开链接 xff08 一 xff09 查询方式和中断方式的区别在于 xff1a 查询方式不断查询标志位然后进行处理 xff0c 而中断要编写中断服务子程序来处理中断事件 xff08 二 xff09 内部中断是指
  • vgg16网络裁剪并加载模型参数

    主要是测试下模型裁剪后转onnx的问题 删除vgg16网络全连接层 xff0c 加载预训练模型并重新保存模型参数 xff0c 将该参数用于转onnx模型格式 usr bin env python coding utf 8 64 Time 2
  • pth转onnx的三种情况

    usr bin env python coding utf 8 64 Time 2022 8 3 16 19 64 Author weiz 64 ProjectName cbir 64 File pth2onnx py 64 Descrip
  • 以vgg为backbone的简易图像检索系统

    图像检索 xff08 Content based Image Retrieval xff0c 简称CBIR xff09 即以图搜图 xff0c 基于图片语义信息 xff0c 诸如颜色 纹理 布局 CNN based高层语义等特征检索技术 该
  • img2pose: Face Alignment and Detection via 6DoF, Face Pose Estimation代码理解

    import argparse import os import sys import time import numpy as np from PIL import Image ImageOps from torchvision impo
  • 解决普通用户使用sudo找不到命令

    sudo bazel build c opt define MEDIAPIPE DISABLE GPU 61 1 mediapipe examples desktop face mesh face mesh cpu 出现 xff1a sud
  • sfm算法之三角化(三角测量)

    sfm算法流程一般是特征点提取 特征点匹配 计算本质矩阵 基础矩阵 xff0c 最后三角化 但是利用机械臂去观察周围 xff0c 前后帧姿态变化参数是具有的 xff0c 所以不需要通过基础矩阵获取 即利用机械臂的信息直接进行深度估计 已知
  • bazel构建项目案例(第三方库,编译成库,运行案例)

    使用bazel构建项目 xff0c 包含如何引入外部库 xff08 项目中引入了opencv和编译的tensorflow lite库 xff09 xff0c 如何编译成动态库和静态库 xff0c 以及如何调用编译好的库 项目根目录的所有文件
  • 各种小功能集二

    各种小功能集一 十一 C C 43 43 路径解析 头文件 std string UtilsGetPath const char pszFilename std string UtilsGetDirname const char pszFi
  • windows10配置paddleOCR的CPU版本总结

    paddleOCR的CPU版本依赖的库还是比较少的 如下 1 opencv库 本人配置的版本是opencv4 5 0 2 paddle inference 推理库 该库解压后有version txt文件 xff0c 版本信息如下 xff1a
  • 传统图像技术的边缘提取

    usr bin env python coding utf 8 import cv2 import os import numpy as np def laplacian img ksize 61 3 laplacian 61 cv2 La
  • TCP-UDP网络编程调试助手下载

    下载地址 xff1a 可能需要谷歌 xff1a 软件干净 xff0c 挺好用的 xff0c 如果有更好的 xff0c 欢迎留言 xff01 https www waveshare com wiki File TCP UDP Debug 7z
  • Data Matrix码的使用

    一 引言 Data Matrix原名Data code xff0c 由美国国际资料公司 International Data Matrix 简称ID Matrix 于1989年发明 Data Matrix又可分为ECC000 140与ECC
  • 小样本学习(Few-Shot Learning)训练参数意义

    一 常规参数 1 1 epoch 是指所有的训练数据都要跑一遍 假设有6400个样本 xff0c 在训练过程中 xff0c 这6400个样本都跑完了才算一个epoch 一般实验需要训练很多个epoch xff0c 直到LOSS稳定后才停止
  • 不同相机之间图片像素对应关系求解(单应性矩阵求解)

    一 场景 相机1和相机2相对位置不变 xff0c 相机拍摄图片有重叠 xff0c 求他们交叠部分的一一对应关系 数学语言描述为已知相机1图片中P点像素 u1 v1 xff0c 相机1中P点在相机2图片中像素值为 u2 v2 xff0c 它们
  • python协程学习

    一 什么是协程及实现方式 1 1 协程 又称微线程 xff0c 纤程 也称为用户级线程 xff0c 在不开辟线程的基础上完成多任务 xff0c 也就是在单线程的情况下完成多任务 xff0c 多个任务按照一定顺序交替执行 1 2 实现方式 g
  • 无法打开文件libboost_random-vc141-mt-s-x64-1_81.lib

    踩坑过程 xff1a 需要使用websocketpp工具 xff0c 得先安装boost 安装boost及websocketpp过程简单且顺利 xff0c 并且能正常能正常运行官方例程 把官方例程简单封装测试 xff0c 一切皆好 等把we
  • 如何一步让你图像分类达到90%以上精准度

    这段时间一直在做图像分类相关的项目 xff0c 也认识了很多这个领域的小伙伴们 xff0c 有不少小伙伴们都是刚接触图像分类 xff0c 对着各种个样的图像分类算法 xff1a AlexNet VGG 16 VGG 19 ResNet 都是
  • 常用9类图像数据增强处理方法(可应用于图像分类、目标检测等场景)-附Python源码

    本文将分享下我做图像识别项目工作过程中常用的关于图像分类数据处理方法 xff0c 如有不当之处 xff0c 欢迎大家指正 图像数据增强 我们做项目过程中 xff0c 经常会遇到某些类的图像数据出现严重不足 xff0c 比如低于100张 xf