Frederick
Frederick

Reputation: 47

Optimizing Perlin Noise Matching for Binary Image Comparison: Slow Processing and Low SSIM Score

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

Answers (0)

Related Questions