Pythonを使って、複数枚、連写画像からの合成処理を行って行きます。過去の記事ではスマホのような小さいセンサで撮影した画像からのノイズ除去を目的としてきましたが、今回はノイズの除去と同時に読めない文字も読めるようになったサンプルがあったので、その例を紹介したいと思います。
いわゆる超解像です。意図せず超解像ができてしまいました。
超解像
いわゆるクラシックな超解像というのは、複数枚の低解像度画像を組み合わせて、1枚では表現できないような周波数の高い、高解像度な画像を作り上げる技術です。学術的には色々複雑でとても解説できるものではないのですが、考え方としては昔からある技術です。最近では1枚からその高解像度画像を作るものや、機械学習を駆使して作り上げるもあり、(むしろそっちが主流?)必ずしも入力が複数枚である必要がないものもあるようですが、クラシックなそれは複数枚が基本です。
撮影された位相(位置)の異なる画像を複数枚組み合わせるのですが、結果として“手振れのある複数の静止画”がそれにあたるので、原理的にはより解像度の高い画像データへの復元が可能になるはずです。(もちろん1枚1枚の写真はぶれてないことを前提としてます。)
例えばこんな感じ、とある被写体(この場合「あ」)を4回撮影したとします。
4連写したのですが、左、下、左下にカメラがぶれて撮影されると、撮影された画像は微妙にシフトします。そのイメージがコレ、
左側の4枚の解像度の低い、微妙に位置がずれた「あ」が取れています。カメラが下にぶれるということは、撮影された画像は上にシフトします。ややこしいですが、ちょっと想像すると分かります。このようにちょっとずつずれた4枚の画像のそれぞれの画素をつなぎ合わせて1枚にすると、右側の1枚の解像度の高い「あ」が出来上がります。
赤でくくった4画素をそのままつなぎ合わせて高解像度化していますが、実際にはこんなにきれいに行くことはないです。イメージです。このように微妙にシフトした画像が複数枚あれば失われた情報が戻ってくる。という仕組みです。
手振れ画像の合成
これまでの記事でも、PythonとOpenCVを使って、回転、シフトを伴う複数の連写画像の簡単な合成は色々試してきました。意外とスマホの画像からでも位置合わせはうまく行き、局所的なマッチングを取ることでぶれなく複数枚合成ができ、ノイズ除去を実現できています。
この記事でPythonのコードも載せています。今回はこのコードのまま動かしてみました。
上で示したような、手振れが起こっている状況での長秒露光を模したもので、ノイズ除去が主な目的でしたが、位置合わせからの合成なので、ここで説明した「あ」の様に、ある程度失われた情報(解像力)が戻る可能性があります。
もともと超解像とは、解像度を上げる→画素数が増える。という処理ですが、スマホのレンズと小さなセンサの高密度画素で、細かい文字を解像できるわけはありはしません。複数枚使って、潰れてしまった文字を元に戻す感じでも十分効果は実感できると思います。
少し細かい文字のような被写体を試してみようと思います。
結果
選んだのはこんな被写体。暗がりの自販機です。細かい文字がいっぱいです。
iPhoneSEで撮影したものです。単体ショットでの手振れは起きてません。それなりにきれいに映っていますが、拡大すると、
こんな感じです。ドラクエを知っていれば右側は「はい」「いいえ」だと認識できそうですが、ぱっと見はわかりません。そこで8枚からのマルチショットのノイズ除去をかけてみます。
ぎりぎり「かいふく」できそうです。他にも、
ぎりぎり故障・お問い合わせができそうです。飲み物の文字もかなり読みやすくなっています。暗部ノイズ系は複数枚使えば復元できる文字がありそうです。ノイズ除去で文字が読めるようになりました。
調子に乗って、昼間の小さい文字がどうなるか試してみました。これもiPhoneSEの写真12枚をソースとして合成させてみました。
とある駐車場の1シーンです。奥に駐車場の案内が書いてあります。これが解像できたらかっこいいのですが、
さすがにこれだけ小さいものは駄目ですね。もちろんノイズなくなり、全般きれいな画像に復元はできているのですが、文字が読めるほどの効果はありません。文字がまだらに、部分的にぼけています。何か撮影後の後処理してますね。rawから行けば復元できるかもしれませんが、この時rawはとっていなかったぁ。
もともとセンサが解像できていないような文字に対しては復元の効果は見込めないようです。カメラ側のノイズ除去処理により失われてしまったような文字であれば、ある程度復元できるようです。真面目に処理すればもう少しなんとかなるのかなぁ…。
まとめ
スマホのような適当なカメラで撮影した、複数枚の連写合成により疑似的な長秒露光をしたかっただけで、別に超解像を目的としたわけではないんですけどね。処理としても何らそれを意識したコードはないですし。結果として被写体や撮影条件によっては、読めない文字が読めるようになる、解像度の復元の効果もあるということで、記事に残しておきました。別に画素数が増えるわけじゃないですけど。(まぁもともとスマホの画素数なんざあってないようなもんですが。)
もう少しまじめにコードを書けば、(1画素未満でマッチングを取るとか)もう少し解像度の復元効果を出せるような気もしますが、今回もあくまでカジュアルに、あまり頑張らずに最大限の効果を出せたかなと思います。コードは過去記事を見てください。今回の検証はコードそのまんまです。
コメント