制作物
洋服を管理できるWebアプリ。洋服をトップスとボトムスに分けて保管でき、コーディネートの登録もできる。また、画像はトリミングや背景を透過して保存できる。
アプリのURL
使い方
アカウントを作成しログインをしたら「Submit」というボタンをクリックして画像を登録できます。登録されたトップスとボトムスの画像をそれぞれクリックするとページ下部にクリックされた画像が新たに表示されるので、その下の「コーデを登録」ボタンを押してコーディネートを登録できます。登録したコーディネートは「Outfit」ページから閲覧できます
使用技術
・Python
・JavaScript
・Flask
・MySQL
・Google Cloud Storage
制作期間
約1ヶ月(2023年4月~5月)
作った理由
外出先で洋服を購入する際に、既に所持しているものと同じ種類のアイテムを再度購入してしまうことがしばしばありました。そこで、持っている洋服を一箇所に整理できるアプリケーションを開発することで、この問題に対策を打つことができると考えました。
工夫した点
GrabCut法の導入
アプリケーションの設計段階から、画像の背景を透過させて洋服だけを表示する機能を付けることを目指していました。しかしながら、既存のAPIを使用すると画像処理に時間がかかり、またコストも高くなるため、代替手段を模索していました。その結果、OpenCVを使ったGrabCut法による前景と背景の分離を採用することにし、外部のAPIに頼らずに背景の透過を実現することが可能となりました。
最も苦労した点
エラーメッセージが表示されない不具合の解決
画像が適切に表示されないという不具合が発生しましたが、エラーメッセージが出てこなかったため、原因の特定に時間がかかってしまいました。そこで、デベロッパーツールを使って調査したところ、Data URIスキームが二重に存在することを発見しました。具体的には、JavaScriptとPythonの両方でエンコードが行われており、それが重複していたというものです。システム全体を把握し、本質的な部分を確認することの重要性を再認識する機会となりました。
改善点
画面表示の遅さ
Google Cloud Storageに画像データを保存しているためか、画面が遷移してからに画像が完全に表示されるまで時間がかかってしまいます。
改善案
キャッシュを利用できるようにする
画像を表示する際、Data URIスキームにバイナリ形式で取得したデータをくっつけていますが、この方法ではキャッシュが無効化されてしまうため直接URLから表示するようにする必要があります。
別のホスティングサービスを利用するか、有料版に移行する
開発環境では画面表示の遅さは見られないため、pythonanywhereの無料プランの通信が遅いことも画面表示が遅い原因の一つとして考えられます。
DB設計
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), nullable=False, unique=True)
password = db.Column(db.String(100))
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(30), nullable=False)
detail = db.Column(db.String(100))
category = db.Column(db.Enum('tops', 'bottoms'))
user_id = db.Column(db.Integer, nullable=False)
image_id = db.Column(db.Integer, db.ForeignKey('image.id')) # Imageモデルとの関連性を定義
class Image(db.Model):
id = db.Column(db.Integer, primary_key=True)
object_name = db.Column(db.String(256), nullable=False) # GCSのオブジェクト名
public_url = db.Column(db.String(256), nullable=False) # Google Cloud Storageの公開URL
user_id = db.Column(db.Integer, nullable=False)
post = db.relationship('Post', backref='image', uselist=False) # Postとの逆参照を定義
class OutfitImage(db.Model):
id = db.Column(db.Integer, primary_key=True)
tops_image_id = db.Column(db.Integer, nullable=False)
bottoms_image_id = db.Column(db.Integer, nullable=False)
user_id = db.Column(db.Integer, nullable=False)
GitHubのレポジトリ