Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from PIL import Image | |
| import numpy as np | |
| matrices = { | |
| 'true': [ [ 0.299, 0.587, 0.114, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0.299, 0.587, 0.114 ] ], | |
| 'mono': [ [ 0.299, 0.587, 0.114, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0.299, 0.587, 0.114, 0.299, 0.587, 0.114 ] ], | |
| 'color': [ [ 1, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0, 0, 0, 1 ] ], | |
| 'halfcolor': [ [ 0.299, 0.587, 0.114, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0, 0, 0, 1 ] ], | |
| 'optimized': [ [ 0, 0.7, 0.3, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0, 0, 0, 1 ] ], | |
| } | |
| def make_anaglyph(left_img, right_img, color_method): | |
| """Generate an anaglyph from left and right images using the specified color method""" | |
| if left_img is None or right_img is None: | |
| return None | |
| # Convert from numpy array (from Gradio) to PIL Image | |
| left = Image.fromarray(left_img) | |
| right = Image.fromarray(right_img) | |
| # Check if both images have the same dimensions | |
| if left.size != right.size: | |
| # Resize right image to match left image dimensions | |
| right = right.resize(left.size, Image.LANCZOS) | |
| # Create a copy of the left image to modify | |
| #result = left.copy() | |
| # Get the pixel maps | |
| width, height = left.size | |
| leftMap = left.load() | |
| rightMap = right.load() | |
| #resultMap = result.load() | |
| # Use the selected color matrix | |
| m = matrices[color_method] | |
| # Apply the anaglyph transformation | |
| for y in range(0, height): | |
| for x in range(0, width): | |
| r1, g1, b1 = leftMap[x, y] | |
| r2, g2, b2 = rightMap[x, y] | |
| leftMap[x, y] = ( | |
| int(r1*m[0][0] + g1*m[0][1] + b1*m[0][2] + r2*m[1][0] + g2*m[1][1] + b2*m[1][2]), | |
| int(r1*m[0][3] + g1*m[0][4] + b1*m[0][5] + r2*m[1][3] + g2*m[1][4] + b2*m[1][5]), | |
| int(r1*m[0][6] + g1*m[0][7] + b1*m[0][8] + r2*m[1][6] + g2*m[1][7] + b2*m[1][8]) | |
| ) | |
| # Convert back to numpy array for Gradio | |
| return np.array(left) | |
| def make_stereopair(left_img, right_img, color_method): | |
| """Generate a stereo pair from left and right images""" | |
| if left_img is None or right_img is None: | |
| return None | |
| # Convert from numpy array (from Gradio) to PIL Image | |
| left = Image.fromarray(left_img) | |
| right = Image.fromarray(right_img) | |
| # Check if both images have the same dimensions | |
| if left.size != right.size: | |
| # Resize right image to match left image dimensions | |
| right = right.resize(left.size, Image.LANCZOS) | |
| width, height = left.size | |
| leftMap = left.load() | |
| rightMap = right.load() | |
| # Create a new image twice as wide | |
| pair = Image.new('RGB', (width * 2, height)) | |
| pairMap = pair.load() | |
| # Copy the left and right images side by side | |
| for y in range(0, height): | |
| for x in range(0, width): | |
| pairMap[x, y] = leftMap[x, y] | |
| pairMap[x + width, y] = rightMap[x, y] | |
| # Convert to monochrome if required | |
| if color_method == 'mono': | |
| pair = pair.convert('L') | |
| # Convert back to numpy array for Gradio | |
| return np.array(pair) | |
| def process_images(left_img, right_img, method, color_method): | |
| """Process images based on the selected method""" | |
| if method == "anaglyph": | |
| return make_anaglyph(left_img, right_img, color_method) | |
| elif method == "parallel": | |
| return make_stereopair(left_img, right_img, color_method) | |
| elif method == "crossed": | |
| return make_stereopair(right_img, left_img, color_method) | |
| return None | |
| css=""" | |
| div#col-container{ | |
| margin: 0 auto; | |
| max-width: 1340px; | |
| } | |
| """ | |
| # Create the Gradio interface | |
| with gr.Blocks(css=css) as app: | |
| with gr.Column(elem_id="col-container"): | |
| gr.Markdown("# 3D Anaglyph Image Generator") | |
| gr.Markdown("Upload left and right images to create 3D images using different methods.") | |
| with gr.Row(): | |
| with gr.Column(): | |
| with gr.Row(): | |
| with gr.Column(): | |
| left_input = gr.Image(label="Left Image") | |
| with gr.Column(): | |
| right_input = gr.Image(label="Right Image") | |
| method = gr.Radio( | |
| ["anaglyph", "parallel", "crossed"], | |
| label="Method", | |
| value="anaglyph", | |
| info="Select the 3D image creation method" | |
| ) | |
| color_method = gr.Radio( | |
| ["optimized", "true", "mono", "color", "halfcolor"], | |
| label="Color Method", | |
| value="optimized", | |
| info="Select the color processing method" | |
| ) | |
| generate_btn = gr.Button("Generate 3D Image", variant="primary") | |
| gr.Markdown(""" | |
| ### Methods: | |
| - **anaglyph**: Creates a red-cyan 3D image (requires 3D glasses) | |
| - **parallel**: Creates side-by-side images for parallel viewing | |
| - **crossed**: Creates side-by-side images for cross-eyed viewing | |
| ### Color Methods: | |
| - **optimized**: Best for most images (default) | |
| - **true**: True color anaglyph | |
| - **mono**: Monochrome output | |
| - **color**: Full color (may cause ghosting) | |
| - **halfcolor**: Balance between color and depth | |
| """) | |
| output = gr.Image(label="Generated 3D Anaglyph Image") | |
| generate_btn.click( | |
| fn=process_images, | |
| inputs=[left_input, right_input, method, color_method], | |
| outputs=output | |
| ) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| app.launch(share = True) |