Created
May 10, 2025 02:17
-
-
Save badjano/f402048ad6ea7fd2bc650530554497af to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import numpy as np | |
from PIL import Image | |
import argparse | |
import os | |
def create_autostereogram(pattern_path, depth_map_path, output_path, repeat_width=128): | |
""" | |
Generate an autostereogram from a pattern image and a depth map. | |
Args: | |
pattern_path (str): Path to the pattern image | |
depth_map_path (str): Path to the depth map image | |
output_path (str): Path to save the output autostereogram | |
repeat_width (int): Width of the repeating pattern in pixels | |
""" | |
# Load pattern and depth map | |
try: | |
pattern = Image.open(pattern_path).convert('RGB') | |
depth_map = Image.open(depth_map_path).convert('L') # Convert depth map to grayscale | |
except Exception as e: | |
print(f"Error loading images: {e}") | |
return False | |
# resize pattern to a fixed size | |
pattern = pattern.resize((repeat_width, repeat_width)) | |
# Resize depth map to match the pattern's height while maintaining aspect ratio | |
pattern_width, pattern_height = pattern.size | |
depth_width, depth_height = depth_map.size | |
# Convert images to numpy arrays for faster processing | |
pattern_array = np.array(pattern) | |
depth_array = np.array(depth_map) | |
output_array = np.zeros((depth_height, depth_width, 3), dtype=np.uint8) | |
# Calculate maximum pixel shift based on depth factor (as a fraction of pattern width) | |
depth_factor = 0.2 # Adjust this value to control depth effect intensity | |
max_shift = int(pattern_width * depth_factor) | |
# get array from pattern | |
strip = np.zeros((pattern_height, pattern_width, 3), dtype=np.uint8) | |
for y in range(pattern_height): | |
for x in range(pattern_width): | |
# Get the color from the pattern | |
strip[y, x] = pattern_array[y % pattern_height, x % pattern_width] | |
output_height = depth_height | |
output_width = depth_width | |
# Generate autostereogram | |
for y in range(output_height): | |
# For each row of the output image | |
for x in range(output_width): | |
# Skip the first pattern width of pixels (reference strip) | |
if x < pattern_width: | |
output_array[y, x] = strip[y % repeat_width, x % repeat_width] | |
else: | |
# Calculate shift based on depth | |
if x < depth_array.shape[1]: | |
# Normalize depth value (0-255) to (0-max_shift) | |
shift = int((depth_array[y, x] / 255.0) * max_shift) | |
# Look up the color from the left, shifted by depth | |
sample_x = x - pattern_width + shift | |
# Ensure sample_x is within bounds | |
if sample_x < 0: | |
sample_x = 0 | |
elif sample_x >= output_width: | |
sample_x = output_width - 1 | |
output_array[y, x] = output_array[y, sample_x] | |
else: | |
# For areas beyond the depth map, just repeat the pattern | |
output_array[y, x] = strip[y, x % pattern_width] | |
# Convert back to PIL image and save | |
output = Image.fromarray(output_array) | |
output.save(output_path) | |
print(f"Autostereogram saved to {output_path}") | |
return True | |
def main(): | |
if len(sys.argv) < 3: | |
create_autostereogram("pattern.png", "depth.png", "autostereogram.png", 256) | |
return | |
parser = argparse.ArgumentParser(description='Generate an autostereogram from a pattern and depth map.') | |
parser.add_argument('pattern', help='Path to the pattern image') | |
parser.add_argument('depth_map', help='Path to the depth map image') | |
parser.add_argument('--output', '-o', default='autostereogram.png', help='Output image path') | |
parser.add_argument('--depth_factor', '-d', type=float, default=0.2, | |
help='Depth effect intensity (0.0-1.0)') | |
parser.add_argument('--repeat_width', '-r', type=int, default=128, | |
help='Number of times to repeat the pattern horizontally') | |
args = parser.parse_args() | |
if not os.path.exists(args.pattern): | |
print(f"Error: Pattern file not found: {args.pattern}") | |
return | |
if not os.path.exists(args.depth_map): | |
print(f"Error: Depth map file not found: {args.depth_map}") | |
return | |
create_autostereogram(args.pattern, args.depth_map, args.output, | |
args.depth_factor, args.repeat_width) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Autostereogram Generator
This Python script builds a single-image random dot autostereogram (SIRDS) from:
It tiles the pattern across the width of the depth map, then shifts pixels according to depth values to produce the familiar “Magic Eye” effect.
Features
Dependencies
Install with:
Usage
Example
Generate stereogram with default parameters
Custom output