目标识别数据集扩充方法_如何扩大目标检测的测试集-程序员宅基地

技术标签: 计算机视觉  深度学习  图像识别  

背景引入

在训练图像识别的深度神经网络时,使用大量更多的训练数据,可能会使网络得到更好的性能,例如提高网络的分类准确率,防止过拟合等。人为扩展训练数据时对数据的操作最好能反映真实世界的变化。人为扩充数据集之后如果分类准确率有明显的提升,说明我们对数据所做的拓展操作是良性的,能够“反映真实世界的变化”,就会被用到整个数据集的扩展。反之,则说明不能用此操作对数据集进行拓展。

例如在2003年Patrice Simard等人所著的一篇论文中[1]他们把MNIST手写数字数据集通过旋转,转换和扭曲进行扩展。通过在这个扩展后的数据集上的训练,他们把MNIST手写数字识别的准确率提升到了98.9%。然后还在“弹性扭曲”的数据集上进行了实验,这是一种特殊的为了模仿手部肌肉的随机抖动的图像扭曲方法。通过使用弹性扭曲扩展的数据,他们最终达到了99.3%的分类准确率。

具体方法

原图

demo.jpg

图像强度变换

亮度变化

lightness

darkness

图像整体加上一个随机偏差,或整体进行尺度的放缩

  • 亮度增强

    demo_brightness.jpg
  • 亮度减弱

    demo_darkness.jpg
brightness = 1 + np.random.randint(1, 9) / 10
brightness_img = img.point(lambda p: p * brightness)

不影响label的位置

对比度变化

contrast

扩展图像灰度级动态范围,对两极的像素进行压缩,对中间范围的像素进行扩展

range_contrast=(-50, 50)
contrast = np.random.randint(*range_contrast)
contrast_img = img.point(lambda p: p * (contrast / 127 + 1) - contrast)

不影响label的位置

demo_contrast.jpg

图像滤波

锐化

sharpen

增强图像边缘信息

identity = np.array([[0, 0, 0],
                     [0, 1, 0],
                     [0, 0, 0]])
sharpen = np.array([[ 0, -1,  0],
                    [-1,  4, -1],
                    [ 0, -1,  0]]) / 4
max_center = 4
sharp = sharpen * np.random.random() * max_center
kernel = identity + sharp
sharpen_img = cv2.filter2D(img, -1, kernel)

不影响label的位置

demo_sharpen.jpg
高斯模糊

blur

图像平滑

kernel_size = (7, 7)
blur_img = cv2.GaussianBlur(img,kernel_size,0)

不影响label的位置

demo_blur.jpg

透视变换

镜像翻转

flip

使图像沿长轴进行翻转

flip_img = cv2.flip(cv2.cvtColor(np.asarray(img),cv2.COLOR_RGB2BGR), 1)

第一个位置的参数 pos = 1 - pos,其他信息不变,可以采用脚本自动生成

with open(name + "_flip.txt", "w") as outfile:
  with open(name + ".txt", "r") as infile:
    for line in infile.readlines():
      words = line.split(" ")
      horizontal_coord = float(words[1])
      outfile.write(words[0] + " " + str(format(1-horizontal_coord, ".6f")) + " " + words[2] + " " + words[3] + " " + words[4])
demo_flip.jpg
图像裁剪

crop

裁剪原图80%大小的中心图像,并进行随机移动

kernel_size = list(map(lambda x: int(x*0.8), size))
shift_min, shift_max = -50, 50
shift_size = [np.random.randint(shift_min, shift_max), np.random.randint(shift_min, shift_max)]

crop_img = img[
  (size[0]-kernel_size[0])//2+shift_size[0]:(size[0]-kernel_size[0])//2+kernel_size[0]+shift_size[0],
  (size[1]-kernel_size[1])//2+shift_size[1]:(size[1]-kernel_size[1])//2+kernel_size[1]+shift_size[1]
]

可能将目标对象裁减掉,因此采用手工重新标注

demo_crop.jpg
图像拉伸

deform

拉伸成长宽为原始宽的正方形图像

deform_img = img.resize((int(w), int(w)))

原图中比例信息改变,最好重新手工标注

demo_deform.jpg
镜头畸变

distortion

对图像进行透视变化,模拟鱼眼镜头的镜头畸变

通过播放径向系数k1,k2,k3和切向系数p1,p2实现

d_coef= np.array((0.15, 0.15, 0.1, 0.1, 0.05))
# get the height and the width of the image
h, w = img.shape[:2]
# compute its diagonal
f = (h ** 2 + w ** 2) ** 0.5
# set the image projective to carrtesian dimension
K = np.array([[f, 0, w / 2],
              [0, f, h / 2],
              [0, 0,   1  ]])
