|
| 1 | +import streamlit as st |
| 2 | +import cv2 |
| 3 | +import numpy as np |
| 4 | +from PIL import Image |
| 5 | + |
| 6 | +st.set_page_config(page_title="Ultimate Image Enhancer", layout="wide") |
| 7 | +st.title("🎨 Ultimate Image Enhancer – Beginner Friendly Image Processing App") |
| 8 | + |
| 9 | +st.markdown(""" |
| 10 | +<div style='background-color:#f0f8ff; padding:20px; border-radius:10px'> |
| 11 | +<h3 style='color:#2e86de'>Upload an image and apply a wide range of filters and operations!</h3> |
| 12 | +</div> |
| 13 | +""", unsafe_allow_html=True) |
| 14 | + |
| 15 | +uploaded_file = st.file_uploader("📤 Upload your image", type=["jpg", "png", "jpeg"]) |
| 16 | + |
| 17 | +if uploaded_file: |
| 18 | + image = Image.open(uploaded_file) |
| 19 | + img_np = np.array(image) |
| 20 | + |
| 21 | + st.image(img_np, caption="🖼️ Original Image", use_container_width=True) |
| 22 | + |
| 23 | + gray = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY) |
| 24 | + operation = st.selectbox("🛠️ Choose an Operation", [ |
| 25 | + "Grayscale", |
| 26 | + "Gaussian Blur", |
| 27 | + "Median Blur", |
| 28 | + "Bilateral Filter", |
| 29 | + "Sobel Edge Detection", |
| 30 | + "Canny Edge Detection", |
| 31 | + "Histogram Equalization", |
| 32 | + "Thresholding", |
| 33 | + "Adaptive Thresholding", |
| 34 | + "Brightness & Contrast", |
| 35 | + "Sharpening", |
| 36 | + "Rotation", |
| 37 | + "Flip", |
| 38 | + "Dilation", |
| 39 | + "Erosion", |
| 40 | + "Opening", |
| 41 | + "Closing", |
| 42 | + "Gradient", |
| 43 | + "Top Hat", |
| 44 | + "Black Hat" |
| 45 | + ]) |
| 46 | + |
| 47 | + kernel_size = st.slider("🧩 Kernel Size (odd only)", 3, 11, step=2, value=5) |
| 48 | + kernel = np.ones((kernel_size, kernel_size), np.uint8) |
| 49 | + |
| 50 | + result = None |
| 51 | + |
| 52 | + if operation == "Grayscale": |
| 53 | + result = gray |
| 54 | + |
| 55 | + elif operation == "Gaussian Blur": |
| 56 | + result = cv2.GaussianBlur(img_np, (kernel_size, kernel_size), 0) |
| 57 | + |
| 58 | + elif operation == "Median Blur": |
| 59 | + result = cv2.medianBlur(img_np, kernel_size) |
| 60 | + |
| 61 | + elif operation == "Bilateral Filter": |
| 62 | + result = cv2.bilateralFilter(img_np, 9, 75, 75) |
| 63 | + |
| 64 | + elif operation == "Sobel Edge Detection": |
| 65 | + sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0) |
| 66 | + sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1) |
| 67 | + sobel = cv2.magnitude(sobel_x, sobel_y) |
| 68 | + result = np.uint8(sobel) |
| 69 | + |
| 70 | + elif operation == "Canny Edge Detection": |
| 71 | + result = cv2.Canny(gray, 100, 200) |
| 72 | + |
| 73 | + elif operation == "Histogram Equalization": |
| 74 | + result = cv2.equalizeHist(gray) |
| 75 | + |
| 76 | + elif operation == "Thresholding": |
| 77 | + _, result = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) |
| 78 | + |
| 79 | + elif operation == "Adaptive Thresholding": |
| 80 | + result = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, |
| 81 | + cv2.THRESH_BINARY, kernel_size, 5) |
| 82 | + |
| 83 | + elif operation == "Brightness & Contrast": |
| 84 | + brightness = st.slider("🔆 Brightness", -100, 100, 0) |
| 85 | + contrast = st.slider("🎚️ Contrast", -100, 100, 0) |
| 86 | + result = cv2.convertScaleAbs(img_np, alpha=1 + contrast / 100.0, beta=brightness) |
| 87 | + |
| 88 | + elif operation == "Sharpening": |
| 89 | + sharp_kernel = np.array([[0, -1, 0], |
| 90 | + [-1, 5, -1], |
| 91 | + [0, -1, 0]]) |
| 92 | + result = cv2.filter2D(img_np, -1, sharp_kernel) |
| 93 | + |
| 94 | + elif operation == "Rotation": |
| 95 | + angle = st.slider("🔁 Rotate Angle", -180, 180, 0) |
| 96 | + (h, w) = img_np.shape[:2] |
| 97 | + center = (w // 2, h // 2) |
| 98 | + M = cv2.getRotationMatrix2D(center, angle, 1.0) |
| 99 | + result = cv2.warpAffine(img_np, M, (w, h)) |
| 100 | + |
| 101 | + elif operation == "Flip": |
| 102 | + flip_code = st.radio("↔️ Flip Mode", ["Horizontal", "Vertical"]) |
| 103 | + result = cv2.flip(img_np, 1 if flip_code == "Horizontal" else 0) |
| 104 | + |
| 105 | + elif operation == "Dilation": |
| 106 | + result = cv2.dilate(gray, kernel, iterations=1) |
| 107 | + |
| 108 | + elif operation == "Erosion": |
| 109 | + result = cv2.erode(gray, kernel, iterations=1) |
| 110 | + |
| 111 | + elif operation == "Opening": |
| 112 | + result = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel) |
| 113 | + |
| 114 | + elif operation == "Closing": |
| 115 | + result = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel) |
| 116 | + |
| 117 | + elif operation == "Gradient": |
| 118 | + result = cv2.morphologyEx(gray, cv2.MORPH_GRADIENT, kernel) |
| 119 | + |
| 120 | + elif operation == "Top Hat": |
| 121 | + result = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, kernel) |
| 122 | + |
| 123 | + elif operation == "Black Hat": |
| 124 | + result = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, kernel) |
| 125 | + |
| 126 | + if result is not None: |
| 127 | + st.markdown("---") |
| 128 | + st.image(result, caption=f"✨ Result: {operation}", use_container_width=True, |
| 129 | + channels="GRAY" if len(result.shape) == 2 else "BGR") |
| 130 | + st.success("✅ Operation Applied Successfully!") |
0 commit comments