使用数据增强扩展数据集





5.00/5 (3投票s)
在本文中,我们将了解如何通过数据增强实现相同的结果。
引言
不受控制的野生动物对于企业和房主来说都是一个难题。像鹿、驼鹿甚至猫这样的动物都会对花园、庄稼和财产造成破坏。
在本系列文章中,我们将演示如何在树莓派上实时(或近乎实时)检测害虫(例如麋鹿),然后采取行动将其清除。由于我们不想造成任何伤害,我们将专注于通过播放响亮的声音来吓跑害虫。
欢迎您下载项目的源代码。我们假设您熟悉 Python,并对神经网络的工作原理有基本了解。
在上一篇文章中,我们准备了麋鹿分类数据集的初始版本。它包含 200 个“麋鹿”类别的样本和 284 个“背景”类别的样本。是不是有点小?在本文中,我们将演示如何在不收集新图像的情况下增强我们的数据集。
数据增强
数据增强通过各种图像修改从现有图像派生新样本。其中最常见的有几何变换、色彩空间变换、数据加噪和图像滤波。在应用数据增强算法时,我们应确保图像修改适合我们的数据集,并且不会损害样本。
让我们考虑一下我们的麋鹿数据集。哪种修改类型适用于它?
色彩空间变换和数据加噪无效。颜色是动物分类的重要特征,因此我们不应更改样本图像的色彩空间。数据加噪是包含手写数字或符号的数据集的有效技术。我们不期望这对自然栖息地中的麋鹿图像有用。
剩下的是几何变换和图像滤波。我们将在 Python 中实现它们时详细讨论这些。
几何变换
有许多几何变换可用于图像数据增强:翻转、旋转、缩放、裁剪、平移等。
一个明显且非常有用的变换是水平翻转,它相对于垂直轴镜像图像。
另一个流行的几何变换是旋转,它模拟从不同角度观察样本。请注意,此变换仅应应用适度的旋转角度以保留物体形状。
我们可以使用 Python OpenCV 软件包轻松实现几何变换
class FlipProcessor:
def name(self):
return "flip"
def process(self, image):
return cv2.flip(image, 1)
class RotateProcessor:
def __init__(self, angle, scale):
self.angle = angle
self.scale = scale
def name(self):
if self.angle>0:
sa = str(self.angle)
else:
sa = "_"+str(-self.angle)
return "rotate"+sa
def process(self, image):
(h, w, c) = image.shape
center = (w/2, h/2)
rmat = cv2.getRotationMatrix2D(center, self.angle, self.scale)
rotated = cv2.warpAffine(image, rmat, (w, h))
return rotated
图像过滤
图像滤波是一种有用但不太直观的数据增强类型。很难估计哪些滤波器可以从现有图像生成最有用的数据样本。
我们的数据集由从野生动物视频中提取的帧组成,因此可以合理地假设有些帧清晰,有些帧模糊。因此,锐化和模糊帧可以改进和多样化我们的数据集。这是 Python 代码中的实现方式
class SmoothProcessor:
def __init__(self, filter_size):
self.filter_size = filter_size
def name(self):
return "smooth"+str(self.filter_size)
def process(self, image):
smoothed = cv2.GaussianBlur(image,(self.filter_size, self.filter_size),0)
return smoothed
class SharpenProcessor:
def __init__(self, filter_size):
self.filter_size = filter_size
def name(self):
return "sharpen"+str(self.filter_size)
def process(self, image):
sharpen = cv2.bilateralFilter(image, self.filter_size, 150, 150);
return sharpen
我们还需要一个将原始图像复制过来的变换(稍后我们将解释其原因)
class OriginalProcessor:
def name(self):
return ""
def process(self, image):
return image
现在所有技巧都在一个算法中
现在我们有了所有要使用的变换。这是将自动处理所有图像并通过变换的算法
class Augmentor:
def __init__(self, processors):
self.processors = processors
def generate(self, source, dest):
files = FileUtils.get_files(source)
if not os.path.isdir(dest):
os.mkdir(dest)
for (i, fname) in enumerate(files):
img = cv2.imread(fname)
for (j, proc) in enumerate(self.processors):
p_img = proc.process(img)
f = os.path.basename(fname)
f = os.path.splitext(f)[0]
f = f + proc.name() + ".png"
dfname = os.path.join(dest, f)
cv2.imwrite(dfname, p_img)
generate
方法遍历源文件夹中的文件,对它们应用所有指定的变换,并将修改后的图像保存到目标目录,文件名为新名称(原始名称后附加处理器名称)。
我们可以使用以下代码将增强算法应用于我们的样本图像
folder = r"C:\PI_PEST\moose"
gen_folder = r"C:\PI_PEST\moose_gen"
processors = [OriginalProcessor(), FlipProcessor()]
gen = Augmentor(processors)
gen.generate(folder, gen_folder)
processors = [SmoothProcessor(5), SharpenProcessor(5)]
gen = Augmentor(processors)
gen.generate(gen_folder, gen_folder)
processors = [RotateProcessor(15, 1.2), RotateProcessor(-15, 1.2)]
gen = Augmentator(processors)
gen.generate(gen_folder, gen_folder)
请注意我们是如何分三个顺序步骤实现增强的。
首先,我们应用了翻转和“原始”处理器。现在我们知道为什么 OriginalProcessor
只是按原样复制原始图像:在此步骤之后,我们希望将原始图像和翻转图像的副本都放入 moose_gen 文件夹。
在第二步中,我们将平滑和锐化处理器应用于第一步生成的所有图像。
在最后一步中,我们将两个变换(顺时针和逆时针旋转 15 度)应用于前两步生成的所有图像。样本的最终图像如下所示
后续步骤
我们现在有多少样本?我们有 18 倍!
我们有 3600 个“麋鹿”类别的样本和 5112 个“背景”类别的样本。对于我们的目的来说,这个大小的数据集将提供可接受的麋鹿检测结果。
但是,如果您正在开发商业害虫探测器,您会想要一个大得多的数据集。在处理 AI 项目时,您会遇到的一个普遍主题是获取高质量数据是最困难的任务。
对于许多常见类型的问题,都有成熟、经过实战检验的 DNN 架构,但获取大量图像、清理它们并增强它们可能需要数天、数周甚至数月,具体取决于您正在解决的问题的大小。
在下一篇文章中,我们将讨论使用增强数据集训练我们的 DNN 分类器。