dseditor commited on
Commit
4616fe0
·
verified ·
1 Parent(s): cc63c68

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +187 -0
  2. requirements.txt +3 -0
app.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ from PIL import Image
4
+ import io
5
+ import base64
6
+
7
+ def calculate_crop_box(image, target_ratio=1170/391):
8
+ """
9
+ 計算保持目標比例的最大裁切框
10
+ """
11
+ width, height = image.size
12
+ current_ratio = width / height
13
+
14
+ if current_ratio > target_ratio:
15
+ # 圖片較寬,需要裁切寬度
16
+ new_width = int(height * target_ratio)
17
+ left = (width - new_width) // 2
18
+ top = 0
19
+ right = left + new_width
20
+ bottom = height
21
+ else:
22
+ # 圖片較高,需要裁切高度
23
+ new_height = int(width / target_ratio)
24
+ left = 0
25
+ top = (height - new_height) // 2
26
+ right = width
27
+ bottom = top + new_height
28
+
29
+ return (left, top, right, bottom)
30
+
31
+ def process_image(image, crop_data=None):
32
+ """
33
+ 處理圖片:裁切並調整為目標尺寸
34
+ """
35
+ if image is None:
36
+ return None, "請上傳圖片"
37
+
38
+ # 如果有裁切數據,使用用戶選擇的區域
39
+ if crop_data is not None:
40
+ # Gradio 的 Image 組件在編輯模式下會返回包含裁切信息的數據
41
+ # 這裡我們處理裁切後的圖片
42
+ processed_image = image
43
+ else:
44
+ # 如果沒有裁切數據,自動計算最佳裁切區域
45
+ crop_box = calculate_crop_box(image)
46
+ processed_image = image.crop(crop_box)
47
+
48
+ # 調整為目標尺寸
49
+ target_size = (1170, 391)
50
+ final_image = processed_image.resize(target_size, Image.Resampling.LANCZOS)
51
+
52
+ return final_image, f"圖片已處理完成!尺寸:{final_image.size}"
53
+
54
+ def auto_crop_preview(image):
55
+ """
56
+ 自動裁切預覽
57
+ """
58
+ if image is None:
59
+ return None, "請上傳圖片"
60
+
61
+ crop_box = calculate_crop_box(image)
62
+ cropped = image.crop(crop_box)
63
+
64
+ # 創建預覽圖片,顯示裁切區域
65
+ preview = image.copy()
66
+ from PIL import ImageDraw
67
+ draw = ImageDraw.Draw(preview)
68
+
69
+ # 繪製裁切框
70
+ draw.rectangle(crop_box, outline="red", width=3)
71
+
72
+ return preview, f"建議裁切區域:{crop_box}"
73
+
74
+ # 創建 Gradio 界面
75
+ with gr.Blocks(title="圖片裁切工具", theme=gr.themes.Soft()) as demo:
76
+ gr.Markdown("# 🖼️ 圖片裁切工具")
77
+ gr.Markdown("### 將任意尺寸的圖片按 1170:391 比例裁切並調整為目標尺寸")
78
+
79
+ with gr.Row():
80
+ with gr.Column(scale=1):
81
+ # 圖片上傳區域
82
+ input_image = gr.Image(
83
+ label="上傳圖片",
84
+ type="pil",
85
+ height=400
86
+ )
87
+
88
+ # 按鈕區域
89
+ with gr.Row():
90
+ preview_btn = gr.Button("🔍 預覽裁切區域", variant="secondary")
91
+ process_btn = gr.Button("✂️ 裁切並處理", variant="primary")
92
+
93
+ with gr.Column(scale=1):
94
+ # 輸出區域
95
+ output_image = gr.Image(
96
+ label="處理後圖片",
97
+ type="pil",
98
+ height=400
99
+ )
100
+
101
+ # 狀態信息
102
+ status_text = gr.Textbox(
103
+ label="狀態",
104
+ value="等待圖片上傳...",
105
+ interactive=False
106
+ )
107
+
108
+ # 預覽功能
109
+ with gr.Row():
110
+ preview_image = gr.Image(
111
+ label="裁切區域預覽(紅框顯示建議裁切區域)",
112
+ type="pil",
113
+ height=300,
114
+ visible=False
115
+ )
116
+
117
+ # 進階設置
118
+ with gr.Accordion("🔧 進階設置", open=False):
119
+ gr.Markdown("### 目標尺寸設置")
120
+ with gr.Row():
121
+ target_width = gr.Number(
122
+ label="目標寬度",
123
+ value=1170,
124
+ precision=0
125
+ )
126
+ target_height = gr.Number(
127
+ label="目標高度",
128
+ value=391,
129
+ precision=0
130
+ )
131
+
132
+ quality_slider = gr.Slider(
133
+ label="輸出品質",
134
+ minimum=1,
135
+ maximum=100,
136
+ value=95,
137
+ step=1
138
+ )
139
+
140
+ # 使用說明
141
+ with gr.Accordion("📖 使用說明", open=False):
142
+ gr.Markdown("""
143
+ ### 如何使用:
144
+ 1. **上傳圖片**:點擊上傳區域選擇您的圖片
145
+ 2. **預覽裁切**:點擊「預覽裁切區域」查看建議的裁切區域
146
+ 3. **手動編輯**:在上傳的圖片上直接拖拽選擇裁切區域
147
+ 4. **處理圖片**:點擊「裁切並處理」生成最終圖片
148
+ 5. **下載結果**:右鍵點擊處理後的圖片選擇「另存為」
149
+
150
+ ### 功能特色:
151
+ - ✨ 自動計算最佳裁切比例
152
+ - 🎯 支援手動選擇裁切區域
153
+ - 📏 保持 1170:391 的精確比例
154
+ - 🖼️ 高品質圖片輸出
155
+ - 💾 簡單的下載流程
156
+ """)
157
+
158
+ # 事件綁定
159
+ preview_btn.click(
160
+ fn=auto_crop_preview,
161
+ inputs=[input_image],
162
+ outputs=[preview_image, status_text]
163
+ ).then(
164
+ fn=lambda: gr.update(visible=True),
165
+ outputs=[preview_image]
166
+ )
167
+
168
+ process_btn.click(
169
+ fn=process_image,
170
+ inputs=[input_image],
171
+ outputs=[output_image, status_text]
172
+ )
173
+
174
+ # 當圖片上傳時自動更新狀態
175
+ input_image.change(
176
+ fn=lambda img: "圖片已上傳,可以開始處理!" if img is not None else "請上傳圖片",
177
+ inputs=[input_image],
178
+ outputs=[status_text]
179
+ )
180
+
181
+ # 啟動應用程式
182
+ if __name__ == "__main__":
183
+ demo.launch(
184
+ server_name="0.0.0.0",
185
+ server_port=7860,
186
+ share=True
187
+ )
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio>=4.0.0
2
+ pillow>=9.0.0
3
+ numpy>=1.21.0