【Python】ピクセルの位置を入れ替えて画像を別の画像にしてみた
概要
本記事では、ある画像(例: オーロラの写真)を、別の画像(例: オバマ大統領)の構造を持つように変形させるモーフィング・アニメーションをPythonで作成する手法を紹介します。
このアルゴリズムの面白い点は、ピクセルの色を一切変えず、その位置を入れ替えるだけで目標画像を再構成する点です。ピクセルの対応付けには「輝度」の順位を利用し、直感的で美しいアニメーションを生成します。完成したコードと、その背景にある「最適輸送」などの考え方についても触れていきます。
![]()
はじめに
最近TLを眺めていたら、任意の画像をオバマ大統領に変換するプログラムを見かけました。そのアイデアに触発され、「ピクセルを移動させるだけ」という独自のアプローチで、同様の画像モーフィングプログラムをPythonで実装してみることにしました。
本記事では、その開発過程で作成したアルゴリズムと、完成したプログラムについて解説します。
アルゴリズムの仕組み
このプログラムのアイデアはとてもシンプルで、例えるなら「ピクセルたちの大規模な席替え」です。
入力画像Bのピクセルたちに、目標画像Aが用意した座席表通りに座ってもらうことで、最終的な画像を完成させます。
Step 1: 2つの「名簿」を用意する
まず、正確な席替えをするために、2つの画像からそれぞれ「名簿」を作ります。話が簡単になるように、両方の画像をグレースケール(白黒)にして、「色の濃さ」だけに着目します。
-
目標画像Aの名簿(座席表): 「どの場所が、どれくらい濃いか」を記録します。
場所(x1, y1) は 濃さ10
場所(x2, y2) は 濃さ200
... -
入力画像Bの名簿(出席簿): 「どのピクセルが、どれくらい濃いか」を記録します。
ピクセル(赤色) は 濃さ210
ピクセル(青色) は 濃さ15
...
Step 2: 名簿を「濃さ」の順に並び替える
次に、作った2つの名簿を、それぞれ**「濃さ」が薄い順(または濃い順)にソート**します。
これで、「Aの1番薄い席」と「Bの1番薄いピクセル」、「Aの2番目に薄い席」と「Bの2番目に薄いピクセル」...という風に、全てのピクセルと座席のペアが自動的に決まります。
Step 3: 席替えを実行!
最後に、ペアになった通りにピクセルを配置していきます。
- まっさらなキャンバスを用意します。
- Bの「1番薄い色のピクセル」を、Aの「1番薄い席(場所)」に置きます。
- Bの「2番目に薄い色のピクセル」を、Aの「2番目に薄い席(場所)」に置きます。
- これを全ピクセル分繰り返します。
たったこれだけで、入力画像Bのピクセルたちが、目標画像Aの構造そっくりに並び変わる、という仕組みです。アニメーションは、この席替えの途中経過をコマ送りで表示している、というわけです。
おわり
参考までにプログラムをGithubで公開したので良かったらスターをつけてください!!
Discussion