File size: 7,379 Bytes
57bd923
914bd5e
 
 
 
 
57bd923
 
 
 
914bd5e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57bd923
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
914bd5e
 
57bd923
914bd5e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57bd923
914bd5e
 
 
 
 
 
 
57bd923
914bd5e
 
57bd923
914bd5e
 
 
 
 
 
 
 
57bd923
 
914bd5e
57bd923
914bd5e
 
 
 
 
57bd923
 
914bd5e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57bd923
 
 
 
 
 
 
 
 
 
914bd5e
 
 
57bd923
 
 
914bd5e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57bd923
 
 
 
 
 
 
 
 
914bd5e
 
 
 
 
 
57bd923
914bd5e
 
 
 
 
 
 
57bd923
 
 
 
914bd5e
 
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# app.py - Streamlit für Hugging Face Spaces (MIT REMBG-INTEGRATION)
import os
import tempfile
import streamlit as st
from PIL import Image
import io
import numpy as np

# NEUER IMPORT für die KI-gestützte Hintergrundentfernung
from rembg import remove 

# ----------------------------------------------------
# 🚨 KRITISCHE FIXES FÜR DEN PERMISSION ERROR (beibehalten)
# ----------------------------------------------------
TEMP_STREAMLIT_HOME = os.path.join(tempfile.gettempdir(), "st_config_workaround")
os.makedirs(TEMP_STREAMLIT_HOME, exist_ok=True)
os.environ["STREAMLIT_HOME"] = TEMP_STREAMLIT_HOME
os.environ["STREAMLIT_GATHER_USAGE_STATS"] = "false"
CONFIG_PATH = os.path.join(TEMP_STREAMLIT_HOME, "config.toml")
CONFIG_CONTENT = """
[browser]
gatherUsageStats = false

[server]
headless = true
port = 7860
enableCORS = false
"""
with open(CONFIG_PATH, "w") as f:
    f.write(CONFIG_CONTENT)

# --- NEUE FUNKTION: Hintergrundentfernung mit KI ---

def remove_background(image_pil):
    """
    Entfernt den Hintergrund eines Bildes mithilfe der rembg-Bibliothek.
    Das Ergebnis ist ein PIL-Image mit Alpha-Kanal (RGBA).
    """
    # Konvertiere PIL Image zu Bytes für rembg (empfohlene Methode)
    img_byte_arr = io.BytesIO()
    image_pil.save(img_byte_arr, format='PNG')
    input_bytes = img_byte_arr.getvalue()
    
    # KI-Operation: Hintergrund entfernen
    # Da wir auf CPU laufen, kann dies einige Sekunden dauern!
    output_bytes = remove(input_bytes, alpha_matting=True)
    
    # Konvertiere die Ergebnis-Bytes zurück zu einem PIL Image
    return Image.open(io.BytesIO(output_bytes))

# --- Bildverarbeitungsfunktionen (Unverändert) ---

def stack_horizontal(img1, img2):
    # ... (Code unverändert) ...
    img1 = img1.convert("RGB") 
    img2 = img2.convert("RGB")
    
    h1, h2 = img1.size[1], img2.size[1]
    if h1 != h2:
        w2_new = int(img2.size[0] * h1 / h2)
        img2 = img2.resize((w2_new, h1), Image.Resampling.LANCZOS)
            
    total_width = img1.size[0] + img2.size[0]
    total_height = img1.size[1]
    
    stacked_img = Image.new('RGB', (total_width, total_height))
    stacked_img.paste(img1, (0, 0))
    stacked_img.paste(img2, (img1.size[0], 0))
    
    return stacked_img

def blend_images_cpu(img1, img2, alpha):
    # ... (Code unverändert) ...
    img1 = img1.convert("RGBA") 
    img2 = img2.convert("RGBA")
    
    if img1.size != img2.size:
        img2 = img2.resize(img1.size, Image.Resampling.LANCZOS)
        
    blended = Image.blend(img1, img2, alpha)
    return blended.convert("RGB") 

def overlay_image(background_img, overlay_img, x_pos, y_pos, scale_factor):
    # ... (Code unverändert) ...
    background = background_img.convert("RGBA")
    overlay = overlay_img.convert("RGBA")

    new_width = int(overlay.width * scale_factor)
    new_height = int(overlay.height * scale_factor)
    overlay = overlay.resize((new_width, new_height), Image.Resampling.LANCZOS)

    result = Image.new("RGBA", background.size)
    result.paste(background, (0, 0))
    result.paste(overlay, (x_pos, y_pos), overlay)

    return result.convert("RGB") 


