使用yolo3实现图片中的数字检测与识别(五):图像的读取与增广

技术凯 2021-06-14 02:59:16 5926

  在上一篇文章中,我们将数据集的标注信息单独保存在一个变量 'datas' 中,这是为了在使用yolo3进行训练时,可以更好地读取图片以及图片中的目标信息。本篇文章首先介绍如何进行图像文件以及对应信息的读取。此外,我们采集的数据集较少,需要对其进行增广处理,即采用一定的手法增加数据集的数量,以达到扩充数据集的目的。

一、数据集的读取

  首先我们回顾一下上一篇文章中保存的信息结构:

第一行是标注信息文件的路径;第二行是所有目标的标签值;第三行到第六行是每个目标的位置(使用(x1,y1,x2,y2)坐标方法);第七行和第八行是对应输入图像的尺寸。

  首先我们需要获取标注信息对应的图片路径。从文件结构中可以看到,图像数据的名称和对应的标注信息名称相同,而且二者在同一个文件夹中,因此我们只需更改标注信息文件名称的后缀即可。实现代码如下:

import os
import matplotlib.pyplot as plt
from matplotlib.image import imread

data=datas[0]
filename=data['filename'] # 获取文件名称
# 替换文件后缀,获取图像路径
name_split=os.path.splitext(filename)
imgname=name_split[0]+'.jpeg'
# 显示图像文件,观察名称是否正确
img=cv2.imread(imgname)
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 因为cv2图像格式为BGR,需要将其转换为RGB
plt.imshow(img)

显示图像文件,观察获取的名称是否正确:

可以正常读取图像,接下来,我们读取目标类别与目标位置:

obj_class=data['obj_class'] # 获取目标标签(类别)
# 获取目标位置
obj_location=np.vstack((data['obj_x1'],data['obj_y1'],data['obj_x2'],data['obj_y2']))
# 查看第一个目标位置
obj_location[:,0]

第一个目标位置坐标(坐标格式为(x1,y1,x2,y2)):

我们将此过程封装成函数,函数名为 'img_read' :

import os
import matplotlib.pyplot as plt
from matplotlib.image import imread
import numpy as np

# 定义一个函数,来根据标注信息读取文件中的图片,data变量存储了某一个图像的标注信息
def img_read(data):
    filename=data['filename'] # 获取文件名称
    # 替换文件后缀,获取图像路径
    name_split=os.path.splitext(filename)
    imgname=name_split[0]+'.jpeg'
    # 读取图像
    img=cv2.imread(imgname)
    img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 因为cv2图像格式为BGR,需要将其转换为RGB
    obj_class=data['obj_class'] # 获取目标标签(类别)
    # 获取目标位置
    obj_location=np.vstack((data['obj_x1'],data['obj_y1'],data['obj_x2'],data['obj_y2']))
    return img,obj_class,obj_location

使用该函数读取一张图片进行显示:

[img,obj_class,obj_location]=img_read(datas[10])
plt.imshow(img)

显示结果为:

二、图像的增广

  我们可以通过改变图像色调(对比度、亮暗、颜色等)、缩放、裁剪等方法生成更多的图像,以达到数据集扩充的目的,下面将一一对这些方法进行介绍:

1.随机改变图像色调

  通过随机改变图像的对比度、亮暗以及色度可以实现图像色调的随机改变,随机改变亮度可通过如下代码实现:

# 产生一个0.5-1.5的随机数,用于表示亮度的调节程度
t=np.random.uniform(0.5,1.5)
imag=Image.fromarray(img)
# 进行亮度调节
imag=ImageEnhance.Brightness(imag).enhance(t)
# 显示图像
plt.imshow(imag)

原始图片为:

改变亮度后的图片为:

随机调节对比度的代码如下:

# 产生一个0.5-1.5的随机数,用于表示对比度的调节程度
t=np.random.uniform(0.5,1.5)
imag=Image.fromarray(img)
# 调节对比度
imag=ImageEnhance.Contrast(imag).enhance(t)
# 显示图片
plt.imshow(imag)

改变对比度后的图像:

随机调节色度的相关代码:

# 产生一个0.5-1.5的随机数,用于表示对比度的调节程度
t=np.random.uniform(-1,3)
imag=Image.fromarray(img)
# 调节色度
imag=ImageEnhance.Color(imag).enhance(t)
# 显示图片
plt.imshow(imag)

改变后的图像:

本项目通过同时改变色度、对比度以及亮度,改变图像的色调:

from PIL import Image,ImageEnhance
import numpy as np
import matplotlib.pyplot as plt

# 产生一个0.5-1.5的随机数,用于表示亮度的调节程度
t=np.random.uniform(0.5,1.5)
imag=Image.fromarray(img)
# 调节亮度
imag=ImageEnhance.Brightness(imag).enhance(t)

# 产生一个0.5-1.5的随机数,用于表示对比度的调节程度
t=np.random.uniform(0.5,1.5)
# 调节对比度
imag=ImageEnhance.Contrast(imag).enhance(t)

# 产生一个0.5-1.5的随机数,用于表示对比度的调节程度
t=np.random.uniform(-5,5)
# 调节色度
imag=ImageEnhance.Color(imag).enhance(t)

# 显示图片
plt.imshow(imag)

原始图像与进行变换后的图像对比:

