fffiloni's picture
Update app.py
d94003f verified
import gradio as gr
from PIL import Image
import numpy as np
# Modified matrices with improved red/cyan separation
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.450, 1.050, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 1]
],
# New matrices with improved red/cyan separation
'dubois': [
[0.456, 0.5, 0.176, -0.04, -0.038, -0.016, -0.015, -0.021, -0.005], # Left image
[-0.043, -0.088, -0.002, 0.378, 0.734, -0.018, -0.072, -0.113, 1.226] # Right image
],
'dubois_optimized': [
[0.4561, 0.500484, 0.176381, -0.0400822, -0.0378246, -0.0157589, -0.0152161, -0.0205971, -0.00546856],
[-0.0434706, -0.0879388, -0.00155529, 0.378476, 0.73364, -0.0184503, -0.0721527, -0.112961, 1.2264]
]
}
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 new image for the result (important change)
result = Image.new("RGB", left.size)
# 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", "dubois", "dubois_optimized"],
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()