零代码玩转AI艺术:用Streamlit打造专属风格迁移平台
引言:当AI艺术遇见零代码开发
在人工智能蓬勃发展的今天,风格迁移技术让每个人都能成为数字艺术家。但传统AI应用开发需要复杂的编程知识,这让许多创意人士望而却步。有没有一种方式,能让非技术用户也能轻松创建和使用AI工具?这就是我们今天要探索的主题——使用Streamlit构建零代码AI艺术生成平台。
Streamlit作为Python生态中的革命性工具,让数据科学家和AI工程师能够用极少的代码创建交互式Web应用。结合风格迁移AI模型,我们可以打造出直观易用的艺术创作平台。
本文将手把手带你完成从设计到打包的完整流程,并附赠一个只需50行代码的完整可运行Demo。
一、平台架构设计:全栈视角
在深入代码之前,让我们先理解整个系统的架构设计。一个完整的AI应用不仅需要前端的交互界面,还需要后端的模型推理、数据处理和状态管理。
这个架构图展示了我们的平台如何将用户交互、AI处理和结果管理有机结合起来。每个模块都有明确的职责,保证了系统的可维护性和扩展性。
二、环境搭建与依赖配置
2.1 创建虚拟环境
首先,我们需要创建一个干净的Python环境来管理依赖:
# 创建项目目录
mkdir ai-art-platform
cd ai-art-platform
# 创建虚拟环境(Windows)
python -m venv venv
venv\Scripts\activate
# 创建虚拟环境(Mac/Linux)
python3 -m venv venv
source venv/bin/activate
2.2 安装核心依赖
创建requirements.txt文件,包含以下内容:
streamlit==1.28.0
torch==2.0.1
torchvision==0.15.2
Pillow==10.0.0
opencv-python==4.8.1
numpy==1.24.3
matplotlib==3.7.2
streamlit-image-comparison==0.0.5
pyinstaller==5.13.0
安装所有依赖:
pip install -r requirements.txt
三、界面设计:打造专业级用户体验
3.1 侧边栏设计:功能控制中心
侧边栏是用户与AI模型交互的主要区域,需要精心设计以提供流畅的用户体验。
import streamlit as st
import base64
from PIL import Image
import io
def create_sidebar():
"""创建功能侧边栏"""
with st.sidebar:
st.title("🎨 AI艺术工作室")
st.markdown("---")
# 图片上传区域
st.subheader("📤 图像上传")
# 双模式上传:本地文件或URL
upload_option = st.radio(
"选择上传方式",
["本地文件", "网络URL"],
help="选择图片上传方式"
)
content_image = None
style_image = None
if upload_option == "本地文件":
col1, col2 = st.columns(2)
with col1:
content_file = st.file_uploader(
"上传内容图片",
type=['png', 'jpg', 'jpeg'],
key="content"
)
if content_file:
content_image = Image.open(content_file)
st.image(content_image, caption="内容图片", use_column_width=True)
with col2:
style_file = st.file_uploader(
"上传风格图片",
type=['png', 'jpg', 'jpeg'],
key="style"
)
if style_file:
style_image = Image.open(style_file)
st.image(style_image, caption="风格图片", use_column_width=True)
else: # URL模式
content_url = st.text_input("内容图片URL", placeholder="https://example.com/image.jpg")
style_url = st.text_input("风格图片URL", placeholder="https://example.com/style.jpg")
if content_url and style_url:
# 这里可以添加URL下载逻辑
st.info("URL模式待实现")
st.markdown("---")
# 风格预设选择
st.subheader("🎭 风格选择")
style_presets = [
"油画风格", "水墨风格", "卡通风格",
"抽象艺术", "像素艺术", "自定义"
]
selected_style = st.selectbox("选择艺术风格", style_presets)
# 高级参数调整
st.subheader("⚙️ 高级参数")
# 使用滑块控件
style_weight = st.slider(
"风格强度",
min_value=0.1,
max_value=1.0,
value=0.5,
step=0.1,
help="控制风格迁移的程度"
)
num_iterations = st.slider(
"迭代次数",
min_value=10,
max_value=500,
value=100,
step=10,
help="迭代次数越多,效果越好但耗时越长"
)
resolution = st.select_slider(
"输出分辨率",
options=["512x512", "768x768", "1024x1024", "原始尺寸"],
value="768x768"
)
return {
"content_image": content_image,
"style_image": style_image,
"style": selected_style,
"style_weight": style_weight,
"iterations": num_iterations,
"resolution": resolution
}
3.2 主界面设计:三栏对比视图
主界面需要同时展示原图、风格图和生成结果,提供直观的对比体验。
def create_main_interface(content_img, style_img, result_img=None, progress=0):
"""创建主界面布局"""
st.title("AI风格迁移创作平台")
st.markdown("---")
# 进度显示
if progress > 0:
progress_bar = st.progress(progress)
st.caption(f"🔄 处理进度: {progress}%")
# 三栏布局
col1, col2, col3 = st.columns(3)
with col1:
st.subheader("📷 原图")
if content_img:
st.image(content_img, use_column_width=True)
# 图片信息
st.caption(f"尺寸: {content_img.size} | 模式: {content_img.mode}")
else:
st.info("请上传内容图片")
with col2:
st.subheader("🎨 风格图")
if style_img:
st.image(style_img, use_column_width=True)
st.caption(f"尺寸: {style_img.size} | 模式: {style_img.mode}")
else:
st.info("请上传风格图片")
with col3:
st.subheader("✨ 生成结果")
if result_img:
# 使用streamlit-image-comparison进行详细对比
try:
from streamlit_image_comparison import image_comparison
# 比较原图和生成图
image_comparison(
img1=content_img,
img2=result_img,
label1="原图",
label2="生成图"
)
except:
# 备选方案
st.image(result_img, use_column_width=True)
# 结果操作按钮
col_a, col_b, col_c = st.columns(3)
with col_a:
if st.button("🔍 放大", key="zoom"):
st.session_state.zoomed = not st.session_state.get('zoomed', False)
with col_b:
# 下载功能
img_bytes = image_to_bytes(result_img)
st.download_button(
label="💾 下载",
data=img_bytes,
file_name="ai_art_result.png",
mime="image/png"
)
with col_c:
if st.button("🔄 重新生成", key="regenerate"):
st.rerun()
else:
if progress > 0:
st.warning("正在生成中...")
else:
st.success("点击生成按钮开始创作!")
# 放大查看功能
if st.session_state.get('zoomed', False) and result_img:
st.markdown("---")
st.subheader("🔍 细节查看")
zoom_level = st.slider("缩放级别", 1.0, 3.0, 1.5, 0.1)
# 这里可以实现图片局部放大功能
st.image(result_img, use_column_width=True)
def image_to_bytes(image):
"""将PIL Image转换为字节流"""
img_byte_arr = io.BytesIO()
image.save(img_byte_arr, format='PNG')
return img_byte_arr.getvalue()
四、核心功能实现
4.1 实时进度反馈:SSE技术实现
Server-Sent Events (SSE) 允许服务器向客户端推送实时更新,是进度反馈的理想选择。
import time
import json
import threading
import queue
class ProgressManager:
"""进度管理类,支持SSE推送"""
def __init__(self):
self.progress_queue = queue.Queue()
self.clients = []
self.current_progress = 0
def update_progress(self, value, message=""):
"""更新进度值"""
self.current_progress = min(100, max(0, value))
progress_data = {
"progress": self.current_progress,
"message": message,
"timestamp": time.time()
}
# 通知所有客户端
for client_queue in self.clients:
try:
client_queue.put(json.dumps(progress_data))
except:
pass # 客户端可能已断开
def simulate_processing(self, steps=10):
"""模拟处理过程(实际项目中替换为真实AI处理)"""
for i in range(steps + 1):
progress = int((i / steps) * 100)
self.update_progress(
progress,
f"正在处理第{i}步/共{steps}步"
)
time.sleep(0.5) # 模拟处理时间
def get_progress_stream(self):
"""获取进度事件流"""
client_queue = queue.Queue()
self.clients.append(client_queue)
def generate():
try:
while True:
# 发送保持连接的消息
yield f"data: {json.dumps({'type': 'ping'})}\n\n"
try:
# 等待新进度更新
message = client_queue.get(timeout=5)
yield f"data: {message}\n\n"
except queue.Empty:
continue
finally:
# 客户端断开连接时清理
if client_queue in self.clients:
self.clients.remove(client_queue)
return generate()
# Streamlit中集成进度显示
def show_live_progress():
"""在Streamlit中显示实时进度"""
if 'progress_manager' not in st.session_state:
st.session_state.progress_manager = ProgressManager()
pm = st.session_state.progress_manager
# 进度显示区域
progress_placeholder = st.empty()
message_placeholder = st.empty()
# 模拟进度更新
if st.button("开始生成", type="primary"):
# 在新线程中处理
def process_in_background():
pm.simulate_processing(20)
thread = threading.Thread(target=process_in_background)
thread.start()
# 在前端显示进度
while pm.current_progress < 100:
progress_placeholder.progress(pm.current_progress / 100)
message_placeholder.caption(f"进度: {pm.current_progress}%")
time.sleep(0.1)
progress_placeholder.success("✅ 处理完成!")
4.2 历史记录管理:LRU缓存实现
from collections import OrderedDict
from datetime import datetime
import hashlib
class HistoryManager:
"""历史记录管理器,使用LRU缓存策略"""
def __init__(self, max_size=100):
self.max_size = max_size
self.history = OrderedDict()
self.storage_path = "history_storage"
# 确保存储目录存在
os.makedirs(self.storage_path, exist_ok=True)
def generate_id(self, content_img, style_img, params):
"""生成唯一ID用于标识记录"""
# 组合图像和参数生成哈希
img_data = content_img.tobytes() + style_img.tobytes()
param_str = str(params)
unique_str = img_data + param_str.encode()
return hashlib.md5(unique_str).hexdigest()[:12]
def add_record(self, content_img, style_img, result_img, params):
"""添加新记录"""
record_id = self.generate_id(content_img, style_img, params)
# 如果达到最大容量,移除最旧的记录
if len(self.history) >= self.max_size:
oldest_id = next(iter(self.history))
self._remove_record_files(oldest_id)
self.history.pop(oldest_id)
# 保存图片到文件系统
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
record_data = {
"id": record_id,
"timestamp": timestamp,
"params": params,
"content_path": f"{self.storage_path}/{record_id}_content.png",
"style_path": f"{self.storage_path}/{record_id}_style.png",
"result_path": f"{self.storage_path}/{record_id}_result.png"
}
# 保存图片
content_img.save(record_data["content_path"])
style_img.save(record_data["style_path"])
result_img.save(record_data["result_path"])
# 添加到历史记录
self.history[record_id] = record_data
# 将新记录移到最前面(LRU特性)
self.history.move_to_end(record_id, last=False)
return record_id
def get_recent_records(self, limit=10):
"""获取最近的历史记录"""
records = []
for i, (record_id, data) in enumerate(self.history.items()):
if i >= limit:
break
records.append(data)
return records
def _remove_record_files(self, record_id):
"""删除记录对应的文件"""
if record_id in self.history:
record = self.history[record_id]
for path_key in ["content_path", "style_path", "result_path"]:
if os.path.exists(record[path_key]):
os.remove(record[path_key])
def display_history_panel(self):
"""显示历史记录面板"""
st.sidebar.markdown("---")
st.sidebar.subheader("📚 历史记录")
records = self.get_recent_records(5)
if not records:
st.sidebar.info("暂无历史记录")
return
for record in records:
with st.sidebar.expander(f"记录 {record['timestamp']}"):
# 显示缩略图
try:
result_img = Image.open(record["result_path"])
st.image(result_img, use_column_width=True)
except:
st.error("无法加载图片")
# 显示参数
st.caption(f"风格强度: {record['params'].get('style_weight', 'N/A')}")
st.caption(f"迭代次数: {record['params'].get('iterations', 'N/A')}")
# 操作按钮
col1, col2 = st.columns(2)
with col1:
if st.button("🔁 复用", key=f"reuse_{record['id']}"):
# 加载记录到当前会话
self.load_record_to_session(record)
st.rerun()
with col2:
if st.button("🗑️ 删除", key=f"delete_{record['id']}"):
self._remove_record_files(record['id'])
if record['id'] in self.history:
del self.history[record['id']]
st.rerun()
4.3 风格迁移AI核心实现
虽然完整的风格迁移模型较复杂,这里提供一个简化版的实现:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import transforms, models
class SimpleStyleTransfer:
"""简化的风格迁移实现"""
def __init__(self, device='cpu'):
self.device = device
self.content_layers = ['conv_4']
self.style_layers = ['conv_1', 'conv_2', 'conv_3', 'conv_4', 'conv_5']
self.content_weight = 1
self.style_weight = 1e6
# 加载预训练的VGG19
self.cnn = models.vgg19(pretrained=True).features.to(device).eval()
# 图像预处理
self.preprocess = transforms.Compose([
transforms.Resize(512),
transforms.ToTensor(),
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]
)
])
self.deprocess = transforms.Compose([
transforms.Normalize(
mean=[-0.485/0.229, -0.456/0.224, -0.406/0.225],
std=[1/0.229, 1/0.224, 1/0.225]
),
transforms.ToPILImage()
])
def extract_features(self, image):
"""提取图像特征"""
features = {}
x = image
for name, layer in self.cnn._modules.items():
x = layer(x)
if name in self.content_layers + self.style_layers:
features[name] = x
return features
def style_transfer(self, content_img, style_img, num_steps=100,
style_weight=0.5, progress_callback=None):
"""执行风格迁移"""
# 准备输入图像
content = self.preprocess(content_img).unsqueeze(0).to(self.device)
style = self.preprocess(style_img).unsqueeze(0).to(self.device)
# 使用内容图像作为初始输入
input_img = content.clone().requires_grad_(True)
# 提取特征
content_features = self.extract_features(content)
style_features = self.extract_features(style)
# 计算风格特征的Gram矩阵
style_grams = {}
for layer in self.style_layers:
style_feature = style_features[layer]
b, c, h, w = style_feature.size()
features = style_feature.view(c, h * w)
gram = torch.mm(features, features.t())
style_grams[layer] = gram.div(c * h * w)
# 优化器
optimizer = optim.LBFGS([input_img])
# 训练循环
step = [0]
while step[0] < num_steps:
def closure():
# 清零梯度
optimizer.zero_grad()
# 前向传播
input_features = self.extract_features(input_img)
# 计算内容损失
content_loss = 0
for layer in self.content_layers:
content_loss += F.mse_loss(
input_features[layer],
content_features[layer]
)
# 计算风格损失
style_loss = 0
for layer in self.style_layers:
input_feature = input_features[layer]
b, c, h, w = input_feature.size()
# 计算Gram矩阵
features = input_feature.view(c, h * w)
gram = torch.mm(features, features.t()).div(c * h * w)
# 计算风格损失
style_gram = style_grams[layer]
style_loss += F.mse_loss(gram, style_gram)
# 总损失
total_loss = (self.content_weight * content_loss +
style_weight * self.style_weight * style_loss)
# 反向传播
total_loss.backward()
# 更新进度
step[0] += 1
if progress_callback:
progress = int((step[0] / num_steps) * 100)
progress_callback(progress, f"迭代 {step[0]}/{num_steps}")
return total_loss
optimizer.step(closure)
# 返回处理后的图像
with torch.no_grad():
output = self.deprocess(input_img.squeeze(0).cpu())
return output
五、实战:50行代码实现可调参Demo
下面是一个完整的、可直接运行的Streamlit应用,展示了核心功能:
# app.py - 完整的50行Streamlit Demo
import streamlit as st
from PIL import Image
import numpy as np
import time
# 页面配置
st.set_page_config(
page_title="AI风格迁移演示",
page_icon="🎨",
layout="wide"
)
def simple_style_transfer(content, style, style_strength=0.5):
"""简化的风格迁移函数(实际中替换为真实模型)"""
# 这里使用简单的图像混合作为演示
time.sleep(2) # 模拟处理时间
# 调整图像尺寸一致
size = content.size
style_resized = style.resize(size)
# 简单混合
content_arr = np.array(content, dtype=np.float32) / 255.0
style_arr = np.array(style_resized, dtype=np.float32) / 255.0
# 加权混合
result_arr = content_arr * (1 - style_strength) + style_arr * style_strength
result_arr = np.clip(result_arr * 255, 0, 255).astype(np.uint8)
return Image.fromarray(result_arr)
def main():
st.title("🎨 50行代码实现AI风格迁移")
st.markdown("---")
# 侧边栏
with st.sidebar:
st.header("参数设置")
# 图片上传
content_file = st.file_uploader("上传内容图片", type=['png', 'jpg'])
style_file = st.file_uploader("上传风格图片", type=['png', 'jpg'])
# 参数调整
style_strength = st.slider("风格强度", 0.0, 1.0, 0.5, 0.1)
process_btn = st.button("开始生成", type="primary")
# 主界面
col1, col2, col3 = st.columns(3)
if content_file and style_file:
content_img = Image.open(content_file)
style_img = Image.open(style_file)
with col1:
st.subheader("原图")
st.image(content_img, use_column_width=True)
with col2:
st.subheader("风格图")
st.image(style_img, use_column_width=True)
with col3:
st.subheader("生成结果")
if process_btn:
# 显示进度
progress_bar = st.progress(0)
status_text = st.empty()
# 模拟处理过程
for i in range(1, 11):
progress_bar.progress(i * 0.1)
status_text.text(f"处理中... {i * 10}%")
time.sleep(0.2)
# 执行风格迁移
result_img = simple_style_transfer(
content_img,
style_img,
style_strength
)
# 显示结果
st.image(result_img, use_column_width=True)
status_text.success("生成完成!")
# 下载按钮
from io import BytesIO
buf = BytesIO()
result_img.save(buf, format="PNG")
st.download_button(
"下载结果",
buf.getvalue(),
"styled_image.png",
"image/png"
)
else:
st.info("点击'开始生成'按钮查看效果")
else:
st.warning("请上传内容图片和风格图片")
if __name__ == "__main__":
main()
六、工具打包:PyInstaller跨平台部署
6.1 创建打包配置文件
# build.spec - PyInstaller配置文件
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['main_app.py'], # 主程序文件
pathex=[],
binaries=[],
datas=[
('styles/*', 'styles'), # 静态文件
('models/*', 'models'), # AI模型文件
],
hiddenimports=[
'PIL', 'PIL._imaging', 'PIL._imagingtk',
'torch', 'torchvision',
'streamlit', 'streamlit_webrtc'
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
# Windows特定配置
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='AI_Art_Studio', # 可执行文件名称
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True, # 使用UPX压缩
runtime_tmpdir=None,
console=False, # 不显示控制台窗口
icon='icon.ico', # 应用图标
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
6.2 创建启动脚本
# launcher.py - 跨平台启动器
import os
import sys
import subprocess
import webbrowser
from threading import Timer
def run_streamlit_app():
"""运行Streamlit应用"""
# 获取当前目录
current_dir = os.path.dirname(os.path.abspath(__file__))
# Streamlit命令
streamlit_cmd = [
sys.executable, "-m", "streamlit", "run",
os.path.join(current_dir, "main_app.py"),
"--server.port", "8501",
"--server.headless", "true",
"--browser.serverAddress", "localhost",
"--theme.base", "light"
]
# 启动Streamlit
process = subprocess.Popen(
streamlit_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
# 等待应用启动
print("正在启动AI艺术工作室...")
# 定时打开浏览器
def open_browser():
webbrowser.open("http://localhost:8501")
Timer(3, open_browser).start()
# 等待进程结束
try:
stdout, stderr = process.communicate()
print(stdout)
if stderr:
print("错误信息:", stderr)
except KeyboardInterrupt:
process.terminate()
print("\n应用已关闭")
if __name__ == "__main__":
run_streamlit_app()
6.3 打包命令
# 创建独立可执行文件
pyinstaller --onefile --windowed --name="AI_Art_Studio" launcher.py
# 添加图标
pyinstaller --onefile --windowed --icon=icon.ico --name="AI_Art_Studio" launcher.py
# 创建安装包(Windows)
# 需要安装NSIS:makensis installer_script.nsi
# Mac应用打包
pyinstaller --onefile --windowed --name="AI\ Art\ Studio" --osx-bundle-identifier=com.aiart.studio launcher.py
# Linux打包
pyinstaller --onefile --name="ai-art-studio" launcher.py
七、高级功能扩展
7.1 多模型支持
class ModelManager:
"""多模型管理器"""
def __init__(self):
self.models = {
"fast_style": FastStyleTransfer(),
"neural_style": NeuralStyleTransfer(),
"cartoon_gan": CartoonGAN(),
"anime_gan": AnimeGAN()
}
def get_model(self, model_name):
"""获取指定模型"""
if model_name in self.models:
return self.models[model_name]
else:
return self.models["fast_style"] # 默认模型
def get_model_info(self):
"""获取所有模型信息"""
info = []
for name, model in self.models.items():
info.append({
"name": name,
"description": model.description,
"speed": model.inference_speed,
"quality": model.quality_score
})
return info
7.2 批量处理功能
def batch_processing(image_folder, style_image, output_folder):
"""批量处理图片"""
import glob
from concurrent.futures import ThreadPoolExecutor
# 获取所有图片文件
image_files = glob.glob(f"{image_folder}/*.jpg") + \
glob.glob(f"{image_folder}/*.png")
results = []
# 使用线程池并行处理
with ThreadPoolExecutor(max_workers=4) as executor:
futures = []
for img_file in image_files:
future = executor.submit(
process_single_image,
img_file,
style_image
)
futures.append(future)
# 收集结果
for future in futures:
try:
result = future.result()
results.append(result)
except Exception as e:
st.error(f"处理失败: {e}")
return results
八、性能优化建议
8.1 缓存优化
from functools import lru_cache
import hashlib
@st.cache_resource
def load_model(model_name="fast_style"):
"""缓存模型加载"""
# 模型加载逻辑
return model
@st.cache_data(ttl=3600)
def process_image_cached(content_img, style_img, params):
"""缓存处理结果"""
# 使用参数生成缓存键
cache_key = generate_cache_key(content_img, style_img, params)
# 处理逻辑
return result
def generate_cache_key(content_img, style_img, params):
"""生成缓存键"""
content_hash = hashlib.md5(content_img.tobytes()).hexdigest()
style_hash = hashlib.md5(style_img.tobytes()).hexdigest()
params_hash = hashlib.md5(str(params).encode()).hexdigest()
return f"{content_hash[:8]}_{style_hash[:8]}_{params_hash[:8]}"
8.2 GPU加速
def setup_gpu_acceleration():
"""设置GPU加速"""
import torch
device = "cpu"
gpu_info = {}
if torch.cuda.is_available():
device = "cuda"
gpu_info = {
"name": torch.cuda.get_device_name(0),
"memory": torch.cuda.get_device_properties(0).total_memory / 1e9,
"available": True
}
elif hasattr(torch.backends, 'mps') and torch.backends.mps.is_available():
device = "mps" # Apple Silicon
gpu_info = {
"name": "Apple M1/M2 GPU",
"available": True
}
return device, gpu_info
九、部署与监控
9.1 Docker容器化部署
# Dockerfile
FROM python:3.9-slim
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
libgl1-mesa-glx \
libglib2.0-0 \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖文件
COPY requirements.txt .
# 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 创建非root用户
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser
# 暴露端口
EXPOSE 8501
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8501/_stcore/health || exit 1
# 启动命令
ENTRYPOINT ["streamlit", "run", "main_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
9.2 监控与日志
import logging
from datetime import datetime
def setup_logging():
"""设置日志系统"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(f'logs/app_{datetime.now().strftime("%Y%m%d")}.log'),
logging.StreamHandler()
]
)
return logging.getLogger(__name__)
class PerformanceMonitor:
"""性能监控器"""
def __init__(self):
self.metrics = {
"processing_time": [],
"memory_usage": [],
"user_actions": []
}
def track_processing_time(self, func):
"""装饰器:跟踪处理时间"""
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
duration = end_time - start_time
self.metrics["processing_time"].append(duration)
return result
return wrapper
def get_performance_report(self):
"""获取性能报告"""
if not self.metrics["processing_time"]:
return {"average_time": 0, "total_requests": 0}
avg_time = sum(self.metrics["processing_time"]) / len(self.metrics["processing_time"])
return {
"average_processing_time": round(avg_time, 2),
"total_requests": len(self.metrics["processing_time"]),
"min_time": round(min(self.metrics["processing_time"]), 2),
"max_time": round(max(self.metrics["processing_time"]), 2)
}
十、完整项目结构
ai-art-studio/
├── app.py # 主应用文件
├── requirements.txt # 依赖列表
├── README.md # 项目说明
├── launcher.py # 启动器
├── build.spec # PyInstaller配置
├── icon.ico # 应用图标
├── icon.png # Mac图标
├── Dockerfile # 容器化配置
├── docker-compose.yml # 多容器编排
├── .streamlit/ # Streamlit配置
│ └── config.toml
├── src/ # 源代码
│ ├── __init__.py
│ ├── models/ # AI模型
│ │ ├── style_transfer.py
│ │ ├── model_manager.py
│ │ └── pretrained/
│ ├── utils/ # 工具函数
│ │ ├── image_utils.py
│ │ ├── cache.py
│ │ └── progress.py
│ ├── ui/ # 界面组件
│ │ ├── sidebar.py
│ │ ├── main_panel.py
│ │ └── history.py
│ └── services/ # 业务逻辑
│ ├── processing.py
│ ├── history_service.py
│ └── export_service.py
├── static/ # 静态资源
│ ├── styles/
│ │ └── custom.css
│ ├── images/
│ └── models/ # 预训练模型
├── tests/ # 测试代码
│ ├── test_models.py
│ ├── test_ui.py
│ └── test_utils.py
├── logs/ # 日志文件
├── history_storage/ # 历史记录存储
└── outputs/ # 输出目录
结语:零代码AI应用的未来
通过本文的详细介绍,我们完成了一个完整的AI风格迁移平台的开发。从界面设计到核心功能实现,再到打包部署,我们展示了如何用Streamlit快速构建专业级的AI应用。
这个项目的亮点在于:
- 零代码理念:用户无需任何编程知识即可使用
- 实时交互:SSE技术提供了流畅的用户体验
- 历史管理:智能缓存和LRU策略优化了资源使用
- 跨平台部署:一次开发,多平台运行
随着AI技术的普及,这种零代码的AI应用开发模式将变得越来越重要。它降低了AI技术的使用门槛,让更多人能够享受AI带来的便利和创新。
未来扩展方向:
- 集成更多AI模型(超分辨率、图像修复等)
- 添加协作功能,多人同时编辑
- 云服务集成,实现跨设备同步
- API开放,支持第三方集成
希望这个项目能为你打开AI应用开发的新思路。无论是作为学习项目、原型验证,还是商业产品的基础,这个框架都能为你提供强大的支持。
3099

被折叠的 条评论
为什么被折叠?



