🎇

【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: 席替えを実行!

最後に、ペアになった通りにピクセルを配置していきます。

  1. まっさらなキャンバスを用意します。
  2. Bの「1番薄い色のピクセル」を、Aの「1番薄い席(場所)」に置きます。
  3. Bの「2番目に薄い色のピクセル」を、Aの「2番目に薄い席(場所)」に置きます。
  4. これを全ピクセル分繰り返します。

たったこれだけで、入力画像Bのピクセルたちが、目標画像Aの構造そっくりに並び変わる、という仕組みです。アニメーションは、この席替えの途中経過をコマ送りで表示している、というわけです。

おわり

参考までにプログラムをGithubで公開したので良かったらスターをつけてください!!

Discussion