# --- Streamlit UI ---
st.set_page_config(page_title="Image Transformer", layout="wide")

st.title("🖼️ CPU Image Transformer (Blend, Stack, KI-Overlay)")
st.markdown("**Blend** (überblenden), **Stack** (aneinanderreihen) oder **KI-Overlay** (Katze auf Klo!) - Reine CPU-Operation.")

col1, col2 = st.columns(2)

with col1:
    st.subheader("Eingabe & Steuerung")
    img1_file = st.file_uploader("Bild 1 (Basisbild / Hintergrund)", type=["png", "jpg", "jpeg", "webp"])
    img2_file = st.file_uploader("Bild 2 (Zusatzbild / Overlay)", type=["png", "jpg", "jpeg", "webp"])
    
    method = st.selectbox("Transformationsmethode", ["Blend", "Stack Horizontal", "Overlay (Position & Scale)"])
    
    # Blending-Faktor (nur bei Blend relevant)
    alpha = st.slider("Blending-Faktor (Alpha, nur bei 'Blend' aktiv)", 0.0, 1.0, 0.5, 0.05, disabled=(method != "Blend"))
    
    # Overlay-Parameter (nur bei Overlay relevant)
    with st.expander("Overlay-Optionen", expanded=(method == "Overlay (Position & Scale)")):
        
        # NEUES UI-ELEMENT: KI-Freistellung
        auto_remove_bg = st.checkbox(
            "Automatisch freistellen (KI)", 
            value=False, 
            disabled=(method != "Overlay (Position & Scale)"),
            help="Nutzt ein KI-Modell, um den Hintergrund von Bild 2 zu entfernen. **Achtung: Dies ist eine CPU-intensive Operation und kann die Verarbeitungszeit erhöhen.**"
        )
        st.divider() # Trennlinie
        
        x_pos = st.slider("X-Position des Overlays", 0, 1000, 0, 10, disabled=(method != "Overlay (Position & Scale)"))
        y_pos = st.slider("Y-Position des Overlays", 0, 1000, 0, 10, disabled=(method != "Overlay (Position & Scale)"))
        scale_factor = st.slider("Skalierung des Overlays", 0.1, 3.0, 1.0, 0.1, disabled=(method != "Overlay (Position & Scale)"))
        
        if not auto_remove_bg:
            st.info("Wenn **nicht** freigestellt wird, muss Bild 2 bereits ein **transparentes PNG** sein!")
    
    process_btn = st.button("🚀 Verarbeiten", type="primary")

with col2:
    st.subheader("Resultat")
    result_placeholder = st.empty()

# Verarbeitung
if process_btn:
    if img1_file and img2_file:
        with st.spinner("Verarbeite..."):
            try:
                img1 = Image.open(img1_file)
                img2 = Image.open(img2_file)
                
                result = None
                if method == "Blend":
                    result = blend_images_cpu(img1, img2, alpha)
                elif method == "Stack Horizontal":
                    result = stack_horizontal(img1, img2)
                elif method == "Overlay (Position & Scale)":
                    
                    # KI-Freistellungslogik HIER
                    overlay_img_final = img2
                    if auto_remove_bg:
                        st.text("KI: Hintergrund von Bild 2 wird entfernt...")
                        overlay_img_final = remove_background(img2)
                        st.text("KI: Freistellung abgeschlossen.")

                    result = overlay_image(img1, overlay_img_final, x_pos, y_pos, scale_factor)
                
                if result:
                    result_placeholder.image(result, use_container_width=True)
                    
                    # Download-Button
                    buf = io.BytesIO()
                    result.save(buf, format="PNG") # PNG ist wichtig, da es den Alpha-Kanal für den Download beibehält
                    st.download_button(
                        label="💾 Download Resultat",
                        data=buf.getvalue(),
                        file_name=f"result_{method.lower().replace(' ', '_')}.png",
                        mime="image/png"
                    )
            except Exception as e:
                st.error(f"Fehler bei der Verarbeitung: {e}")
                # Füge hier weitere Debug-Informationen hinzu, wenn das Modell nicht lädt
                if "No such file or directory" in str(e):
                    st.error("WICHTIG: Die KI-Modell-Dateien wurden nicht gefunden. Stelle sicher, dass `rembg` alle Abhängigkeiten korrekt geladen hat.")
    else:
        st.warning("⚠️ Bitte beide Bilder hochladen!")