<< 2024-08-26 | 2024-08-28 >>
DailyNote
- データ拡張ツールがあんまり落ちてないので、とりあえず回転だけさせるツールを作った。
import streamlit as st
import os
import zipfile
from PIL import Image
import tempfile
import io
import base64
def rotate_image(image, angle):
width, height = image.size
new_size = int(((width ** 2 + height ** 2) ** 0.5))
result = Image.new('RGBA', (new_size, new_size), (0, 0, 0, 0))
paste_x = (new_size - width) // 2
paste_y = (new_size - height) // 2
result.paste(image, (paste_x, paste_y))
result = result.rotate(angle, expand=True)
bbox = result.getbbox()
result = result.crop(bbox)
return result
def process_images(uploaded_files, rotation_steps):
processed_images = []
total_files = len(uploaded_files)
progress_bar = st.progress(0)
status_text = st.empty()
with tempfile.TemporaryDirectory() as temp_dir:
for i, uploaded_file in enumerate(uploaded_files):
status_text.text(f"ファイル {i + 1}/{total_files} を処理中...")
if uploaded_file.name.endswith('.zip'):
with zipfile.ZipFile(uploaded_file, 'r') as zip_ref:
zip_ref.extractall(temp_dir)
else:
img = Image.open(uploaded_file)
img.save(os.path.join(temp_dir, uploaded_file.name))
progress_bar.progress((i + 1) / total_files)
with tempfile.TemporaryDirectory() as output_dir:
total_images = len(
[f for f in os.listdir(temp_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp'))])
for i, filename in enumerate(os.listdir(temp_dir)):
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp')):
status_text.text(f"画像 {i + 1}/{total_images} を回転中...")
img_path = os.path.join(temp_dir, filename)
img = Image.open(img_path)
if img.mode != 'RGBA':
img = img.convert('RGBA')
for step in rotation_steps:
angle = step * 22.5
rotated_img = rotate_image(img, angle)
save_filename = f"rotated_{step}_{os.path.splitext(filename)[0]}.png"
save_path = os.path.join(output_dir, save_filename)
rotated_img.save(save_path, "PNG")
thumbnail = rotated_img.copy()
thumbnail.thumbnail((100, 100))
processed_images.append((save_filename, thumbnail))
progress_bar.progress((i + 1) / total_images)
status_text.text("ZIPファイルを作成中...")
output_zip = "processed_images.zip"
with zipfile.ZipFile(output_zip, 'w') as zipf:
for root, dirs, files in os.walk(output_dir):
for file in files:
zipf.write(os.path.join(root, file), file)
status_text.text("処理完了!")
progress_bar.progress(1.0)
return output_zip, processed_images
st.set_page_config(layout="wide")
st.title("画像回転ツール (1/16回転)")
# サイドバーに回転設定を配置
with st.sidebar:
st.header("回転設定")
all_steps = list(range(16))
rotation_steps = st.multiselect(
"回転ステップを選択してください",
options=all_steps,
default=[4],
format_func=lambda x: f"{x}/16回転 ({x * 22.5}度)"
)
uploaded_files = st.file_uploader("画像またはZIPファイルをアップロードしてください", accept_multiple_files=True)
if st.button("処理開始"):
if uploaded_files and rotation_steps:
output_zip, processed_images = process_images(uploaded_files, rotation_steps)
with open(output_zip, "rb") as file:
st.download_button(
label="処理済み画像をダウンロード",
data=file,
file_name="processed_images.zip",
mime="application/zip"
)
# st.header("処理済み画像のプレビュー")
# # # サムネイルを3列で表示
# cols = st.columns(3)
# for idx, (filename, thumbnail) in enumerate(processed_images): # with cols[idx % 3]: # # サムネイルの背景を設定
# st.markdown(
# f""" # <div style=" # background-color: #f0f0f0; # border: 1px solid #ddd; # border-radius: 5px; # padding: 10px; # margin-bottom: 10px; # text-align: center; # "> # <img src="data:image/png;base64,{base64.b64encode(thumbnail.tobytes()).decode()}" style="max-width: 100%; height: auto;"> # <p style="margin-top: 5px; font-size: 12px;">{filename}</p> # </div> # """, # unsafe_allow_html=True # )
os.remove(output_zip)
else:
st.warning("ファイルをアップロードし、少なくとも1つの回転ステップを選択してください。")