import streamlit as st import cv2 import numpy as np from PIL import Image # Function to process the image def process_image(image, operation, value=None): if operation == "🖼 Original": return image elif operation == "⚫ Convert to Grayscale": return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) elif operation == "🌈 Convert to Color": return cv2.cvtColor(image, cv2.COLOR_BGR2RGB) elif operation == "🔄 Rotate": if value is not None: return rotate_image_without_cropping(image, value) elif operation == "🌀 Blur": if value is not None: kernel_size = (value, value) return cv2.GaussianBlur(image, kernel_size, 0) elif operation == "✂ Edge Detection": return cv2.Canny(image, 100, 200) elif operation == "☀ Adjust Brightness": if value is not None: hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV) h, s, v = cv2.split(hsv) v = np.clip(v.astype(np.int16) + value, 0, 255).astype(np.uint8) final_hsv = cv2.merge((h, s, v)) return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2RGB) return image # Fix rotation issue (avoids cropping & mirroring) def rotate_image_without_cropping(image, angle): (h, w) = image.shape[:2] center = (w // 2, h // 2) # Compute the rotation matrix M = cv2.getRotationMatrix2D(center, angle, 1.0) # Compute the new bounding box size cos = np.abs(M[0, 0]) sin = np.abs(M[0, 1]) new_w = int((h * sin) + (w * cos)) new_h = int((h * cos) + (w * sin)) # Adjust transformation matrix to fit in new bounds M[0, 2] += (new_w / 2) - center[0] M[1, 2] += (new_h / 2) - center[1] # Apply rotation with expanded borders rotated = cv2.warpAffine(image, M, (new_w, new_h), borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0)) return rotated # Streamlit app def main(): st.title(" Image Processing App ") st.write("📂 Upload an image and apply various transformations below! ✨") uploaded_file = st.file_uploader("📤 Choose an image...", type=["jpg", "jpeg", "png"]) if uploaded_file is not None: # Read image image = Image.open(uploaded_file) img_array = np.array(image) img_bgr = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR) col1, col2 = st.columns(2) with col1: st.subheader("📌 Original Image") st.image(image, use_container_width=True) with col2: st.subheader("🖌 Processed Image") operation = st.selectbox( "🎛 Select an Operation", ["🖼 Original", "⚫ Convert to Grayscale", "🌈 Convert to Color", "🔄 Rotate", "🌀 Blur", "✂ Edge Detection", "☀ Adjust Brightness"] ) processed_img = img_bgr.copy() if operation == "🔄 Rotate": angle = st.slider("↩ Rotation Angle", -180, 180, 0) processed_img = process_image(img_bgr, operation, angle) elif operation == "☀ Adjust Brightness": brightness = st.slider("🔆 Brightness Level", -100, 100, 0) processed_img = process_image(img_bgr, operation, brightness) elif operation == "🌀 Blur": blur_level = st.slider("🎭 Blur Intensity", 1, 25, 5, step=2) # Ensures odd kernel size processed_img = process_image(img_bgr, operation, blur_level) else: processed_img = process_image(img_bgr, operation) # Convert back to RGB if len(processed_img.shape) == 2: processed_img_rgb = cv2.cvtColor(processed_img, cv2.COLOR_GRAY2RGB) else: processed_img_rgb = cv2.cvtColor(processed_img, cv2.COLOR_BGR2RGB) st.image(processed_img_rgb, use_container_width=True) # Ensure grayscale images are properly handled before download if len(processed_img.shape) == 2: processed_img = cv2.cvtColor(processed_img, cv2.COLOR_GRAY2BGR) is_success, buffer = cv2.imencode(".png", processed_img) if is_success: st.download_button( label="📥 Download Processed Image", data=buffer.tobytes(), file_name="processed_image.png", mime="image/png" ) if __name__ == "__main__": main()