こんにちは、Tech Samuraiです!
今回は、一枚の画像にまとめられた複数のアイコン(カード)を、それぞれ個別のファイルに自動で分割するPythonスクリプトを開発した際の、試行錯誤の全記録を共有します。
最初は「画像を均等に切るだけで簡単だろう」と高を括っていましたが、最終的に満足のいく結果を得るまでには、いくつかの「壁」と「発想の転換」が必要でした。これは、単純な問題に見えて、実は奥深い画像処理の世界を探検する物語です。
Step 1: 最初のアイデア – Pillowによる単純なグリッド分割
目標: 1枚の画像に3行2列で配置された6つのアイコンを、個別のファイルに分割する。
まず最初に試したのは、Pythonの画像処理ライブラリ`Pillow`を使い、画像を単純にグリッドで6等分する方法です。画像全体のサイズを取得し、幅を2で、高さを3で割って、機械的に切り出しました。
課題: この方法では、各アイコン間の余白やレイアウトの微妙なズレを考慮できませんでした。結果、アイコンが途中で切れたり、不要な余白が多く含まれたりと、精度が低く、使い物になりませんでした。
Step 2: 発想の転換 – OpenCVによる輪郭検出
単純な分割がダメなら、画像の中身を「認識」すれば良い。そう考え、より高度な画像処理ライブラリ`OpenCV`を導入しました。アイコンの輪郭を自動で検出し、その部分だけを切り出す作戦です。
- 画像をグレースケールに変換し、二値化処理で背景(白)とアイコン(色付き)を明確に分離。
cv2.findContours`
でアイコンの輪郭を検出し、それを囲む四角形(バウンディングボックス)を取得して切り出す。
課題: この方法は一歩前進でしたが、各アイコンの形状が異なるため、検出される四角形のサイズがバラバラになりました。結果として、切り出される画像の大きさが統一されず、不揃いになってしまいました。
Step 3: さらなる転換 – 「カード領域」の検出へ
アイコン自体の形がバラバラなら、全てのアイコンが乗っている「角の丸い白いカード」を検出すれば、サイズが揃うのではないか?と考えました。
cv2.threshold`
の閾値を微調整し、画像全体の真っ白な背景と、カード部分のわずかに異なる白とを区別させ、カードの輪郭を検出。しかし、この方法でも、輪郭検出のわずかな誤差により、切り出されるカードの大きさが数ピクセル単位で異なってしまう問題は解決しませんでした。
Step 4: 最終解決策 – 「レイアウト解析」による均一サイズ切り出し
ここで、私はプロジェクトの重要な前提条件に立ち返りました。「**画像内のカードは、常に同じ配置・同じサイズである**」ということです。このルールを利用しない手はありません。
最終的な解決策は、個々の輪郭の精度に頼るのではなく、**全体のレイアウトから「理想的なカードサイズ」を逆算する**アプローチです。
- まず、Step 3の方法で、6枚全てのカードのおおよその位置とサイズを検出します。サイズは少しずつ違っていても構いません。
- 検出した6つの矩形の幅と高さから、カードの「平均サイズ」(平均幅・平均高さ)を算出します。これが、私たちが切り出すべき「理想のサイズ」です。
- 次に、検出した各矩形の中心座標を計算します。
- 最後に、各カードの「中心座標」と、算出した「平均サイズ」を使い、**全てのカードを完全に同じ大きさで**中心から切り出します。
成果: この方法により、輪郭検出のわずかな誤差は中心座標の特定にのみ影響し、最終的な切り出しサイズは計算された統一サイズで行われるため、出力される全画像のサイズが完璧に一致するようになりました。これこそが、求めていた理想的な結果です!
Step 5: 仕上げ – フォルダ内の一括処理機能
コアロジックが完成したので、最後にスクリプトの利便性を高めます。Pythonの`os`および`glob`ライブラリを使い、指定したフォルダ内にある全ての画像を一括で処理する機能を追加しました。分割後の画像は、元のファイル名ごとに作成されたサブフォルダ内に保存されるようにし、整理しやすくしました。
これにより、大量の画像を手作業なしで一度に処理できる、実用的なツールが完成しました。
完成したコードとリポジトリ
この一連の「アジャイルな」開発プロセスを経て完成したスクリプトの全コードは、ImgProcKit (Image Processing Kit) と名付けた、以下のGitHubリポジトリで公開しています。
- GitHubリポジトリ: ImgProcKit – Image Processing Utilities
将来的には、今回の画像分割スクリプト以外にも、様々な画像処理の便利ツールをこのリポジトリに追加していく予定です。
まとめ
「画像を6つに切る」という単純なタスクから始まったこのプロジェクトは、最終的に「複数の不正確な情報から、統計的に最も確からしい答え(平均サイズ)を導き出し、それを元に均一な結果を得る」という、データ解析にも通じる、非常に洗練されたアプローチにたどり着きました。
プログラミングの面白さは、このように試行錯誤を繰り返し、よりエレガントな解決策へとたどり着く、そのプロセスそのものにあるのかもしれません。
【Pythonで脳トレアプリ開発】ロジックを進化させろ!「色読み」グリッド作成の全思考プロセス
コメント