昨年10月に自作スキャナーを完成させこれまでに数十本のフィルムをデジタル化したのですが、気になったのがフィルム上の傷や埃がノイズとして入りこんでしまう点でした。
年末の休みを利用し、スキャンした画像の連続自動修復を行うプログラムを書いてみました。作業は基本パソコン上で行いプログラミング言語としてpythonを使用。画像処理ライブラリOpenCVで動かしていきます。
時系列を追った試行錯誤は別枠で詳述。本稿では現時点までの成果をご紹介していきます。
修復対象は1928年公開のジャン・ルノワール作品『城下町の決闘』。スキャンをしてみたところ、以前の映写に由来する深い傷が目立ちました。旧所有者があまり良くない映写機を使っていたと思われ、フィルムの各コマのほぼ同じ位置に大きな傷が入っています。
その他にも埃や繊維と思われるゴミの影が黒く映りこんでいます。それでも画像一枚ならフォトショップで何とかなるのですが、総コマ数が数千~数万となる映画フィルム修復ではあまり現実的とは言えません。或る程度のコマ数を一括処理できるプログラムを書く方が早そうです。
試行錯誤の末、以下の4ステップで修復を行う流れを考えてみました。
【ステップ1:深い傷の一括修復】複数枚の画像に繰り返し現れる傷にOpenCVの「インペイント」で一括修正をかける。
『城下町の決闘』から連続する画像10枚を選んでみました。
まずは各コマの右側に多く見られる斜めの傷に修正をかけていきます。黒地に手描きの白で傷を示したマスク画像を一枚用意します。
OpenCVの「INPAINT_TELEA」関数を使い、ファイル名の連番で自動修復を行う設定をかけながらマスク画像の白い部分を画像の周辺データから修復していきます。
白いパッチ部分をもう少し広めに取れば良かったですね。
【ステップ2:ノイズの一括除去】続いて、スキャン画像に個別で現れてくる黒い点状のノイズ(埃やゴミ)を認識させ一括で除去していきます。ステップ1同様にマスク画像と「INPAINT_TELEA」関数を使用していくのですが、先のステップではマスク画像が手描きだったのに対し、今回は画面上の一定の黒さ以上の部分を色抽出プログラムで抜き出し、各コマごとにマスク画像を自動生成、自動修復していきます。
画面のあちこちに発生していたノイズの点々をある程度除去できました。
【ステップ3:薄い傷の個別修復】ステップ1では大きな傷、ステップ2で細かなゴミの影を除去した後、今度はコマ個別に発生している薄く細い縦線(映写機由来の傷)を消していきます。OpenCVの線描画機能(Line関数)を使用し、画面上の細かな傷をなぞった跡をマスク画像として保存、三度「INPAINT_TELEA」関数でノイズ除去を行います。細かな傷が対象ですので描線はステップ1より一段階細くしています。
【ステップ4:最終調整】メイン作業はここまでで終了。最後は明度や輝度など微修正を施していきます。OpenCVでガンマ輝度を0.9に下げ、完成画像をオリジナルと比べてみます。
課題は山積みで精度もまだ上げられそう。でも今のプログラミング能力だと1週間で組めるのはこの辺まででした。
もう一枚もこの程度まで回復。「綺乃九五式スキャナー」と同様、次段階ではユーザーインターフェイスを自作しモニター画面を見ながらボタンでステップ1~4の作業を行えるようしていきます。