Team Ai
Apppublic

JasonHong984/ImageProcessingApp

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes
app.py165 linesDownload Raw Back to root
1import streamlit as st2import cv23import numpy as np4import random5import os6import zipfile7import shutil8from moviepy.editor import ImageSequenceClip9from PIL import Image10import io11 12# 定義生成白色矩形的函數13def generate_white_rectangles(14    image,  # 直接傳入圖像陣列15    min_width_ratio=0.2,16    min_height_ratio=0.2,17    max_width_ratio=0.5,18    max_height_ratio=0.5,19    num_rectangles_range=(2, 5),20    margin_ratio=0.0521):22    height, width, _ = image.shape23    min_width = int(width * min_width_ratio)24    min_height = int(height * min_height_ratio)25    max_width = int(width * max_width_ratio)26    max_height = int(height * max_height_ratio)27    margin = int(min(width, height) * margin_ratio)28    num_rectangles = random.randint(num_rectangles_range[0], num_rectangles_range[1])29 30    output = image.copy()31    positions = []32 33    random.seed(random.randint(0, 1000000))34 35    for _ in range(num_rectangles):36        for attempt in range(500):37            rect_width = random.randint(min_width, max_width)38            rect_height = random.randint(min_height, max_height)39            x = random.randint(0, width - rect_width)40            y = random.randint(0, height - rect_height)41            new_rect = (x, y, x + rect_width, y + rect_height)42 43            expanded_rect = (x - margin, y - margin, x + rect_width + margin, y + rect_height + margin)44 45            if expanded_rect[0] < 0 or expanded_rect[1] < 0 or expanded_rect[2] > width or expanded_rect[3] > height:46                continue47 48            overlap = False49            for (x1, y1, x2, y2) in positions:50                expanded_existing = (x1 - margin, y1 - margin, x2 + margin, y2 + margin)51                if not (expanded_rect[2] <= expanded_existing[0] or expanded_rect[0] >= expanded_existing[2] or52                        expanded_rect[3] <= expanded_existing[1] or expanded_rect[1] >= expanded_existing[3]):53                    overlap = True54                    break55 56            if not overlap:57                positions.append(new_rect)58                cv2.rectangle(output, (x, y), (x + rect_width, y + rect_height), (255, 255, 255), -1)59                break60 61    return output62 63# 定義生成影片的函數64def create_random_video(image_list, fps=2, frame_duration=0.5, total_duration=15):65    required_frames = int(total_duration / frame_duration)66 67    if len(image_list) < required_frames:68        image_list = random.choices(image_list, k=required_frames)69    else:70        image_list = random.sample(image_list, k=required_frames)71 72    random.shuffle(image_list)73 74    first_image = image_list[0]75    height, width, _ = first_image.shape76 77    processed_images = []78    for img in image_list:79        img_resized = cv2.resize(img, (width, height))80        img_rgb = cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB)81        processed_images.append(img_rgb)82 83    clip = ImageSequenceClip(processed_images, durations=[frame_duration] * len(processed_images))84    clip = clip.set_fps(fps)85 86    # 將影片寫入記憶體(BytesIO)87    video_io = io.BytesIO()88    clip.write_videofile("temp.mp4", codec="libx264", audio=False)89    with open("temp.mp4", "rb") as f:90        video_io.write(f.read())91    video_io.seek(0)92    os.remove("temp.mp4")  # 刪除臨時檔案93    return video_io94 95# Streamlit 應用主邏輯96def main():97    st.title("圖片處理與影片生成工具")98    st.subheader("上傳多張 JPG 或 PNG 圖片,我們將添加隨機白色矩形、保存處理後圖片並生成 15 秒影片(每張 0.5 秒)")99 100    uploaded_files = st.file_uploader("選擇圖片", type=["jpg", "jpeg", "png"], accept_multiple_files=True)101 102    if uploaded_files:103        # 創建臨時資料夾保存處理後圖片104        output_dir = "processed_images"105        if os.path.exists(output_dir):106            shutil.rmtree(output_dir)107        os.makedirs(output_dir)108 109        image_list = []110        processed_paths = []111 112        for uploaded_file in uploaded_files:113            # 讀取上傳的圖片114            image = Image.open(uploaded_file)115            image_np = np.array(image)116            if image_np.shape[2] == 4:  # 處理 PNG 的 RGBA117                image_np = cv2.cvtColor(image_np, cv2.COLOR_RGBA2BGR)118            else:119                image_np = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)120 121            # 生成處理後圖片122            processed_image = generate_white_rectangles(image_np)123 124            # 保存處理後圖片125            output_path = os.path.join(output_dir, f"masked_{uploaded_file.name}")126            cv2.imwrite(output_path, processed_image)127            processed_paths.append(output_path)128 129            image_list.append(processed_image)130 131        if image_list:132            st.success(f"已處理並保存 {len(image_list)} 張圖片!")133 134            # 顯示處理後圖片135            st.subheader("處理後的圖片")136            for img_path in processed_paths:137                st.image(img_path, caption=os.path.basename(img_path), use_column_width=True)138 139            # 生成影片140            with st.spinner("生成影片中..."):141                video_io = create_random_video(image_list)142 143            # 顯示影片144            st.video(video_io.read(), format="video/mp4")145 146            # 提供影片下載按鈕147            video_io.seek(0)148            st.download_button("下載影片", video_io, file_name="processed_video.mp4", mime="video/mp4")149 150            # 打包處理後圖片為 ZIP 並提供下載151            zip_io = io.BytesIO()152            with zipfile.ZipFile(zip_io, mode='w', compression=zipfile.ZIP_DEFLATED) as zipf:153                for root, _, files in os.walk(output_dir):154                    for file in files:155                        zipf.write(os.path.join(root, file), arcname=file)156            zip_io.seek(0)157            st.download_button("下載處理後圖片 ZIP", zip_io, file_name="processed_images.zip", mime="application/zip")158 159        # 清空臨時資料夾160        shutil.rmtree(output_dir)161 162# 運行 Streamlit 應用163if __name__ == "__main__":164    main()165