在本文中,将介绍如何为面部口罩检测器准备数据集。将通过一系列步骤来收集图像、预处理图像,并增强最终的数据集。这些步骤对于任何图像数据集都是相似的。将通过一个较长的过程来覆盖数据稀缺的真实场景。从两个不同的来源获取图像,并展示如何标准化和增强它们以供未来的标记使用。
尽管有许多自动化工具可以使这个过程变得轻松,但将采用更困难的方式进行,以便学到更多。将使用一个包含149张佩戴口罩的人的图像的Roboflow数据集,所有图像都有黑色填充,并且“尺寸相同”,以及从Kaggle获得的另一组仅包含人脸(无口罩)的图像。这两个数据集代表了两个类别——戴口罩的面部和未戴口罩的面部——让逐步实现标准化和增强的数据集。
将使用Kaggle笔记本来运行本文中的代码,因为它们提供了易于访问的计算能力,并且预先配置了将需要的所有工具,所以不需要安装Python、Tensorflow或其他任何东西。但它们不是必需的;如果更喜欢,也可以在本地运行Jupyter Notebook来实现相同的结果。
在这种情况下,手动下载了数据集,将其压缩并上传到Kaggle笔记本。要启动Kaggle笔记本,请访问,登录,转到左侧面板中的Notebooks,然后点击“New notebook”。一旦它运行,上传zip文件并运行以下单元格。
Python
import os
#
用于探索目录
import matplotlib.pyplot as plt
#
用于绘制图像
import matplotlib.image as mpimg
import cv2
#
用于图像转换
from PIL import Image, ImageOps
#
用于图像处理
让探索图像的尺寸。将读取每张图像,获取其形状,并获取数据集中的唯一尺寸:
Python
#
图像尺寸探索
shapes = []
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
if filename.endswith('.jpg'):
shapes.append(cv2.imread(os.path.join(dirname, filename)).shape)
print('Unique shapes at imageset: ', set(shapes))
正如可能知道的,不能使用不同尺寸的图像来训练任何模型。让将它们标准化为单一尺寸(415x415):
Python
def make_square(image, minimun_size=256, fill=(0, 0, 0, 0)):
x, y = image.size
size = max(minimun_size, x, y)
new_image = Image.new('RGB', (size, size), fill)
new_image.paste(image, (int((size - x) / 2), int((size - y) / 2)))
return new_image
counter = 0
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
if filename.endswith('.jpg'):
counter += 1
new_image = Image.open(os.path.join(dirname, filename))
new_image = make_square(new_image)
new_image = new_image.resize((415, 415))
new_image.save("/kaggle/working/" + str(counter) + "-roboflow.jpg")
if counter == 150:
break
在Kaggle中保存文件并将其作为输出的方便目录是/kaggle/working/。在下载标准化的数据集之前,运行此单元格以压缩所有图像,这样将更容易找到最终的归档文件:
Python
!zip -r /kaggle/working/output.zip /kaggle/working/
!rm -rf /kaggle/working/*.jpg
现在可以在右侧的目录浏览器中找到output.zip文件。
这次的任务方法与之前为Roboflow数据集选择的方法略有不同。这次,数据集包含4000+张图像,所有图像的尺寸都完全不同。转到数据集链接并从那里启动Jupyter Notebook。将选择前150张图像。
Python
import os
#
用于探索目录
import matplotlib.pyplot as plt
#
用于绘制图像
import cv2
#
用于图像转换
from PIL import Image
#
用于图像处理
如果想探索数据集:
Python
#
有多少张图像?
counter = 0
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
if filename.endswith('.jpg'):
counter += 1
print('Images in directory: ', counter)
让探索一张图像:
Python
%matplotlib inline
plt.figure()
image = cv2.imread('/kaggle/input/human-faces/Humans/1 (719).jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
plt.show()
图像尺寸探索:
Python
shapes = []
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
if filename.endswith('.jpg'):
shapes.append(cv2.imread(os.path.join(dirname, filename)).shape)
print('Unique shapes at imageset: ', set(shapes))
这个单元格返回了大量不同的尺寸,因此标准化是必要的。让将所有图像调整为(415x415),黑色填充:
Python
def make_square(image, minimun_size=256, fill=(0, 0, 0, 0)):
x, y = image.size
size = max(minimun_size, x, y)
new_image = Image.new('RGBA', (size, size), fill)
new_image.paste(image, (int((size - x) / 2), int((size - y) / 2)))
return new_image
counter = 0
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
if filename.endswith('.jpg'):
counter += 1
test_image = Image.open(os.path.join(dirname, filename))
new_image = make_square(test_image)
new_image = new_image.convert("RGB")
new_image = new_image.resize((415, 415))
new_image.save("/kaggle/working/" + str(counter) + "-kaggle.jpg")
if counter == 150:
break
要下载数据集:
Python
!zip -r /kaggle/working/output.zip /kaggle/working/
!rm -rf /kaggle/working/*.jpg
现在可以在右侧面板中轻松找到它。
一旦标准化了两个数据集,是时候将数据合并并增强结果集了。数据增强为提供了一种方法,可以从相对较小的数据集中人为地生成更多的小型训练数据。增强通常是必要的,因为任何模型在训练期间都需要大量的数据才能取得良好的结果。
在计算机上解压缩两个文件,将所有图像放在同一个文件夹中,将它们压缩,启动一个新的Kaggle笔记本(在这里),然后上传结果文件。
接下来,让看看需要做什么来增强数据。可以使用自动化服务来减少一些工作,但决定自己做所有事情,以便学到更多。
Python
import numpy as np
from numpy import expand_dims
import os
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import cv2
from keras.preprocessing import image
from keras.preprocessing.image import ImageDataGenerator
from PIL import Image
直接进行增强。将使用Keras中广泛使用的ImageDataGenerator方法:
Python
def data_augmentation(filename):
"""
这个函数将执行数据增强:
对于每一张图像,将创建扩展/缩小,变暗/变亮,旋转的图像。每种修改类型5个。
总共,将为原始数据集中的每一个创建15个额外的图像。
"""
image_data = []
#
读取图像
image = cv2.imread(filename, 3)
#
将图像扩展到一个样本
samples = expand_dims(image, 0)
#
创建图像数据增强生成器
datagen1 = ImageDataGenerator(zoom_range=[0.5, 1.2])
datagen2 = ImageDataGenerator(brightness_range=[0.2, 1.0])
datagen3 = ImageDataGenerator(rotation_range=20)
#
准备迭代器
it1 = datagen1.flow(samples, batch_size=1)
it2 = datagen2.flow(samples, batch_size=1)
it3 = datagen3.flow(samples, batch_size=1)
#
image_data.append(image)
for i in range(5):
#
生成一批图像
batch1 = it1.next()
batch2 = it2.next()
batch3 = it3.next()
#
转换为无符号整数
image1 = batch1[0].astype('uint8')
image2 = batch2[0].astype('uint8')
image3 = batch3[0].astype('uint8')
#
添加到图像列表
image_data.append(image1)
image_data.append(image2)
image_data.append(image3)
return image_data
要实现它,让遍历/kaggle/input目录中的每张图像,并将所有结果保存在/kaggle/working中,以便将来下载:
Python
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
print(os.path.join(dirname, filename))
result = data_augmentation(os.path.join(dirname, filename))
for i in range(16):
cv2.imwrite('/kaggle/working/' + str(counter) + '.jpg', result[i])
再次,在下载之前,只需运行下一行,就可以在右侧面板中更容易地找到文件:
Python
!zip -r /kaggle/working/output.zip /kaggle/working/
!rm -rf /kaggle/working/*.jpg