はじめに
facebookresearchからAugLyという新しいデータ拡張ライブラリが出てきたので少し試してみました。この記事は、試してみた結果の備忘録となっております。
AugLyは、画像・音声・テキスト・ビデオで100種類以上のデータ拡張に対応しているらしいです。
以下では、試してみたときの環境構築についてと、画像と音声に対する拡張処理の一部について記載しています。
※この記事で行った処理に関してはGitHub上で公開しております。(特に音声の拡張に関しては、実際にノートブックを実行して聞いてみると分かりやすいと思います。)
環境構築
今回は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実行の例を記載します。
単発
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)
ちなみに、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}]
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}]
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を張ってくれる拡張です。
引数に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}]
Component
aug = imaugs.Compose(
[
imaugs.VFlip(),
imaugs.Blur(),
imaugs.RandomNoise(),
imaugs.OverlayEmoji(),
imaugs.OverlayStripes(line_width=0.1, line_angle=60)
]
)
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実行の例を記載します。
単発
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}]
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}]
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}]
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}]
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}]
おわりに
今回はfacebookresearchが公開したAugLyを少しだけ試してみました。
これ1つで画像や音声などの簡単な拡張処理ができるのは結構便利だなぁと思いました。
処理速度とかは特に計測していないので、また測ってみたいと思います。