最近,在研究项目中,开始了解图像增强技术的重要性。该项目的目标是训练一个能够重建原始图像的鲁棒生成模型。所解决的问题是异常检测,这是一个相当具有挑战性的问题,因为数据量很小,而且模型不足以单独完成所有工作。
常见的场景是使用可用于训练的正常图像训练网络模型,并在包含正常图像和异常图像的测试集上评估其性能。
最初的假设是,生成模型应该很好地捕捉正态分布,但同时,它应该无法重建异常样本。如何验证这一假设?我们可以看到重建误差,异常图像的重建误差应该较高,而正常样本的重建误差应该较低。
在这篇文章中,将列出最好的数据增强技术,以增加数据集中图像的大小和多样性。其主要目的是提高模型的性能和泛化能力。
我们将探索简单的变换,如旋转、裁剪和高斯模糊,以及更复杂的技术,如高斯噪声和随机块。

图像增强技术:

1、简单变换
  • 调整大小
  • 灰度
  • 规范化
  • 随机旋转
  • 中心裁剪
  • 随机裁剪
  • 高斯模糊
2、更先进的技术
  • 高斯噪声
  • 随机块
  • 中心区域

1、表面裂纹数据集简介

在本教程中,我们将使用表面裂纹检测数据集。你可以在此处或Kaggle上下载数据集:
https://data.mendeley.com/datasets/5y9wdsg2zt/2
从名称可以推断,它提供了有裂纹和无裂纹曲面的图像。因此,它可以作为异常检测任务的数据集,其中异常类由有裂纹的图像表示,而正常类由无裂纹的表面表示。
该数据集包含4000幅有缺陷和无缺陷表面的彩色图像。这两个类都有训练和测试集。此外,以227×227像素的分辨率获取每个数据集图像。

2、简单变换

本节包括torchvision中可用的不同转换模块。在深入研究之前,我们从训练数据集中导入模块和一个没有缺陷的图像。
from
 PIL 
import
 Image

from
 pathlib 
import
 Path

import
 matplotlib.pyplot 
as
 plt

import
 numpy 
as
 np

import
 sys

import
 torch

import
 numpy 
as
 np

import
 torchvision.transforms 
as
 T


plt.rcParams[
"savefig.bbox"
] = 
'tight'
orig_img = Image.open(Path(
'../input/surface-crack-detection/Negative/00026.jpg'
))

torch.manual_seed(
0
)

data_path = 
'../input/surface-crack-detection/'
diz_class = {
'Positive'
:
'Crack'
,
'Negative'
:
'No crack'
}

让我们显示图像的尺寸:
np.asarray(orig_img).shape  
#(227, 227, 3)
这意味着我们有一个227x227的图像,有3个通道。

调整大小

由于图像具有很高的高度和宽度,因此在将其传递给神经网络之前,需要降低维数。例如,我们可以将227x227图像调整为32x32和128x128图像。
resized_imgs = [T.Resize(size=size)(orig_img) 
for
 size 
in
 [
32
,
128
]]

plot(resized_imgs,col_title=[
"32x32"
,
"128x128"
])

值得注意的是,当我们获得一幅32x32的图像时,我们会失去分辨率,而128x128的尺寸似乎可以保持样品的高分辨率。

灰度等级

RGB图像可能很难管理。因此,将图像转换为灰度可能很有用:
gray_img = T.Grayscale()(orig_img)

plot([gray_img], cmap=
'gray'
, col_title=[
"Gray"
])

规范化

规范化是一种有效的方法,可以加快基于神经网络结构的模型的计算速度,加快学习速度。规范化图像有两个步骤:
  • 我们从每个输入通道中减去通道平均值
  • 稍后,我们将其除以通道标准差。
我们可以显示原始图像及其规范化版本:
normalized_img = T.Normalize(mean=(
0.5
0.5
0.5
), std=(
0.5
0.5
0.5
))(T.ToTensor()(orig_img)) 

normalized_img = [T.ToPILImage()(normalized_img)]

plot(normalized_img, col_title=[
"Standard normalize"
])

随机旋转

随机旋转方法以随机角度旋转图像。
rotated_imgs = [T.RandomRotation(degrees=d)(orig_img) 
for
 d 
in
 range(
50
,
151
,
50
)]

plot(rotated_imgs, col_title=[
"Rotation 50"
,
"Rotation 100"
,
"Rotation 150"
])