d_coef = d_coef * np.random.random(5) # value
d_coef = d_coef * (2 * (np.random.random(5) < 0.5) - 1) # sign
# Generate new camera matrix from parameters
M, _ = cv2.getOptimalNewCameraMatrix(K, d_coef, (w, h), 0)
# Generate look-up tables for remapping the camera image
remap = cv2.initUndistortRectifyMap(K, d_coef, None, M, (w, h), 5)
# Remap the original image to a new image
distortion_img = cv2.remap(img, *remap, cv2.INTER_LINEAR)

最好重新手工标注

demo_distortion.jpg

注入噪声

椒盐噪声

noise

在图像中随机添加白/黑像素

for i in range(5000):
  x = np.random.randint(0,rows)
  y = np.random.randint(0,cols)
  noise_img[x,y,:] = 255
  noise_img.flags.writeable = True

不影响label的位置

demo_noise.jpg
渐晕

vignetting

对图像添加一个圆范围内的噪声模拟光晕

ratio_min_dist=0.2
range_vignette=np.array((0.2, 0.8))
random_sign=False

h, w = img.shape[:2]
min_dist = np.array([h, w]) / 2 * np.random.random() * ratio_min_dist

# create matrix of distance from the center on the two axis
x, y = np.meshgrid(np.linspace(-w/2, w/2, w), np.linspace(-h/2, h/2, h))
x, y = np.abs(x), np.abs(y)
# create the vignette mask on the two axis
x = (x - min_dist[0]) / (np.max(x) - min_dist[0])
x = np.clip(x, 0, 1)
y = (y - min_dist[1]) / (np.max(y) - min_dist[1])
y = np.clip(y, 0, 1)
# then get a random intensity of the vignette
vignette = (x + y) / 2 * np.random.uniform(*range_vignette)
vignette = np.tile(vignette[..., None], [1, 1, 3])
sign = 2 * (np.random.random() < 0.5) * (random_sign) - 1
vignetting_img = img * (1 + sign * vignette)

不影响label的位置

demo_vignetting.jpg

其他

随机抠除

cutout

随机抠出四个位置,并用黑色/彩色矩形填充

channel_wise = False
max_crop = 4
replacement=0

size = np.array(img.shape[:2])
mini, maxi = min_size_ratio * size, max_size_ratio * size
cutout_img = img
for _ in range(max_crop):
  # random size
  h = np.random.randint(mini[0], maxi[0])
  w = np.random.randint(mini[1], maxi[1])
  # random place
  shift_h = np.random.randint(0, size[0] - h)
  shift_w = np.random.randint(0, size[1] - w)

  if channel_wise:
    c = np.random.randint(0, img.shape[-1])
    cutout_img[shift_h:shift_h+h, shift_w:shift_w+w, c] = replacement
    else:
      cutout_img[shift_h:shift_h+h, shift_w:shift_w+w] = replacement

不影响label的位置

demo_cutout.jpg
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/double_ZZZ/article/details/115691995

智能推荐

【Android功能测试 如何定位bug】_自己写的安卓软件出bug怎么知道-程序员宅基地

文章浏览阅读1.1k次。话不多说,直接上定位1.4XX 客户端问题, 比如发生了401,那么要看下是否带了正确的身份验证信息;发生了403则要看下是否 有权限访问;404则要看下对应的URL是否真实存在;真实场景(直接提bug给前端开发,管他4几几,哈哈)​ 2.5xx服务端出现问题(配合服务器log进行定位,发生了502错误则可能是服务器挂了导致的问题、发生503 错误可能是由于网络过载导致的问题、发生504错误则可能是程序执行时间过长导致超时);真实场景(直接提bug给后端开发,管他5几几,哈哈)3.android功能测_自己写的安卓软件出bug怎么知道

python 中 冒泡排序 等while、for循环的总结_利用一个for和一个while实现排序-程序员宅基地

文章浏览阅读1.2k次。一、冒泡排序的案例二、字符串遍历案例三、for 循环计算1~100的和四、for 循环计算1~100的偶数和六、for循环打印矩形七、for循环输入数据打印矩形八、for循环打印三角形九、for循环打印九九乘法表十、键盘录入年龄案例十一、continue 循环案例..._利用一个for和一个while实现排序

BI的体系架构及相关技术_bi架构-程序员宅基地

文章浏览阅读3.1k次。一个BI系统为了满足企业管理者的要求,从浩如烟海的资料中找出其关心的数据,必须要做到以下几步:1)为了整合各种格式的数据,清除原有数据中的错误记录——数据预处理的要求。2)对预处理过数据,应该统一集中起来——元数据(Meta Data)、数据仓库(Data Warehouse)的要求;3)最后,对于集中起来的庞大的数据集,还应进行相应的专业统计,从中发掘出对企业决策有价值的新的机会——..._bi架构

