web-dev-qa-db-ja.com

画像のぼけ除去

Python=で画像のブレを除去しようとしていますが、いくつかの問題が発生しています。ここに私が試したことがありますが、私はこのトピックの専門家ではないことに注意してください。ポイントスプレッド関数がわかっている場合は、デコンボリューションを実行するだけで画像をぼかすことができるはずです。しかし、これは機能していないようで、私が愚かなことをしているのか、それともマークニューマンの計算物理学の本(Pythonを使用)では、問題7.9のこの主題に触れています。この問題では、ガウスの点像分布関数(psf)を使用して意図的にぼかした画像を提供し、この問題の目的は、ガウスを使用して画像のブレを除去することです。これは、ぼやけた画像の2D FFTをpsfの2D FFTで除算し、逆変換を行うことで達成されます。

この問題を拡大するために、意図的に焦点が合っていないカメラで撮影された実際の画像をぼかしたいと思いました。それで、私はカメラをセットアップして、2セットの写真を撮りました。写真の最初のセットに焦点が当てられました。 1つ目は、完全に暗い部屋にある非常に小さなLEDライトで、2つ目は、(フラッシュを使用して)テキストが書かれた紙でした。次に、距離などを変更することなく、カメラのフォーカス設定を変更して、テキストの焦点が非常にぼやけるようにしました。次に、フラッシュを使用してテキストの写真を撮り、LEDの2番目の写真(フラッシュなし)を撮りました。これがぼやけた画像です。

Blurred Text

Blurred Point Light Source

今、私の理解によれば、ぼやけた点光源の画像は点像分布関数であるはずであり、それで私はそれを使って自分の画像をぼかすことができるはずです。問題は、そうすると、ノイズのように見える画像が表示されることです。少し調べてみると、デコンボリューション技術を使用する場合、ノイズが大きな問題になり得るようです。しかし、正確な点像分布関数であると私が信じるものを測定したので、ここでノイズが問題になることに驚きます。

私が試みたのは、psf変換の小さな値(イプシロン未満)を1またはイプシロンで置き換えることで、これをイプシロンの非常に広い範囲の値で試しました。これにより、ノイズだけでなく、ぼやけたバージョンのイメージでもないイメージが生成されました。元の(ぼやけていない)画像の奇妙でぼやけたバージョンのように見えます。これが私のプログラムの画像です(このプログラムでは使用されなかったsigmaの値は無視できます)。

enter image description here

私はノイズの問題に対処していると思いますが、なぜなのか、どうすればいいのかわかりません。助言をいただければ幸いです(私はこの分野の専門家ではないことを覚えておいてください)。

この時点ではあまり関係がないと思うので、意図的にコードを投稿していません。しかし、誰かがそれが有用だと思ったら、喜んでそうします。同じ手法を使用しており、既知の点像分布関数がある場合(元のフォーカス画像のFFTをアウトオブFFTで除算する場合など)に問題なく動作するため、プログラミングの問題ではないと思います-画像をフォーカスしてから逆変換します)。実験的に測定した点像分布関数を使用できない理由がわかりません。

8
DJElectric

残念ながら、あなたが解決しようとしていた問題は、予想よりも難しいものです。 4つのパートで説明しましょう。最初のセクションは、フーリエ変換に慣れていることを前提としています。

  1. 単純なデコンボリューションではこの問題を解決できないのはなぜですか。
  2. 画像のブレ除去を実行する方法の概要。
  3. FFTによるデコンボリューションとそれが悪いアイデアである理由
  4. デコンボリューションを実行する別の方法

しかし、最初に、いくつかの表記:

