File size: 5,816 Bytes
aec5cde
 
 
 
 
aa2570e
aec5cde
 
 
aa2570e
aec5cde
 
f118b28
 
aec5cde
 
 
 
aa2570e
 
aec5cde
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f118b28
 
aec5cde
 
 
 
 
 
aa2570e
 
 
 
 
aec5cde
 
 
 
f118b28
 
 
 
 
 
aa2570e
 
f118b28
 
 
 
 
 
 
aa2570e
 
f118b28
 
 
aa2570e
f118b28
aa2570e
 
 
 
 
f118b28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aa2570e
 
 
 
 
 
aec5cde
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
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()