File size: 6,094 Bytes
aec5cde
 
 
 
f7efd7b
aec5cde
f7efd7b
 
aec5cde
 
 
aa2570e
aec5cde
 
f118b28
 
aec5cde
 
 
 
f7efd7b
 
aec5cde
 
 
 
 
 
f7efd7b
 
 
aec5cde
 
 
 
 
 
f118b28
 
aec5cde
 
 
 
 
 
f7efd7b
 
 
 
 
 
 
 
 
 
 
 
aec5cde
 
 
 
f118b28
 
 
 
 
 
f7efd7b
 
f118b28
 
 
 
 
 
 
 
 
 
 
f7efd7b
 
 
f118b28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aa2570e
 
 
 
 
 
aec5cde
aa2570e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f7efd7b
aa2570e
f7efd7b
aa2570e
 
 
 
 
 
 
 
 
 
 
 
f7efd7b
 
 
aa2570e
f7efd7b
aa2570e
 
 
 
aec5cde
f118b28
 
aec5cde
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import gradio as gr
from PIL import Image
import numpy as np

# Fixed matrices for proper red/cyan anaglyph viewing
matrices = {
    # For true red/cyan anaglyphs, we need strict channel separation
    'true': [ [ 1, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0, 0, 0, 1 ] ],
    '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).convert('RGB')
    right = Image.fromarray(right_img).convert('RGB')
    
    # 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 blank image to put the anaglyph into
    width, height = left.size
    result = Image.new('RGB', (width, height))
    
    # Get the pixel maps
    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]
            
            # Calculate new RGB values
            r = 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])
            g = 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])
            b = 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])
            
            # Ensure values are in valid range
            r = max(0, min(255, r))
            g = max(0, min(255, g))
            b = max(0, min(255, b))
            
            resultMap[x, y] = (r, g, b)
    
    # 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).convert('RGB')
    right = Image.fromarray(right_img).convert('RGB')
    
    # 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
    
    # Create a new image twice as wide
    pair = Image.new('RGB', (width * 2, height))
    
    # Paste the left and right images side by side
    pair.paste(left, (0, 0))
    pair.paste(right, (width, 0))
    
    # 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(
                    ["true", "color", "optimized", "halfcolor", "mono"], 
                    label="Color Method", 
                    value="true",
                    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:
                - **true**: Pure red-cyan anaglyph (best for 3D glasses)
                - **color**: Same as true for red-cyan glasses
                - **optimized**: Better color perception but may cause ghosting
                - **halfcolor**: Balance between color and depth
                - **mono**: Monochrome output
                """)
    
            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()