中心裁剪

我们使用T.CenterCrop方法裁剪图像的中心部分,其中需要指定裁剪大小。
center_crops = [T.CenterCrop(size=size)(orig_img) 
for
 size 
in
 (
128
,
64
32
)]

plot(center_crops,col_title=[
'128x128'
,
'64x64'
,
'32x32'
])

当图像的边界中有一个大背景,而分类任务根本不需要这个背景时,这种转换非常有用。

随机裁剪

我们没有裁剪图像的中心部分,而是通过T.RandomCrop方法随机裁剪图像的一部分,该方法将裁剪的输出大小作为参数。
random_crops = [T.RandomCrop(size=size)(orig_img) 
for
 size 
in
 (
832
,
704
256
)]

plot(random_crops,col_title=[
'832x832'
,
'704x704'
,
'256x256'
])

高斯模糊

我们使用高斯核对图像进行高斯模糊变换。这种方法有助于降低图像的清晰度和清晰度,然后将生成的图像输入到神经网络中,神经网络在样本的学习模式方面变得更加稳健。
blurred_imgs = [T.GaussianBlur(kernel_size=(
51
91
), sigma=sigma)(orig_img) 
for
 sigma 
in
 (
3
,
7
)]

plot(blurred_imgs)

3、更先进的技术

前面展示了PyTorch提供的简单转换示例。现在,我们将重点讨论从零开始实现的更复杂的技术。

高斯噪声

高斯噪声是一种常用的向整个数据集添加噪声的方法,它迫使模型学习数据中包含的最重要信息。
它包括注入高斯噪声矩阵,高斯噪声矩阵是从高斯分布中提取的随机值矩阵。稍后,我们将在0和1之间剪裁样本。噪声因子越高,图像的噪声越大。
defadd_noise(inputs,noise_factor=0.3):
     noisy = inputs+torch.randn_like(inputs) * noise_factor

     noisy = torch.clip(noisy,
0.
,
1.
)

return
 noisy


noise_imgs = [add_noise(T.ToTensor()(orig_img),noise_factor) 
for
 noise_factor 
in
 (
0.3
,
0.6
,
0.9
)]

noise_imgs = [T.ToPILImage()(noise_img) 
for
 noise_img 
in
 noise_imgs]

plot(noise_imgs, col_title=[
"noise_factor=0.3"
,
"noise_factor=0.6"
,
"noise_factor=0.9"
])

随机块

正方形补丁随机应用在图像中。这些补丁的数量越多,神经网络解决问题的难度就越大。
defadd_random_boxes(img,n_k,size=32):
    h,w = size,size

    img = np.asarray(img)

    img_size = img.shape[
1
]

    boxes = []

for
 k 
in
 range(n_k):

        y,x = np.random.randint(
0
,img_size-w,(
2
,))

        img[y:y+h,x:x+w] = 
0
        boxes.append((x,y,h,w))

    img = Image.fromarray(img.astype(
'uint8'
), 
'RGB'
)

return
 img


blocks_imgs = [add_random_boxes(orig_img,n_k=i) 
for
 i 
in
 (
10
,
20
)]

plot(blocks_imgs,col_title=[
"10 black boxes"
,
"20 black boxes"
])

中心区域

这是一种非常简单的方法,可以使模型更一般化。它包括在图像的中心区域添加一个补丁块。
defadd_central_region(img,size=32):
    h,w = size,size

    img = np.asarray(img)

    img_size = img.shape[
1

    img[int(img_size/
2
-h):int(img_size/
2
+h),int(img_size/
2
-w):int(img_size/
2
+w)] = 
0
    img = Image.fromarray(img.astype(
'uint8'
), 
'RGB'
)

return
 img


central_imgs = [add_central_region(orig_img,size=s) 
for
 s 
in
 (
32
,
64
)]

plot(central_imgs,col_title=[
"32"
,
"64"
])

最后的想法:

希望你发现本教程很有用。目的是对基于神经网络的图像增强方法进行概述,以解决模型的泛化问题。代码位于GitHub上:
https://github.com/eugeniaring/Medium-Articles/blob/main/Anomaly%20Detection/image-augmentation-on-crack-images.ipynb
感谢阅读!
☆ END ☆
如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 woshicver」,每日朋友圈更新一篇高质量博文
扫描二维码添加小编↓
继续阅读
阅读原文