MaskRcnn(二)实例分割的图像与标签同时进行增强

2023-11-05

一、增强原因

1、防止过拟合

1.1、过拟合的定义

为了得到一致假设而使假设变得过度严格。
也就是说模型在训练集上的表现很好,但在测试集和新数据上的表现很差。
欠拟合,过拟合,适度拟合的区别。

训练集表现 测试集表现 结论
欠拟合
过拟合
适度拟合

1.2、过拟合出现的原因

①、模型复杂度过高,参数过多。
②、训练数据少。
③、训练集和测试集分布不一致。
④、样本里面的噪声数据干扰过大,导致模型过分记住了噪声特征,反而忽略了真实的输入输出特征。
⑤、训练集和测试集特征分布不一样。

1.3、解决方法

①、降低模型复杂度
②、扩大数据集或者进行数据增强
③、正则化
④、早停
⑤、清洗异常数据

2、增强结果模型的鲁棒性和泛化能力。

以下为我的理解,鲁棒性我理解为训练数据集中可能会出现一些错误,对这些错误的容忍能力越好,鲁棒性就越强,反之亦反,而泛化能力就是面对位置数据的一种预测能力,比如说我在A数据集上训练的,但在B数据集上仍然有比较好的表现,说明该模型或算法泛化能力比较好。

2.1、鲁棒性

模型对异常数据的容忍能力。

2.2、泛化性

模型对未知数据的预测能力。

3、提高识别精度

精度可以理解为模型好坏,把A预测为A,把B预测为B,预测的越准,精度越高。

二、常用数据增强方法

1、平移

对图像进行各个方向上的移动。

2、缩放

对图像进行缩小放大处理。

3、旋转

对图像进行一定角度的旋转。

4、随机裁切

对图像进行随机的裁剪。

5、颜色抖动

对图像的曝光度(exposure)、饱和度(saturation)和色调(hue)进行随机变化形成不同光照及颜色下的图片,达到数据增强的目的,尽可能使得模型能够使用不同光照条件小的情形,提高模型泛化能力。

6、随机遮挡

对图像进行小区域的遮挡。

7、噪声扰动:

对图像的每个像素RGB进行随机扰动, 常用的噪声模式是椒盐噪声和高斯噪声。

三、实例分割数据增强实现

因为实例分割数据集实在太难标记了,数据增强必不可少,使用手动标记的数据加上随机水平翻转进行训练后效果一般,决定把数据再一次进行增强,因为采用的是labelme标记的数据,必须对原图加上标签同时进行转变,决定尝试尝试。

1、旋转

对图像进行一定角度的旋转。
因为之前对原始数据加上水平翻转后的数据进行训练后,发现效果不是特别理想,看了看效果图后,发现原始数据大多数都是很规整的,而测试的数据如果有的物体不正,就会导致识别不出来,如下图。
在这里插入图片描述
如果比较规整,还蛮好识别的。
在这里插入图片描述
于是决定首先对图像进行旋转处理。

1.1先观察一下json文件

