Last commit not found
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] | |
resultMap[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(result) | |
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() |