<< 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つの回転ステップを選択してください。")