{
    "version": "4.5.9",               //labelme的版本号
    "flags": {},                      //flag标记
    "shapes": [                       //边由点构成的多边形
      {
        "line_color": null,           //线的颜色
        "fill_color": null,           //填充颜色
        "label": "2",                 //标签
        "points": [                   //一个个点,这里只列出一个点。
          [
            1365.8296754954001,
            1075.6984533100115
          ]
        ],
        "group_id": 1,                //实体的id号,同一类的第几个
        "shape_type": "polygon",      //图形类型
        "flags": {}                   //flag标记
      }
    ],
    "imagePath": "1.jpg"              //图片的位置

后面就是一长串一长串的东西,可以不用管它。根据这个json文件的特征进行修改标签。

1.2、导入必要的库

import cv2        #计算机视觉库
import json       #用来解析json文件
import numpy as np  #科学计算包
import sys #处理Python运行时配置以及资源
import os  #负责程序与操作系统的交互,提供了访问操作系统底层的接口。
import random  #实现了各种分布的伪随机数生成
import time #处理时间的标准库
import base64 #编解码库
from math import cos ,sin ,pi,fabs,radians #内置数学类函数库

1.3、导入图片

图片数量很多,不可能一张张图片进行,直接对一个文件里所有图片进行相同处理。

import cv2 as cv
import os
images_path = 'C:/Users/Administrator/Desktop/PersonCode/data/'  #图片的根目录
save_path = "C:/Users/Administrator/Desktop/PersonCode/sava_data/" #保存图片文件夹
file_list = os.listdir(images_path)
for img_name in file_list:
    print(img_name)

1.4、读取json文件

同样得对json进行批量读取,不过要注意每一张图片和json对应起来,这样处理的时候才能正确,下面给出读取json文件的代码,完整代码会放在最后面。
#读取json文件

def ReadJson(jsonfile):
    with open(jsonfile,encoding='utf-8') as f:
        jsonData = json.load(f)
    return jsonData

1.5、对图片进行旋转

图像旋转函数如下

def RotateImage(img, degree):
    height, width = img.shape[:2]    #获得图片的高和宽
    heightNew = int(width * fabs(sin(radians(degree))) + height * fabs(cos(radians(degree))))
    widthNew = int(height * fabs(sin(radians(degree))) + width * fabs(cos(radians(degree))))
    matRotation = cv2.getRotationMatrix2D((width // 2, height // 2), degree, 1)
    matRotation[0, 2] += (widthNew - width) // 2
    matRotation[1, 2] += (heightNew - height) // 2
    print(width // 2,height // 2)
    imgRotation = cv2.warpAffine(img, matRotation, (widthNew, heightNew), borderValue=(255, 255, 255))
    return imgRotation,matRotation

在这里插入图片描述
背景可以改cv2的参数进行替换,image_rotate = cv2.warpAffine(image, M, (nW, nH),borderValue=(255,255,255))中的borderValue删了,改成用边缘颜色填充即可,加上参数borderMode=1,也就是改成imgRotation = cv2.warpAffine(img, matRotation, (widthNew, heightNew),borderMode=1)。
虽然看着有些别扭,但是能训练就行。
在这里插入图片描述

1.6、对图片进行裁剪

发现旋转后的图片有些高,因为很多都是补充出来的,而我使用的数据集大多数在中间,其实可以四周裁剪一下。
采用以下方法

imgRotation=imgRotation[imgRotation.shape[0]//9:(imgRotation.shape[0]//9)*8,imgRotation.shape[1]//9:(imgRotation.shape[1]//9)*8]

其实就是从长和宽的九分之一处到九分之八处裁剪一下。imgRotation[0]处理的是y方向(纵),imgRotation[1]处理x方向(横),裁剪后得改标签,慢慢探索。

1.7、对标签进行旋转

#坐标旋转
def rotatePoint(Srcimg_rotate,jsonTemp,M,imagePath):
    json_dict = {}
    for key, value in jsonTemp.items():
        if key=='imageHeight':
            json_dict[key]=Srcimg_rotate.shape[0]
            print('gao',json_dict[key])
        elif key=='imageWidth':
            json_dict[key] = Srcimg_rotate.shape[1]
            print('kuai',json_dict[key])
        elif key=='imageData':
            json_dict[key] = image_to_base64(Srcimg_rotate)
        elif key=='imagePath':
            json_dict[key] = imagePath
        else:
            json_dict[key] = value
    for item in json_dict['shapes']:
        for key, value in item.items():
            if key == 'points':
                for item2 in range(len(value)):
                    pt1=np.dot(M,np.array([[value[item2][0]],[value[item2][1]],[1]]))
                    value[item2][0], value[item2][1] = pt1[0][0], pt1[1][0]
    return json_dict

1.7、保存图片

cv2.imwrite("./result/"+img_name[:-4]+"_30"+'.jpg',img_rotate)
WriteJson('./result/'+img_name[:-4]+"_30"+'.json', json_rotate)

1.8、完整代码

import cv2        #计算机视觉库
import json       #用来解析json文件
import numpy as np  #科学计算包
import sys #处理Python运行时配置以及资源
import os  #负责程序与操作系统的交互,提供了访问操作系统底层的接口。
import random  #实现了各种分布的伪随机数生成
import time #处理时间的标准库
import base64 #编解码库
from math import cos ,sin ,pi,fabs,radians #内置数学类函数库
images_path = 'C:/Users/Administrator/Desktop/PersonCode/data/'  #图片的根目录
json_path='C:/Users/Administrator/Desktop/PersonCode/json/'  #json文件的根目录
save_path = "C:/Users/Administrator/Desktop/PersonCode/sava_data/" #保存图片文件夹
#读取json文件
def ReadJson(jsonfile):
    with open(jsonfile,encoding='utf-8') as f:
        jsonData = json.load(f)
    return jsonData
#保存json
def WriteJson(filePath,data):
    write_json = open(filePath,'w')
    write_json.write(json.dumps(data,indent=2)) 
    write_json.close()
def rotate_bound(image, angle):
    h, w,_ = image.shape
    (cX, cY) = (w // 2, h // 2)
    M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY
    image_rotate = cv2.warpAffine(image, M, (nW, nH),borderMode=1)
    return image_rotate,cX,cY,angle
def RotateImage(img, degree):
    height, width = img.shape[:2]    #获得图片的高和宽
    heightNew = int(width * fabs(sin(radians(degree))) + height * fabs(cos(radians(degree))))
    widthNew = int(height * fabs(sin(radians(degree))) + width * fabs(cos(radians(degree))))
    matRotation = cv2.getRotationMatrix2D((width // 2, height // 2), degree, 1)
    matRotation[0, 2] += (widthNew - width) // 2
    matRotation[1, 2] += (heightNew - height) // 2
    print(width // 2,height // 2)
    imgRotation = cv2.warpAffine(img, matRotation, (widthNew, heightNew),borderMode=1)
    
    return imgRotation,matRotation
def rotate_xy(x, y, angle, cx, cy):
    # print(cx,cy)
    angle = angle * pi / 180
    x_new = (x - cx) * cos(angle) - (y - cy) * sin(angle) + cx
    y_new = (x - cx) * sin(angle) + (y - cy) * cos(angle) + cy
    return x_new, y_new
#转base64
def image_to_base64(image_np):
    image = cv2.imencode('.jpg', image_np)[1]
    image_code = str(base64.b64encode(image))[2:-1]
    return image_code
#坐标旋转
def rotatePoint(Srcimg_rotate,jsonTemp,M,imagePath):
    json_dict = {}
    for key, value in jsonTemp.items():
        if key=='imageHeight':
            json_dict[key]=Srcimg_rotate.shape[0]
            print('gao',json_dict[key])
        elif key=='imageWidth':
            json_dict[key] = Srcimg_rotate.shape[1]
            print('kuai',json_dict[key])
        elif key=='imageData':
            json_dict[key] = image_to_base64(Srcimg_rotate)
        elif key=='imagePath':
            json_dict[key] = imagePath
        else:
            json_dict[key] = value
    for item in json_dict['shapes']:
        for key, value in item.items():
            if key == 'points':
                for item2 in range(len(value)):
                    pt1=np.dot(M,np.array([[value[item2][0]],[value[item2][1]],[1]]))
                    value[item2][0], value[item2][1] = pt1[0][0], pt1[1][0]
    return json_dict

if __name__=='__main__':
    file_list = os.listdir(images_path)
    i=0
    for img_name in file_list:
        i=i+1
        if i==211:
            break
        SrcImg=cv2.imread(images_path+img_name)            #读取图片
        JsonData=ReadJson(json_path+img_name[:-3]+'json')    #读取对应的json文件
        img_rotate,mat_rotate=RotateImage(SrcImg, 30)    #旋转图片
        json_rotate=rotatePoint(img_rotate,JsonData,mat_rotate,img_name)
        cv2.imwrite("./result/"+img_name[:-4]+"_30"+'.jpg',img_rotate)
        WriteJson('./result/'+img_name[:-4]+"_30"+'.json', json_rotate)
        print(img_name,"is ok!")

后面的处理方式和代码后续会补上。

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

MaskRcnn(二)实例分割的图像与标签同时进行增强 的相关文章

随机推荐

  • 算法实现之二叉树的前序、中序、后序递归和非递归遍历以及层序遍历

    概述 二叉树是每个节点最多有两个子树的树结构 通常子树被称作左子树和右子树 二叉树的遍历通常分为 前序遍历 中序遍历 后序遍历和层序遍历 前序遍历 前序递归遍历算法 访问根结点 gt 递归遍历根结点的左子树 gt 递归遍历根结点的右子树 中
  • linux tr命令完整,linux tr命令详解

    tr命令可以对来自标准输入的字符进行替换 压缩和删除 下面由学习啦小编为大家整理了linux tr命令的相关知识 希望对大家有帮助 linux tr命令用途 tr命令可以对来自标准输入的字符进行替换 压缩和删除 它可以将一组字符变成另一组字
  • 大数据分析——云南的花样之旅

    认真阅读过小伙伴们的评论 最终将我们此行的目的地定在了山清水秀的云南了 对于从小生活在北方的小编 对云南还是抱着不小的憧憬呢 下面就来看看数据人员给出的官方数据吧 首先我们就来说说久负盛名的云南大理吧 先看一下数据 看了下数据结果 小编才知
  • 【好工具】不需要知道地址,一个命令就能下载任何文件,它不香吗?

    今天介绍一款浏览器插件 可以直接将文件的下载链接直接转换成 Linux 命令 方便无操作界面的电脑下载无直链的文件 作者 编辑 Leong 导言 使用过 Linux 的朋友可能知道 大部分软件都是不支持 Linux 系统的 Windows系
  • List及String类的Contains方法底层源码解析

    public boolean Contains Object o 此处的o即为contains方法中的参数对象 return indexOf o gt 0 如果数值 gt 0 则返回true public int indexOf Objec
  • mysql中的Date日期格式的问题:只有日期没有时间及格式化时间

    只有日期没有时间 把xml中的date改为timestamp 格式化最简单的方法 JsonFormat pattern yyyy MM dd HH mm ss timezone GMT 8 转载于 https www cnblogs com
  • day7pyecharts制图-组合图

    Pyecharts制图 标题一 柱状图 导入柱状图的类 from pyecharts charts import Bar 导入图标配置类 from pyecharts import options 基本的柱状图 1 创建图标对象 bar B
  • 在Linux上部署KVM和使用

    实验前 我们关闭防火墙 systemctl stop firewalld systemctl enable firewalld 如果我们之前安装过KVM或者有残余 可以先执行以下命令来清除一下 yum remove rpm qa egrep
  • oracle中常用的set命令

    time 2008 2 1author skate oracle中常用的set命令 前一阵在做数据库数据的转移 所以就写个shell脚本来自动化完成 用shell脚本生成sql脚本时 就要用到oracle的set的命令来去掉一些不需要的提示
  • JVM内存划分

    1 程序计数器 每一个线程都有自己的一个程序计数器 创建线程时被一起创建 用于记录当前字节码执行位置 例如一个线程在执行过程中被挂起 一定时间片后 又继续执行 此时需要进行现场恢复 那么就可以在对应的程序记录器中找到被挂起时的下一条指令将要
  • java中mybatis原理,mybatis的工作原理

    由以上图可以看出 mybatis框架在操作数据库时大致经过了8个步骤 对这8个步骤分析如下 1 读取mybatis配置文件mybatis config xml mybatis config xml配置文件作为mybatis的全局配置文件 配
  • C++多态

    多态是C 面向对象三大特性之一 多态分为两类 静态多态 函数重载 和 运算符重载属于静态多态 复用函数名 动态多态 派生类和虚函数实现运行时多态 静态多态和动态多态区别 静态多态的函数地址早绑定 编译阶段确定函数地址 动态多态的函数地址晚绑
  • 图像处理:摩尔纹

    文章目录 1 什么是摩尔纹 2 怎样消除摩尔纹 总结 1 什么是摩尔纹 什么是摩尔纹 当我们对着电脑屏幕拍照时 会发现规则的彩色条纹 那就是我们常说的摩尔纹 它是由于采样不足 离散图像数据混淆产生的 刚才说的在空域上的混淆产生的摩尔纹 时域
  • 2021-05-14 thread已经退出析构qtcreator中仍显示thread正在运行

    threadobject已经析构 thread isrunning 是false thread isfinishing 也是true 说明thread退出了 但是qtcreator调试窗口中还是可见Qthread状态竟然是正在运行 什么鬼
  • python的22个基本语法

    人生苦短 我用Python Python编程语言是最容易学习 并且功能强大的语言 只需会微信聊天 懂一点英文单词即可学会Python编程语言 但是很多人声称自己精通Python 然后自己却写不出Pythonic的代码 对很多常用的包不是很了
  • 使用QT对MYSQL数据库进行简单操作

    include 在这里插入代码片 QtMySql h include
  • Transformer之编码器

    Bert是从transformer中衍生出来的预训练的模型 transformer模型已经得到广泛应用 应用的方式是先进行预训练语言模型 然后把预训练的模型适配给下游任务 以完成各种不同的任务 比如分类 生成 标记等 1 transform
  • windows10配置自己的深度学习、机器学习工作站

    活动地址 CSDN21天学习挑战赛 1 anaconda3 官网 下载速度超级慢 查找镜像源 Windows Python 3 9 64 Bit Graphical Installer的传到了csnd下载链接 右键 管理员身份运行 否则有的
  • 前端js数据加密解密

    一 最简单的加密解密 函数escape 和unescape 二 base64加密 1 introduction base64是网络上最常见的用于传输8bit字节码的编码方式之一 base64就是一种基于64个可打印字符来表示二进制数据的方法
  • MaskRcnn(二)实例分割的图像与标签同时进行增强

    实例分割数据增强 一 增强原因 1 防止过拟合 1 1 过拟合的定义 1 2 过拟合出现的原因 1 3 解决方法 2 增强结果模型的鲁棒性和泛化能力 2 1 鲁棒性 2 2 泛化性 3 提高识别精度 二 常用数据增强方法 1 平移 2 缩放