[〜#〜] i [〜#〜]を使用して画像を表し、[〜#〜] k [〜#〜]を使用して畳み込みカーネルを表します。 I * Kは画像のたたみ込みです[〜#〜] i [〜#〜]カーネルを使用した場合[〜#〜] k [〜# 〜][〜#〜] f [〜#〜](I)は画像の(n次元)フーリエ変換です[〜#〜] i [〜#〜]および[〜#〜] f [〜#〜](K)は、たたみ込みカーネルのフーリエ変換[ 〜#〜] k [〜#〜](これは、点像分布関数、またはPSFとも呼ばれます)。同様に、Fiは逆フーリエ変換です。

単純なデコンボリューションでこの問題を解決できない理由:

ぼやけた画像Ib = I * Kのフーリエ変換Ib[〜 #〜] k [〜#〜]。ただし、レンズぼかしは畳み込みぼかし操作ではありません。これは、ぼかしカーネル[〜#〜] k [〜#〜]が、撮影したオブジェクトまでの距離に依存する、変更された畳み込みぼかし操作です。したがって、カーネルはピクセルごとに変化します。

イメージの位置で正しいカーネルを測定したので、これはイメージの問題ではないと考えるかもしれません。ただし、遠くにある画像の一部が近くにある画像の一部に影響を与える可能性があるため、これは当てはまらない場合があります。この問題を解決する1つの方法は、表示されるのが用紙だけになるようにイメージをトリミングすることです。

FFTによるデコンボリューションが悪い考えである理由:

たたみ込み定理は次のように述べていますI * K = Fi[〜#〜] f [〜#〜](I) [〜#〜] f [〜#〜](K))。この定理は、画像がある場合、Ib = I * Kたたみ込みカーネルによってぼやけているという合理的な仮定につながります[〜#〜] k [〜#〜] =、次に計算によってブレのない画像を回復できますI =([〜#〜] f [〜#〜](Ib)/ [〜#〜] f [〜#〜](K))

なぜこれが悪い考えなのかを見る前に、畳み込み定理が何を意味するのか直感的に理解したいと思います。画像をカーネルでコンボリューションする場合、それは画像の周波数成分を取り、それをカーネルの周波数成分で要素ごとに乗算することと同じです。

ここで、FFTで画像をデコンボリューションすることが難しい理由を説明しましょう。デフォルトでは、ぼかしは高周波の情報を削除します。したがって、[〜#〜] k [〜#〜]の高周波はゼロに近づく必要があります。この理由は、ぼかされたときに[〜#〜] i [〜#〜]の高周波情報が失われるためです-したがって、-の高周波成分はIbはゼロに向かう必要があります。そのためには、[〜#〜] k [〜#〜]の高周波成分もゼロに向かう必要があります。

[〜#〜] k [〜#〜]の高周波成分がほぼゼロであるため、-Ibの高周波成分はFFTでデコンボリューションすると、大幅に増幅されます(ほぼゼロで除算されるため)。これは、ノイズのない場合の問題ではありません。

しかし、騒々しい場合には、これが問題です。この理由は、ノイズは定義上、高周波情報であるためです。したがって、デコンボリューションIbを実行しようとすると、ノイズはほぼ無限に増幅されます。これがFFTによるデコンボリューションが悪い考えである理由です。

さらに、FFTベースのたたみ込みアルゴリズムが境界条件をどのように処理するかを考慮する必要があります。通常、画像を畳み込むと、解像度は多少低下します。これは望ましくない動作なので、画像外のピクセルのピクセル値を指定する境界条件を導入します。そのような境界条件の例は

  1. 画像の外側のピクセルは、画像内の最も近いピクセルと同じ値を持っています
  2. 画像の外側のピクセルの値は一定です(例:0)
  3. 画像は周期的な信号の一部であるため、一番上の行の上のピクセルの行は一番下のピクセルの行と等しくなります。

多くの場合、最終的な境界条件は1D信号にとって意味があります。ただし、画像の場合はほとんど意味がありません。残念ながら、畳み込み定理は周期的な境界条件が使用されることを指定しています。

これに加えて、FFTベースの反転法は、反復法(勾配降下法やFISTAなど)よりも、誤ったカーネルに対して非常に敏感であるようです。

デコンボリューションを実行する別の方法

すべての画像にノイズが含まれ、デコンボリューションによってノイズが増えるため、すべての希望が失われたように思われるかもしれません。ただし、デコンボリューションを実行する反復的な方法があるため、これは当てはまりません。まず、最も簡単な反復法を紹介します。

しましょう I ||²[〜#〜] i [〜#〜]のすべてのピクセルの2乗和になります。方程式を解く

Ib = I * K

[〜#〜] i [〜#〜]に関しては、次の最適化問題を解くことと同じです:

最小L(I) =最小|| I * K-Ib ||²

[〜#〜] i [〜#〜]に関して。 [〜#〜] l [〜#〜]の勾配は次のように与えられるため、これは勾配降下法を使用して行うことができます

DL = Q *(I * K-Ib)

ここで、[〜#〜] q [〜#〜]は、転置によって取得されるカーネルです[〜#〜] k [〜#〜](これは、信号処理文献の整合フィルター)。

したがって、画像をぼかす次の反復アルゴリズムを取得できます。

from scipy.ndimage import convolve

blurred_image = # Load image
kernel = # Load kernel/psf
learning_rate = # You need to find this yourself, do a logarithmic line search. Small rate will always converge, but slowly. Start with 0.4 and divide by 2 every time it fails.
maxit = 100

def loss(image):
    return np.sum(convolve(image, kernel) - blurred_image)

def gradient(image):
    return convolve(convolve(image, kernel) - blurred_image)

deblurred = blurred_image.copy()
for _ in range(maxit):
    deblurred -= learning_rate*gradient(image)

上記の方法は、おそらく最も単純な反復デコンボリューションアルゴリズムです。これらが実際に使用される方法は、いわゆる正則化されたデコンボリューションアルゴリズムによるものです。これらのアルゴリズムは、最初に画像のノイズ量を測定する関数を指定することで機能します。 TV(I)(-[〜#〜] i [〜#〜]の合計バリエーション)。次に、最適化手順がL(I)+ wTV(I)に対して実行されます。そのようなアルゴリズムに興味があるなら、Amir BeckとMarc TeboulleによるFISTA論文を読むことをお勧めします。この論文はかなり計算量が多いですが、ほとんどのことを理解する必要はありません。テレビのぼかしアルゴリズムを実装する方法だけです。

レギュラライザーを使用することに加えて、損失を最小限に抑えるために加速化された方法を使用しますL(I)。そのような例の1つは、ネステロフ加速勾配降下です。このような方法の詳細については、ブレンダンオドノヒュー、エマニュエルカンデスによる加速勾配スキームの適応型再起動を参照してください。

画像のブレ除去を実行する方法の概要。

  1. すべてがカメラから同じ距離になるように画像をトリミングします
  2. 今と同じ方法でコンボリューションカーネルを見つけます(まず合成ボケ画像でデコンボリューションアルゴリズムをテストします)
  3. デコンボリュートを計算する反復法を実装する
  4. 画像をデコンボリューションします。
9
Yngve Moe