将该过程封装成函数,并包含图像的标注信息:

def rand_distort(img,obj_class,obj_location):
    # 产生一个0.5-1.5的随机数,用于表示亮度的调节程度
    t=np.random.uniform(0.5,1.5)
    imag=Image.fromarray(img)
    # 调节亮度
    imag=ImageEnhance.Brightness(imag).enhance(t)

    # 产生一个0.5-1.5的随机数,用于表示对比度的调节程度
    t=np.random.uniform(0.5,1.5)
    # 调节对比度
    imag=ImageEnhance.Contrast(imag).enhance(t)

    # 产生一个0.5-1.5的随机数,用于表示对比度的调节程度
    t=np.random.uniform(-5,5)
    # 调节色度
    imag=ImageEnhance.Color(imag).enhance(t)
    # 将图像格式由PIL转换为cv2
    imag=np.asarray(imag)
    return imag,obj_class,obj_location
2.随机缩放图像

  通过设置缩放比例的范围,实现随机缩放图像,相关代码如下:

import numpy as np

# 产生随机数,作为缩放的比例
xy_scale=np.random.uniform(0.5,1.5)
# 缩放
img=cv2.resize(img,None,fx=xy_scale, fy=xy_scale)
plt.imshow(img)

将上述过程封装成函数,在函数中,不仅图像被缩放,图像中目标的位置信息也随之变动:

def rand_scale(img,obj_class,obj_location):
    # 产生两个随机数,作为缩放的比例
    xy_scale=np.random.uniform(0.5,1.5)
    # 缩放
    img=cv2.resize(img,None,fx=xy_scale, fy=xy_scale)
    obj_location=np.int32(obj_location*xy_scale)
    return img,obj_class,obj_location
3.随机裁剪图像

  通过随机裁剪可以改变目标在图像中的位置以及占比,因此裁剪操作能够实现数据集的增广。通过随机设置裁切区域的起点(左上角),可以实现随机裁剪的过程。相关代码如下:

# 获取图像的尺寸
w=img.shape[0]
h=img.shape[1]
# 在图像中随机确定一个点作为裁剪区域的起点(左上角)
x1_cut=np.random.randint(0,2*w/3)
y1_cut=np.random.randint(0,2*h/3)
# 设定裁剪区域长宽比例
ratio_cut=0.3
# 确定裁剪区域的宽和高
w_cut=int(w*ratio_cut)
h_cut=int(h*ratio_cut)
# 确定裁剪区域
x2_cut=min(x1_cut+w_cut,w)
y2_cut=min(x2_cut+h_cut,h)
img_cut=img[x1_cut:x2_cut,y1_cut:y2_cut]
plt.imshow(img_cut)

裁剪后的图像如图:

将上述过程封装成函数,其中包含图像裁剪后标注信息的改变:

def rand_cut(img,obj_class,obj_location):
    # 获取图像的尺寸
    w=img.shape[0]
    h=img.shape[1]
    # 在图像中随机确定一个点作为裁剪区域的起点(左上角)
    x1_cut=np.random.randint(0,2*w/3)
    y1_cut=np.random.randint(0,2*h/3)
    # 设定裁剪区域长宽比例
    ratio_cut=0.3
    # 确定裁剪区域的宽和高
    w_cut=int(w*ratio_cut)
    h_cut=int(h*ratio_cut)
    # 确定裁剪区域
    x2_cut=min(x1_cut+w_cut,w)
    y2_cut=min(x2_cut+h_cut,h)
    img_cut=img[x1_cut:x2_cut,y1_cut:y2_cut]

    # 修改标注信息
    class_new=[]# 创建一个新数组,用来存储裁剪区域中的目标类别
    class_num=len(obj_class)# 获取目标个数

    location_new=np.zeros([4,class_num]) # 创建一个新数组,用来存储裁剪区域中的目标位置
    cut_box=[x1_cut,y1_cut,x2_cut,y2_cut] # 裁剪区域所在的矩形框
    # 判断每一个目标是否在裁剪区域内
    for i in range(class_num):
        obj_box=obj_location[:,i] # 目标所在的矩形框
        IoU=IoUofBox(obj_box,cut_box)# 计算目标与裁剪区域的交并比,判断目标是否在裁剪区域内
        i_new=0;
        if IoU>0:
            class_new=np.append(class_new,obj_class[i])
            # 确定裁剪区域内目标的新位置坐标
            obj_x1=max(obj_box[0],cut_box[0])-cut_box[0]
            obj_y1=max(obj_box[1],cut_box[1])-cut_box[1]
            obj_x2=min(obj_box[2],cut_box[2])-cut_box[0]
            obj_y2=min(obj_box[3],cut_box[3])-cut_box[1]
            location_new[:,i_new]=[obj_x1,obj_y1,obj_x2,obj_y2]
    # 转换数组类型
    class_new=np.array(class_new,dtype=np.int32)
    temp=location_new;
    location_new=np.zeros([4,len(class_new)])
    location_new=temp[:len(class_new)]
    location_new=np.array(location_new,dtype=np.int32)
    return img_cut,class_new,location_new
三、总结

  本文介绍了数据集的读取以及数据集的增广,增广后的数据集能够有效减少模型过拟合的现象,对于模型的训练性能有很大的提升。

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 92 4 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
技术凯
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区