Tensorflow Serving部署推荐模型_tfserving 输出key怎么制定-程序员宅基地

文章浏览阅读1k次。Tensorflow Serving部署推荐模型1、找到当前模型中定义的variables,并在此定义一个saver用于保存模型参数def saveVariables(self): variables_dict = {} variables_dict[self.user_embedding.op.name] = self.user_embedding variables_dict[self.item_embedding.op.name] = self.item_embedding_tfserving 输出key怎么制定

【JavaWeb】servlet response.getWriter().print()输出中文乱码�_response.getwriter().print指定字符集-程序员宅基地

文章浏览阅读455次。request.setCharacterEncoding(“utf-8”);response.setContentType(“text/html;charset=utf-8”);_response.getwriter().print指定字符集

如何用社群引流裂变?社群裂变引流怎么操作?_就是利用公司社群资源进行社群裂变引流就行了-程序员宅基地

文章浏览阅读490次。什么是社群裂变?社群裂变开始是要有一个群,通过与群里的成员互动有过一段时间的交流,有一定的信任度了,群成员也对你有一定的了解之后,然后加对方为好友的一个路径这就是一个简单的从社群里面裂变出来的粉丝,我们也要通过一些途径进入到一些精准的微信群中去。为什么我要讲社群裂变呢?社群裂变可以给企业和创业者带来流量,一个企业最重要的不是员工,重要的是如何获取流量的方式,社群裂变能给企业带来大量的客流量,我们通过这些流量可以成交然后再裂变更多的流量,这样可以给企业带来很大的收益,社群流量给你的网店也是可以同样的获_就是利用公司社群资源进行社群裂变引流就行了

随便推点

js实现下载excel_exceljs.workbook()-程序员宅基地

文章浏览阅读6.3k次,点赞2次,收藏7次。excel是常见的表格处理工具,那么前端怎么实现excel生成与下载呢?我们利用xlsx.js来实现一. 安装js-xlsxnpm install xlsx二. 文档简介完成的XLSX对象:需要理解的术语:1 workbook是xlsx读取excel内容后的js对象,读取到内容后可以对表格进行操作;同样的也可以创建一个空的workbook,往其中写入内容完整的workbook对象..._exceljs.workbook()

php 启动workman,workerman如何启动-程序员宅基地

文章浏览阅读1.5k次。Workerman启动停止等命令都是在命令行中完成的。要启动Workerman,首先需要有一个启动入口文件,里面定义了服务监听的端口及协议。Workerman启动的方法:以debug(调试)方式启动php start.php start以daemon(守护进程)方式启动php start.php start -ddebug和daemon方式区别:1、以debug方式启动,代码中echo、var_d..._workman 启动

wperl与perl-程序员宅基地

文章浏览阅读174次。以前在xp下,可以用wperl运行"*.pl"的文件,而不现实一个dos窗口,但在vista中不行了,需要更改文件的扩展名为"wpl",才能通过wperl运行,否则只能以perl运行。[@more@]以前在xp下,可以用wper..._wperl是什么文件

电脑W7系统怎样安装鸿蒙系统,家用电脑升级win7系统的操作方法-程序员宅基地

文章浏览阅读7.5k次。原标题:家用电脑升级win7系统的操作方法虽然xp系统运行流畅,但是现在电脑硬件更新换代速度非常快,xp系统已经不适合高配置的电脑安装使用,甚至会降低硬件的性能,所以我们需要升级到更新版本的系统,那么电脑要怎么样升级win7系统呢?一起看看家用电脑升级win7系统的操作方法吧。家用电脑升级win7系统的操作方法1、下载打开咔咔装机软件,选择U盘重装系统。 2、选择U盘模式,点击“开始制作”下一步。..._windows7鸿蒙

后端程序员成长之路_后端程序员的成长-程序员宅基地

文章浏览阅读2.2k次。今天,收到了转正通知,很开心。实习过去了两个半月,感谢我的公司,也要感谢我的leader。在公司实习的这段日子里,对我帮助最大的人就是我的leader,我逐渐从刚进入公司时的新人状态成长了许多,多了几分从容,也多了几分信心。 2018年9月份即将开始,我很幸运的能留在公司,不必参加秋招,希望自己能珍惜这次机会,努力成长。 那么,接下来的几个月我应该做些什么呢?我们在做业务的过程中,一定不能忘了..._后端程序员的成长

android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity_exception calling sethistory-程序员宅基地

文章浏览阅读1k次。android.util.AndroidRuntimeException: Calling startActivity() from outside of an ActivityCaused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity contex_exception calling sethistory

推荐文章

热门文章

相关标签