Source code for image_segmentation.datasets.segmentation.sintetic_dataset.texture_generation

"""
Texture generation using Perlin noise

Reference: https://github.com/nikagra/python-noise
"""


import random, math

import numpy as np 
from PIL import Image



[docs]class NoiseUtils: def __init__(self, imageSize): self.imageSize = imageSize self.gradientNumber = 256 self.grid = [[]] self.gradients = [] self.permutations = [] self.img = {} self.__generateGradientVectors() self.__normalizeGradientVectors() self.__generatePermutationsTable() def __generateGradientVectors(self): for i in range(self.gradientNumber): while True: x, y = random.uniform(-1, 1), random.uniform(-1, 1) if x * x + y * y < 1: self.gradients.append([x, y]) break def __normalizeGradientVectors(self): for i in range(self.gradientNumber): x, y = self.gradients[i][0], self.gradients[i][1] length = math.sqrt(x * x + y * y) self.gradients[i] = [x / length, y / length] # The modern version of the Fisher-Yates shuffle def __generatePermutationsTable(self): self.permutations = [i for i in range(self.gradientNumber)] for i in reversed(range(self.gradientNumber)): j = random.randint(0, i) self.permutations[i], self.permutations[j] = \ self.permutations[j], self.permutations[i]
[docs] def getGradientIndex(self, x, y): return self.permutations[(x + self.permutations[y % self.gradientNumber]) % self.gradientNumber]
[docs] def perlinNoise(self, x, y): qx0 = int(math.floor(x)) qx1 = qx0 + 1 qy0 = int(math.floor(y)) qy1 = qy0 + 1 q00 = self.getGradientIndex(qx0, qy0) q01 = self.getGradientIndex(qx1, qy0) q10 = self.getGradientIndex(qx0, qy1) q11 = self.getGradientIndex(qx1, qy1) tx0 = x - math.floor(x) tx1 = tx0 - 1 ty0 = y - math.floor(y) ty1 = ty0 - 1 v00 = self.gradients[q00][0] * tx0 + self.gradients[q00][1] * ty0 v01 = self.gradients[q01][0] * tx1 + self.gradients[q01][1] * ty0 v10 = self.gradients[q10][0] * tx0 + self.gradients[q10][1] * ty1 v11 = self.gradients[q11][0] * tx1 + self.gradients[q11][1] * ty1 wx = tx0 * tx0 * (3 - 2 * tx0) v0 = v00 + wx * (v01 - v00) v1 = v10 + wx * (v11 - v10) wy = ty0 * ty0 * (3 - 2 * ty0) return (v0 + wy * (v1 - v0)) * 0.5 + 1
[docs] def makeTexture(self, texture = None): if texture == None: texture = self.cloud i_index, j_index = np.meshgrid(np.arange(self.imageSize),np.arange(self.imageSize),indexing='ij') v_myfunc = np.vectorize(texture) noise = v_myfunc(i_index, j_index) max = noise.max() min = noise.min() self.img = np.uint8((noise - min) / (max - min) * 255 )
[docs] def fractalBrownianMotion(self, x, y, func): octaves = 12 amplitude = 1.0 frequency = 1.0 / self.imageSize persistence = 0.5 value = 0.0 for k in range(octaves): value += func(x * frequency, y * frequency) * amplitude frequency *= 2 amplitude *= persistence return value
[docs] def cloud(self, x, y, func = None): if func is None: func = self.perlinNoise return self.fractalBrownianMotion(8 * x, 8 * y, func)
[docs] def wood(self, x, y, noise = None): if noise is None: noise = self.perlinNoise frequency = 1.0 / self.imageSize n = noise(4 * x * frequency, 4 * y * frequency) * 10 return n - int(n)
[docs] def marble(self, x,y, noise = None): if noise is None: noise = self.perlinNoise frequency = 1.0 / self.imageSize n = self.fractalBrownianMotion(8 * x, 8 * y, self.perlinNoise) return (math.sin(16 * x * frequency + 4 * (n - 0.5)) + 1) * 0.5