Spaces:
Build error
Build error
Upload seathruapp6.py
Browse files- seathruapp6.py +96 -0
seathruapp6.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import cv2
|
| 3 |
+
import numpy as np
|
| 4 |
+
from io import BytesIO
|
| 5 |
+
from PIL import Image
|
| 6 |
+
|
| 7 |
+
st.set_page_config(page_title="3-Point Underwater Color Corrector", layout="centered")
|
| 8 |
+
st.title("π Underwater Image Color Correction")
|
| 9 |
+
|
| 10 |
+
# --- Color Balancing Function ---
|
| 11 |
+
def gray_world_white_balance(img):
|
| 12 |
+
img = img.astype(np.float32)
|
| 13 |
+
avg_b, avg_g, avg_r = [np.mean(img[:, :, c]) for c in range(3)]
|
| 14 |
+
avg_gray = (avg_b + avg_g + avg_r) / 3
|
| 15 |
+
scale = [avg_gray / avg_b, avg_gray / avg_g, avg_gray / avg_r]
|
| 16 |
+
|
| 17 |
+
for c in range(3):
|
| 18 |
+
img[:, :, c] *= scale[c]
|
| 19 |
+
|
| 20 |
+
return np.clip(img, 0, 255).astype(np.uint8)
|
| 21 |
+
|
| 22 |
+
# --- 3-Point Correction Function ---
|
| 23 |
+
def apply_3_point_color_correction(image, shadow_shift, midtone_shift, highlight_shift):
|
| 24 |
+
image = image.astype(np.float32)
|
| 25 |
+
gray = cv2.cvtColor(image.astype(np.uint8), cv2.COLOR_BGR2GRAY)
|
| 26 |
+
|
| 27 |
+
shadow_mask = gray < 85
|
| 28 |
+
midtone_mask = (gray >= 85) & (gray < 170)
|
| 29 |
+
highlight_mask = gray >= 170
|
| 30 |
+
|
| 31 |
+
for c in range(3):
|
| 32 |
+
image[:, :, c][shadow_mask] += shadow_shift[c]
|
| 33 |
+
image[:, :, c][midtone_mask] += midtone_shift[c]
|
| 34 |
+
image[:, :, c][highlight_mask] += highlight_shift[c]
|
| 35 |
+
|
| 36 |
+
return np.clip(image, 0, 255).astype(np.uint8)
|
| 37 |
+
|
| 38 |
+
# --- Upload Section ---
|
| 39 |
+
uploaded_file = st.file_uploader("π€ Upload an underwater image", type=["jpg", "jpeg", "png"])
|
| 40 |
+
|
| 41 |
+
if uploaded_file:
|
| 42 |
+
image = Image.open(uploaded_file).convert("RGB")
|
| 43 |
+
image_np = np.array(image)
|
| 44 |
+
image_bgr = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
|
| 45 |
+
|
| 46 |
+
st.image(image, caption="π· Original Image", use_column_width=True)
|
| 47 |
+
|
| 48 |
+
# --- Auto Color Balance ---
|
| 49 |
+
apply_balance = st.checkbox("π§ͺ Auto Color Balance (Neutralize Blue/Green Tint)", value=True)
|
| 50 |
+
|
| 51 |
+
if apply_balance:
|
| 52 |
+
image_bgr = gray_world_white_balance(image_bgr)
|
| 53 |
+
|
| 54 |
+
# --- 3-Point Sliders ---
|
| 55 |
+
st.markdown("### ποΈ 3-Point Color Shift Controls")
|
| 56 |
+
|
| 57 |
+
col1, col2, col3 = st.columns(3)
|
| 58 |
+
with col1:
|
| 59 |
+
st.markdown("**Shadows**")
|
| 60 |
+
sr = st.slider("Red", -50, 50, 0, key="sr")
|
| 61 |
+
sg = st.slider("Green", -50, 50, 0, key="sg")
|
| 62 |
+
sb = st.slider("Blue", -50, 50, 0, key="sb")
|
| 63 |
+
|
| 64 |
+
with col2:
|
| 65 |
+
st.markdown("**Midtones**")
|
| 66 |
+
mr = st.slider("Red", -50, 50, 0, key="mr")
|
| 67 |
+
mg = st.slider("Green", -50, 50, 0, key="mg")
|
| 68 |
+
mb = st.slider("Blue", -50, 50, 0, key="mb")
|
| 69 |
+
|
| 70 |
+
with col3:
|
| 71 |
+
st.markdown("**Highlights**")
|
| 72 |
+
hr = st.slider("Red", -50, 50, 0, key="hr")
|
| 73 |
+
hg = st.slider("Green", -50, 50, 0, key="hg")
|
| 74 |
+
hb = st.slider("Blue", -50, 50, 0, key="hb")
|
| 75 |
+
|
| 76 |
+
shadow_shift = [sb, sg, sr]
|
| 77 |
+
midtone_shift = [mb, mg, mr]
|
| 78 |
+
highlight_shift = [hb, hg, hr]
|
| 79 |
+
|
| 80 |
+
corrected = apply_3_point_color_correction(image_bgr.copy(), shadow_shift, midtone_shift, highlight_shift)
|
| 81 |
+
corrected_rgb = cv2.cvtColor(corrected, cv2.COLOR_BGR2RGB)
|
| 82 |
+
|
| 83 |
+
st.image(corrected_rgb, caption="β
Corrected Image", use_column_width=True)
|
| 84 |
+
|
| 85 |
+
# --- Download Button ---
|
| 86 |
+
corrected_pil = Image.fromarray(corrected_rgb)
|
| 87 |
+
buf = BytesIO()
|
| 88 |
+
corrected_pil.save(buf, format="PNG")
|
| 89 |
+
byte_im = buf.getvalue()
|
| 90 |
+
|
| 91 |
+
st.download_button(
|
| 92 |
+
label="π₯ Download Corrected Image",
|
| 93 |
+
data=byte_im,
|
| 94 |
+
file_name="corrected_image.png",
|
| 95 |
+
mime="image/png"
|
| 96 |
+
)
|