wufan's picture
Upload 119 files
8a8d449 verified
raw
history blame
8.35 kB
import math
from io import BytesIO
import cv2
import numpy as np
from PIL import Image, ImageOps, ImageDraw
from pkg_resources import resource_filename
from wand.image import Image as WandImage
import albumentations as alb
from .ops import plasma_fractal
class Fog(alb.ImageOnlyTransform):
def __init__(self, mag=-1, always_apply=False, p=1.):
super().__init__(always_apply=always_apply, p=p)
self.rng = np.random.default_rng()
self.mag = mag
def apply(self, img, **params):
img = Image.fromarray(img.astype(np.uint8))
w, h = img.size
c = [(1.5, 2), (2., 2), (2.5, 1.7)]
if self.mag < 0 or self.mag >= len(c):
index = self.rng.integers(0, len(c))
else:
index = self.mag
c = c[index]
n_channels = len(img.getbands())
isgray = n_channels == 1
img = np.asarray(img) / 255.
max_val = img.max()
# Make sure fog image is at least twice the size of the input image
max_size = 2 ** math.ceil(math.log2(max(w, h)) + 1)
fog = c[0] * plasma_fractal(mapsize=max_size, wibbledecay=c[1], rng=self.rng)[:h, :w][..., np.newaxis]
# x += c[0] * plasma_fractal(wibbledecay=c[1])[:224, :224][..., np.newaxis]
# return np.clip(x * max_val / (max_val + c[0]), 0, 1) * 255
if isgray:
fog = np.squeeze(fog)
else:
fog = np.repeat(fog, 3, axis=2)
img += fog
img = np.clip(img * max_val / (max_val + c[0]), 0, 1) * 255
return img.astype(np.uint8)
class Frost(alb.ImageOnlyTransform):
def __init__(self, mag=-1, always_apply=False, p=1.):
super().__init__(always_apply=always_apply, p=p)
self.rng = np.random.default_rng()
self.mag = mag
def apply(self, img, **params):
img = Image.fromarray(img.astype(np.uint8))
w, h = img.size
c = [(0.78, 0.22), (0.64, 0.36), (0.5, 0.5)]
if self.mag < 0 or self.mag >= len(c):
index = self.rng.integers(0, len(c))
else:
index = self.mag
c = c[index]
filename = [resource_filename(__name__, 'frost/frost1.png'),
resource_filename(__name__, 'frost/frost2.png'),
resource_filename(__name__, 'frost/frost3.png'),
resource_filename(__name__, 'frost/frost4.jpg'),
resource_filename(__name__, 'frost/frost5.jpg'),
resource_filename(__name__, 'frost/frost6.jpg')]
index = self.rng.integers(0, len(filename))
filename = filename[index]
# Some images have transparency. Remove alpha channel.
frost = Image.open(filename).convert('RGB')
# Resize the frost image to match the input image's dimensions
f_w, f_h = frost.size
if w / h > f_w / f_h:
f_h = round(f_h * w / f_w)
f_w = w
else:
f_w = round(f_w * h / f_h)
f_h = h
frost = np.asarray(frost.resize((f_w, f_h)))
# randomly crop
y_start, x_start = self.rng.integers(0, f_h - h + 1), self.rng.integers(0, f_w - w + 1)
frost = frost[y_start:y_start + h, x_start:x_start + w]
n_channels = len(img.getbands())
isgray = n_channels == 1
img = np.asarray(img)
if isgray:
img = np.expand_dims(img, axis=2)
img = np.repeat(img, 3, axis=2)
img = np.clip(np.round(c[0] * img + c[1] * frost), 0, 255)
img = img.astype(np.uint8)
if isgray:
img = np.squeeze(img)
return img
class Snow(alb.ImageOnlyTransform):
def __init__(self, mag=-1, always_apply=False, p=1.):
super().__init__(always_apply=always_apply, p=p)
self.rng = np.random.default_rng()
self.mag = mag
def apply(self, img, **params):
img = Image.fromarray(img.astype(np.uint8))
w, h = img.size
c = [(0.1, 0.3, 3, 0.5, 10, 4, 0.8),
(0.2, 0.3, 2, 0.5, 12, 4, 0.7),
(0.55, 0.3, 4, 0.9, 12, 8, 0.7)]
if self.mag < 0 or self.mag >= len(c):
index = self.rng.integers(0, len(c))
else:
index = self.mag
c = c[index]
n_channels = len(img.getbands())
isgray = n_channels == 1
img = np.asarray(img, dtype=np.float32) / 255.
if isgray:
img = np.expand_dims(img, axis=2)
img = np.repeat(img, 3, axis=2)
snow_layer = self.rng.normal(size=img.shape[:2], loc=c[0], scale=c[1]) # [:2] for monochrome
# snow_layer = clipped_zoom(snow_layer[..., np.newaxis], c[2])
snow_layer[snow_layer < c[3]] = 0
snow_layer = Image.fromarray((np.clip(snow_layer.squeeze(), 0, 1) * 255).astype(np.uint8), mode='L')
output = BytesIO()
snow_layer.save(output, format='PNG')
snow_layer = WandImage(blob=output.getvalue())
snow_layer.motion_blur(radius=c[4], sigma=c[5], angle=self.rng.uniform(-135, -45))
snow_layer = cv2.imdecode(np.frombuffer(snow_layer.make_blob(), np.uint8),
cv2.IMREAD_UNCHANGED) / 255.
# snow_layer = cv2.cvtColor(snow_layer, cv2.COLOR_BGR2RGB)
snow_layer = snow_layer[..., np.newaxis]
img = c[6] * img
gray_img = (1 - c[6]) * np.maximum(img, cv2.cvtColor(img, cv2.COLOR_RGB2GRAY).reshape(h, w, 1) * 1.5 + 0.5)
img += gray_img
img = np.clip(img + snow_layer + np.rot90(snow_layer, k=2), 0, 1) * 255
img = img.astype(np.uint8)
if isgray:
img = np.squeeze(img)
return img
class Rain(alb.ImageOnlyTransform):
def __init__(self, mag=-1, always_apply=False, p=1.):
super().__init__(always_apply=always_apply, p=p)
self.rng = np.random.default_rng()
self.mag = mag
def apply(self, img, **params):
img = Image.fromarray(img.astype(np.uint8))
img = img.copy()
w, h = img.size
n_channels = len(img.getbands())
isgray = n_channels == 1
line_width = self.rng.integers(1, 2)
c = [50, 70, 90]
if self.mag < 0 or self.mag >= len(c):
index = 0
else:
index = self.mag
c = c[index]
n_rains = self.rng.integers(c, c + 20)
slant = self.rng.integers(-60, 60)
fillcolor = 200 if isgray else (200, 200, 200)
draw = ImageDraw.Draw(img)
max_length = min(w, h, 10)
for i in range(1, n_rains):
length = self.rng.integers(5, max_length)
x1 = self.rng.integers(0, w - length)
y1 = self.rng.integers(0, h - length)
x2 = x1 + length * math.sin(slant * math.pi / 180.)
y2 = y1 + length * math.cos(slant * math.pi / 180.)
x2 = int(x2)
y2 = int(y2)
draw.line([(x1, y1), (x2, y2)], width=line_width, fill=fillcolor)
img = np.asarray(img).astype(np.uint8)
return img
class Shadow(alb.ImageOnlyTransform):
def __init__(self, mag=-1, always_apply=False, p=1.):
super().__init__(always_apply=always_apply, p=p)
self.rng = np.random.default_rng()
self.mag = mag
def apply(self, img, **params):
img = Image.fromarray(img.astype(np.uint8))
# img = img.copy()
w, h = img.size
n_channels = len(img.getbands())
isgray = n_channels == 1
c = [64, 96, 128]
if self.mag < 0 or self.mag >= len(c):
index = 0
else:
index = self.mag
c = c[index]
img = img.convert('RGBA')
overlay = Image.new('RGBA', img.size, (255, 255, 255, 0))
draw = ImageDraw.Draw(overlay)
transparency = self.rng.integers(c, c + 32)
x1 = self.rng.integers(0, w // 2)
y1 = 0
x2 = self.rng.integers(w // 2, w)
y2 = 0
x3 = self.rng.integers(w // 2, w)
y3 = h - 1
x4 = self.rng.integers(0, w // 2)
y4 = h - 1
draw.polygon([(x1, y1), (x2, y2), (x3, y3), (x4, y4)], fill=(0, 0, 0, transparency))
img = Image.alpha_composite(img, overlay)
img = img.convert("RGB")
if isgray:
img = ImageOps.grayscale(img)
img = np.asarray(img).astype(np.uint8)
return img