AugLyを少し試してみた

# はじめに
facebookresearchから[AugLy](https://github.com/facebookresearch/AugLy)という新しいデータ拡張ライブラリが出てきたので少し試してみました。この記事は、試してみた結果の備忘録となっております。

AugLyは、画像・音声・テキスト・ビデオで100種類以上のデータ拡張に対応しているらしいです。


以下では、試してみたときの環境構築についてと、画像と音声に対する拡張処理の一部について記載しています。

※この記事で行った処理に関しては[GitHub上で公開](https://github.com/T-Sumida/my_AugLy_example)しております。（特に音声の拡張に関しては、実際にノートブックを実行して聞いてみると分かりやすいと思います。）

# 環境構築
今回はWSL2上にpipenvを使って環境構築をしました。

```
$pipenv install augly python-magic jupyterlab
```

# 画像の拡張
2021/06/19現在、以下の画像拡張が実装されているようです。

```
ApplyLambda,
Blur,
Brightness,
ChangeAspectRatio,
ColorJitter,
Contrast,
ConvertColor,
Crop,
EncodingQuality,
Grayscale,
HFlip,
MaskedComposite,
MemeFormat,
Opacity,
OverlayEmoji,
OverlayImage,
OverlayOntoScreenshot,
OverlayStripes,
OverlayText,
Pad,
PadSquare,
PerspectiveTransform,
Pixelization,
RandomAspectRatio,
RandomBlur,
RandomBrightness,
RandomEmojiOverlay,
RandomNoise,
RandomPixelization,
RandomRotation,
Resize,
Rotate,
Saturation,
Scale,
Sharpen,
ShufflePixels,
VFlip,
```

今回は自分で撮った画像を使って試してみます。

以下では拡張単発実行と、Component実行の例を記載します。

![original.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/60d5aa94-281d-f086-a09b-62e06a17cb25.jpeg)


## 単発
### Flip

```
import augly.image as imaugs
import augly.utils as utils
from IPython.display import display

metadata = []
input_img = imaugs.vflip(input_img_path, output_path="./output/vflip.jpg",metadata=metadata)
```

![vflip.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/18c6fb44-461a-14da-b5fe-72146174252e.jpeg)


ちなみに、metadataには拡張時の情報が格納されていて確認することができます。

```
print(metadata)
[{'name': 'vflip', 'src_width': 739, 'src_height': 554, 'dst_width': 739, 'dst_height': 554, 'output_path': './output/vflip.jpg', 'intensity': 100.0}]
```

### Blur
```
metadata = []
input_img = imaugs.blur(input_img_path, output_path="./output/blur.jpg",metadata=metadata)
print(metadata)

[{'name': 'blur', 'src_width': 739, 'src_height': 554, 'dst_width': 739, 'dst_height': 554, 'output_path': './output/blur.jpg', 'radius': 2.0, 'intensity': 2.0}]
```

![blur.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/d2ea7b1c-69c0-8cc0-ea96-3203d66e451c.jpeg)


### Random Noise
```
metadata = []
input_img = imaugs.random_noise(input_img_path, output_path="./output/random_noise.jpg",
metadata=metadata)
print(metadata)

[{'name': 'random_noise', 'src_width': 739, 'src_height': 554, 'dst_width': 739, 'dst_height': 554, 'output_path': './output/random_noise.jpg', 'mean': 0.0, 'var': 0.01, 'seed': 42, 'intensity': 0.01}]
```

![random_noise.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/30cbba78-f2d9-dbcd-dbf6-7e37e21e250f.jpeg)



### Emoji
```
metadata = []
input_img = imaugs.overlay_emoji(input_img_path, output_path="./output/emoji.jpg",metadata=metadata)
print(metadata)

[{'name': 'overlay_emoji', 'src_width': 739, 'src_height': 554, 'dst_width': 739, 'dst_height': 554, 'output_path': './output/emoji.jpg', 'emoji_path': '/home/sumita/augly_example/.venv/lib/python3.8/site-packages/augly/assets/twemojis/smileys/smiling_face_with_heart_eyes.png', 'opacity': 1.0, 'emoji_size': 0.15, 'x_pos': 0.4, 'y_pos': 0.8, 'intensity': 2.25}]
```

![emoji.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/eb9f2785-f961-81cf-1d92-c76ee4ed2343.jpeg)



画像の上にEmojiを張ってくれる拡張です。
引数にemoji_pathで指定できるので、自分の好きなEmojiを貼れたりするっぽいです。


### Stripes
```
metadata = []
input_img = imaugs.overlay_stripes(input_img_path, output_path="./output/stripes.jpg", line_width=0.1, line_angle=60,
metadata=metadata)
print(metadata)

[{'name': 'overlay_stripes', 'src_width': 739, 'src_height': 554, 'dst_width': 739, 'dst_height': 554, 'output_path': './output/stripes.jpg', 'line_width': 0.1, 'line_color': [255, 255, 255], 'line_angle': 60, 'line_density': 0.5, 'line_type': 'solid', 'line_opacity': 1.0, 'intensity': 1.0000195406004824}]
```

![stripes.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/cbe6df37-db5b-993d-54e3-377cf94b4183.jpeg)


## Component
```
aug = imaugs.Compose(
    [
        imaugs.VFlip(),
        imaugs.Blur(),
        imaugs.RandomNoise(),
        imaugs.OverlayEmoji(),
        imaugs.OverlayStripes(line_width=0.1, line_angle=60)
    ]
)
```

![mixed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/f43c9b3d-2f4e-c734-10ce-1e2f1ccc5cc4.png)


pytorchのComponentみたいにOneOfとかも使えたりするみたいです。


# 音声の拡張

2021/06/19現在、以下の音声拡張が実装されているようです。

```
AddBackgroundNoise,
ApplyLambda,
ChangeVolume,
Clicks,
Clip,
Harmonic,
HighPassFilter,
InsertInBackground,
InvertChannels,
LowPassFilter,
Normalize,
PeakingEqualizer,
Percussive,
PitchShift,
Reverb,
Speed,
Tempo,
TimeStretch,
ToMono,
```

今回は自分で録音した音声を使って試してみます。

以下では拡張単発実行と、Component実行の例を記載します。

![original.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/aca2df6c-e850-5532-755f-ffd22020a55a.png)

## 単発
### Add Background Noise
```
metadata = []
aug_audio, sr = audaugs.add_background_noise(audio_path, sample_rate=SR, metadata=metadata)
print(metadata)
ipd.Audio(aug_audio, rate=sr)


[{'name': 'add_background_noise', 'src_duration': 3.7738548752834467, 'dst_duration': 3.7738548752834467, 'src_num_channels': 1, 'dst_num_channels': 1, 'src_sample_rate': 44100, 'dst_sample_rate': 44100, 'src_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'dst_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'background_audio': None, 'snr_level_db': 10.0, 'output_path': None, 'background_duration': 3.7738548752834467, 'intensity': 90.9090909090909}]
```

![bgnoise.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/27f5f1af-708f-0319-a0b3-b62e55cde402.png)



### Low-Pass Filter
```
metadata = []
aug_audio, sr = audaugs.low_pass_filter(audio_path, sample_rate=SR, cutoff_hz=5000, metadata=metadata)
print(metadata)
ipd.Audio(aug_audio, rate=sr)

[{'name': 'low_pass_filter', 'src_duration': 3.7738548752834467, 'dst_duration': 3.7738548752834467, 'src_num_channels': 1, 'dst_num_channels': 1, 'src_sample_rate': 44100, 'dst_sample_rate': 44100, 'src_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'dst_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'alpha': 0.4160172294378693, 'cutoff_hz': 5000, 'output_path': None, 'intensity': 75.0}]
```

![lowpass.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/bde74324-164a-611a-ca4d-657fe653d893.png)



### Extracts the Percussive
```
metadata = []
aug_audio, sr = audaugs.percussive(audio_path, sample_rate=SR, metadata=metadata)
print(metadata)
ipd.Audio(aug_audio, rate=sr)

[{'name': 'percussive', 'src_duration': 3.7738548752834467, 'dst_duration': 3.7738548752834467, 'src_num_channels': 1, 'dst_num_channels': 1, 'src_sample_rate': 44100, 'dst_sample_rate': 44100, 'src_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'dst_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'output_path': None, 'kernel_size': 31, 'margin': 1.0, 'power': 2.0, 'intensity': 100.0}]
```

![percussive.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/f6ee6a02-2f19-333c-6066-8a2e9f5b223b.png)



### Pitch Shift
```
metadata = []
aug_audio, sr = audaugs.pitch_shift(audio_path, sample_rate=SR, n_steps=10, metadata=metadata)
print(metadata)
ipd.Audio(aug_audio, rate=sr)

[{'name': 'pitch_shift', 'src_duration': 3.7738548752834467, 'dst_duration': 3.7738548752834467, 'src_num_channels': 1, 'dst_num_channels': 1, 'src_sample_rate': 44100, 'dst_sample_rate': 44100, 'src_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'dst_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'output_path': None, 'n_steps': 10, 'intensity': 11.904761904761903}]
```

![pitchshift.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/cc5f827b-bee4-d6a6-9adb-536e6fc94c43.png)



## Components

```
TRANSFORMS = audaugs.Compose([
    audaugs.AddBackgroundNoise(),
    audaugs.ChangeVolume(volume_db=10.0, p=0.5),
    audaugs.OneOf(
        [audaugs.LowPassFilter(cutoff_hz=3000), audaugs.PitchShift(n_steps=10)]
    ),
])

metadata = []

# aug_audio is a NumPy array with your augmentations applied!
audio_array, _ = librosa.load(audio_path, sr=SR)
aug_audio, _ = TRANSFORMS(audio_array, SR, metadata=metadata)
print(metadata)
ipd.Audio(aug_audio, rate=SR)

[{'name': 'add_background_noise', 'src_duration': 3.7738548752834467, 'dst_duration': 3.7738548752834467, 'src_num_channels': 1, 'dst_num_channels': 1, 'src_sample_rate': 44100, 'dst_sample_rate': 44100, 'src_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'dst_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'background_audio': None, 'snr_level_db': 10.0, 'output_path': None, 'background_duration': 3.7738548752834467, 'intensity': 90.9090909090909}, {'name': 'low_pass_filter', 'src_duration': 3.7738548752834467, 'dst_duration': 3.7738548752834467, 'src_num_channels': 1, 'dst_num_channels': 1, 'src_sample_rate': 44100, 'dst_sample_rate': 44100, 'src_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'dst_segments': [{'start': 0.0, 'end': 3.7738548752834467}], 'alpha': 0.2994390610957307, 'cutoff_hz': 3000, 'output_path': None, 'intensity': 85.0}]
```


![components.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130155/f8e8fc2d-e75f-13d0-c36e-d28a29c08118.png)



# おわりに
今回はfacebookresearchが公開したAugLyを少しだけ試してみました。

これ1つで画像や音声などの簡単な拡張処理ができるのは結構便利だなぁと思いました。

処理速度とかは特に計測していないので、また測ってみたいと思います。