Reputation: 47
I’m working on a project where I need to generate Perlin noise and match it with a binary (black & white) image. I want to find the Perlin noise pattern that best matches the input image in terms of similarity (using SSIM). However, I’m encountering performance issues and low similarity scores (never getting over 8% SSIM).
Here’s the code I’m working with: py
import numpy as np
from skimage.metrics import structural_similarity as ssim
from perlin_noise import PerlinNoise
import matplotlib.pyplot as plt
def binarize_image(image, threshold=0.5):
"""
Convert a grayscale image to binary (B&W) using a threshold.
Parameters:
- image: 2D numpy array
- threshold: pixel value above which is considered white (default: 0.5)
Returns:
- Binarized 2D numpy array
"""
return (image > threshold).astype(np.uint8)
def generate_perlin_noise(shape, scale, seed, octaves=1):
"""
Generate a 2D Perlin noise pattern.
"""
noise = PerlinNoise(seed=seed, octaves=octaves)
noise_map = np.zeros(shape)
for y in range(shape[0]):
for x in range(shape[1]):
noise_map[y, x] = noise([x / scale, y / scale])
return noise_map
def calculate_similarity(img1, img2):
"""
Calculate the Structural Similarity Index (SSIM) between two images.
"""
return ssim(img1, img2, data_range=1) # Binary images have a data range of 1
def find_best_match(image, shape, scales, seeds, octaves=1):
"""
Find the best matching Perlin noise pattern for the binary input image.
"""
best_match = None
best_score = -1 # SSIM ranges from -1 to 1
for scale in scales:
for seed in seeds:
noise_pattern = generate_perlin_noise(shape, scale, seed, octaves)
binary_noise = binarize_image(noise_pattern) # Binarize the noise
score = calculate_similarity(image, binary_noise)
if score > best_score:
best_score = score
best_match = (scale, seed)
return best_match, best_score
# Example usage
# Replace with your B&W binary image
image = np.random.rand(16, 16)
binary_image = binarize_image(image) # Convert to binary
shape = binary_image.shape
scales = np.linspace(10, 100, 10) # Adjust scale range
seeds = range(0, 1000) # Adjust seed range
best_match, best_score = find_best_match(binary_image, shape, scales, seeds)
print(f"Best match: Scale={best_match[0]}, Seed={best_match[1]}, Score={best_score}")
# Visualize the best match
best_noise_pattern = generate_perlin_noise(shape, best_match[0], best_match[1], octaves=1)
binary_best_noise_pattern = binarize_image(best_noise_pattern)
plt.imshow(binary_best_noise_pattern, cmap='gray')
plt.title("Best Matching Perlin Noise Pattern")
plt.colorbar()
plt.show()
later I want to insert a B&W .png image into it instead which will find a 1 to 1 match so I can do pattern continuation, which is its end goal purpose.
as always any help is appreciated :)
Upvotes: 0
Views: 27