opencv Foundation 58 フーリエ変換 cv2.dft()->(画像強調、画像ノイズ除去、エッジ検出、特徴抽出、画像圧縮および暗号化)

フーリエ変換とは何ですか?

フーリエ変換は、フランスの数学者ジャン バティスト ジョゼフ フーリエにちなんで名付けられ、
この数学ツールへの彼の貢献に敬意を表します。フーリエは18世紀末から19世紀初頭に生き、数学の分野で優れた業績を残したばかりでなく、熱伝導や天体物理学の分野でも重要な貢献をした多才な科学者です。

フーリエ変換の最も初期の形式は、1822 年にフーリエによって初めて導入されました。フーリエは、著書「熱方程式を解くための解析手法」の中で、周期関数を一連のサイン関数とコサイン関数に分解する方法を説明しました。彼の研究は、信号処理、画像処理、その他の分野における現代の周波数領域解析の基礎を築きました。

フーリエ変換は、フーリエがこの数学的ツールを初めて体系的に研究し、適用したため、フーリエにちなんで名付けられました。フーリエの研究は、現代科学、特に信号処理、画像処理、通信の分野に大きな影響を与えました。フーリエ変換は、さまざまな種類の信号やデータの分析と処理に広く使用されています。

フーリエ変換における変換とは何ですか?

フーリエ変換における「変換」とは、関数を時間領域(時間領域)表現から周波数領域(周波数領域)表現に変換することを指します。言い換えれば、フーリエ変換は、関数をさまざまな時点での動作の記述から、さまざまな周波数でのコンポーネントの記述に変換します。

フーリエ変換では、関数 (通常は信号または画像) を変換します。この関数は連続的または離散的にすることができます。連続フーリエ変換 (CFT) は連続時間信号に適用され、時間領域から連続周波数領域に変換されます。離散フーリエ変換 (DFT) は離散時間信号に適用され、時間領域から離散周波数領域に変換されます。

opencvでは何が変換されるのでしょうか?

OpenCV では、フーリエ変換 (Fourier Transform) は画像に対して実行される変換であり、画像を空間領域 (時間領域) から周波数領域に変換します。具体的には、
OpenCV のフーリエ変換は離散フーリエ変換 (DFT) であり、離散画像を時間領域から離散周波数領域に変換するために使用されます。

フーリエ変換では、OpenCV 对输入的图像进行数学变换,将图像的每个像素表示为一系列正弦和余弦波的振幅和相位. これにより、画像が生のピクセル表現から、画像内のさまざまな周波数成分を表す複合表現に変換されます。

上記の情報を読んでも、それが何であるかはまだわかりませんが、なぜそれがフーリエ変換と呼ばれるかはわかりました。


フーリエ変換は非常に抽象的であり、工学分野で長年フーリエ変換を使用してきた人が多くいますが、フーリエ変換が何であるかを完全には理解していません。フーリエ変換をよりよく説明するために、人生における例を見てみましょう。

表 14-1 は、ある飲み物の計算式を示したもので、時間の形をした表になっていますが、この表は非常に長いので、ここでは一部のみを抜粋しています。このテーブルには、時刻「00:00」から特定の時刻「00:11」までの操作が記録されています。

ここに画像の説明を挿入

表を注意深く分析すると、レシピが次のとおりであることがわかります。

  • 1分ごとに氷砂糖を1粒入れます。
  • 2分おきに小豆を3粒ずつ入れていきます。
  • 3分ごとに緑豆を2個入れます。
  • 4分ごとにトマト4個を置きます。
  • 5分ごとに1カップの精製水を入れます。

上記本文は動作周波数の観点から計算式を解説したものです。

データ処理の過程で、情報はグラフの形式で表現されることがよくあります。時間領域の観点から、レシピテーブルは図 14-1 のように表現できます。図 14-1 ではレシピの最初の 11 分間の動作のみを示していますが、レシピの動作を完全に表現するには、全時間の動作ステップをチャートで描く必要があります。

ここに画像の説明を挿入

この計算式表を周波数(周期)の観点から表現すると図14-2のように表せます。図の横軸は周期(周波数の逆数)、縦軸は成分数です。

図 14-2 は、このレシピの動作プロセスを完全に表すことができることがわかります。

ここに画像の説明を挿入

関数については、時間領域から周波数領域に変換することも可能です

図 14-3 は、周波数 5 (1 秒に 5 サイクル)、振幅 1 の正弦波です。

ここに画像の説明を挿入
周波数の観点から考えると、図 14-4 に示す周波数領域図として描くことができます。ここで、横軸は周波数、縦軸は振幅です。

ここに画像の説明を挿入
図 14-3 と図 14-4 は同等であり、同じ関数を異なる形式で表現したものです。対応する時間領域表現は周波数領域表現を通じて取得することができ、対応する周波数領域表現も時間領域表現を通じて取得することができる。

フランスの数学者フーリエは、あらゆる周期関数は異なる周波数の正弦関数の和として表現できると指摘しました。今では当たり前の理論ですが、当時はこの理論が分かりにくく、大きな疑問を持たれました。

フーリエ変換の具体的な過程を見てみましょう。たとえば、周期関数の曲線は図 14-5 の左上のプロットに示されています。この周期関数は次のように表現できます。

y = 3 np.sin(0.8 x) + 7 np.sin(0.5 x) + 2 np.sin(0.2 x)

したがって、この関数は次の 3 つの関数の合計として見ることができます。

  • y1 = 3 np.sin(0.8 x) (関数 1)
  • y2 = 7 np.sin(0.5 x) (関数 2)
  • y3 = 2 np.sin(0.2 x) (関数 3)

上記 3 つの関数に対応する関数曲線を、図 14-5 の右上隅、左下隅、右下隅にそれぞれ示します。

ここに画像の説明を挿入
周波数領域の観点から考えると、上記の 3 つの正弦関数は図 14-6 の 3 つの列として表すことができます。図の横軸は周波数、縦軸は振幅です。

ここに画像の説明を挿入
上記の分析から、図 14-5 の左上隅の関数曲線は、図 14-6 に示す周波数領域図として表現できることがわかります。

図 14-5 の左上隅の時間領域関数グラフから図 14-6 に示す周波数領域グラフを構築するプロセスがフーリエ変換です。

図 14-1 と図 14-2 は同じ情報を表しており、図 14-1 は時間領域の図、図 14-2 は周波数領域の図です。
図 14-5 の左上隅にある時間領域関数のグラフは、図 14-6 に示されている周波数領域のグラフとまったく同じ情報です。
フーリエ変換は、時間領域の情報を周波数領域の観点から完全に表現することです。
上記の周波数と振幅に加えて、時間差の問題も考慮する必要があります。たとえば、飲料の配合では、風味を制御するために成分を添加するタイミングを厳密に制御する必要があります。表 14-1 の「00:00」の動作をさらに細かく制御すると、実際には表 14-2 のようになります。

ここに画像の説明を挿入
材料を加えるタイミングが変わると飲み物の味も変わります。したがって、実際の処理工程では、この時間差も考慮する必要がある。この時間差がフーリエ変換における位相となります位相は時間差に関する情報を表します。

たとえば、図 14-7 の左上隅に対応する関数は次のように表現できます。

y = 3 np.sin(0.8 x) + 7 np.sin(0.5 x+2) + 2 np.sin(0.2 x+3)

したがって、この関数は次の 3 つの関数の合計として見ることができます。

  • y1 = 3 np.sin(0.8 x) (関数 1)
  • y2 = 7 np.sin(0.5 x+2) (関数 2)
  • y3 = 2 np.sin(0.2 x+3) (関数 3)

上記 3 つの関数に対応する関数曲線を、それぞれ図 14-7 の右上隅、左下隅、右下隅に示します。

ここに画像の説明を挿入
この例では、横軸を開始時刻とすると、関数yを構成する3つの正弦関数は全て時刻0から始まるわけではなく、時間差が存在する。時差のない関数をそのまま使用すると、図 14-7 の左上の関数は作成できませんが、図 14-5 の左上の関数が作成されます。
したがって、位相差もフーリエ変換において非常に重要な条件となる。

以上、飲料のレシピと関数の例を用いて、時間領域と周波数領域の変換の可能性を紹介しましたので、皆様のフーリエ変換の理解の一助になれば幸いです。

画像処理プロセスにおいて、フーリエ変換とは画像をサイン成分とコサイン成分の2つに分解すること、つまり画像を空間領域から周波数領域(以下、周波数領域と呼びます)に変換することです。 。デジタル画像がフーリエ変換されると、得られる周波数領域の値は複素数になります。

したがって、フーリエ変換の結果を表示するには、実像+虚像(複素像)、または大きさ像(マグニチュード像)+位相像(位相像)の形で表示する必要があります。

等級画像には元の画像に必要な情報のほとんどが含まれているため、通常は画像処理中に等級画像のみが使用されます。もちろん、最初に周波数領域で画像を処理し、次に逆フーリエ変換を通じて修正された空間領域画像を取得する場合は、振幅画像と位相画像を同時に保存する必要があります。

画像にフーリエ変換を実行すると、画像内の低周波と高周波の情報が得られます。低周波情報は、画像内のゆっくりと変化するグレースケール成分に対応します。高周波情報は、画像内でますます速く変化するグレースケール成分に対応します。これは、グレースケールの急激な遷移によって引き起こされます。

たとえば、大草原の画像にライオンがいる場合、低周波情報は色が均一な広大な草原などの細部に相当し、高周波情報は草の輪郭などのさまざまなエッジやノイズ情報に相当します。ライオン。

フーリエ変換の目的は、画像を空間領域から周波数領域に変換し、画像内の特定のオブジェクトの処理を周波数領域で実現し、処理された周波数領域画像を逆フーリエ変換して空間領域画像を取得することです。 。フーリエ変換は画像処理の分野で非常に重要な役割を果たしており、画像の強調、画像のノイズ除去、エッジ検出、特徴抽出、画像の圧縮と暗号化などを実現できます。


大量のテキストの説明を見ると頭が痛くなります。コードを見てみましょう

Numpy が実装するフーリエ変換関数の説明

Numpy モジュールはフーリエ変換関数を提供しており、Numpy モジュール内の fft2() 関数は画像のフーリエ変換を実現できます。

フーリエ変換を実現するために Numpy が提供する関数は numpy.fft.fft2() で、その構文形式は次のとおりです。

戻り値 = numpy.fft.fft2(元の画像)

这里需要注意的是,参数“原始图像”的类型是灰度图像,函数的返回值是一个复数数组(complex ndarray)。

この関数の処理後、画像のスペクトル情報を取得できます。このとき、画像スペクトルのゼロ周波数成分はスペクトル画像 (周波数領域画像) 1 の左上隅に位置します。観察の便宜上、通常は numpy.fft.fftshift() 関数を使用して移動します。図 14-8 に示すように、ゼロ周波数成分を周波数領域画像の中心に移動します。

ここに画像の説明を挿入
関数 numpy.fft.fftshift() の構文形式は次のとおりです。

戻り値 = numpy.fft.fftshift(生のスペクトル)

この機能で処理すると、画像スペクトルのゼロ周波数成分が周波数領域画像の中心に移動するため、フーリエ変換後のスペクトルのゼロ周波数部分を観察するのに非常に効果的です。
画像をフーリエ変換すると、複素数の配列が得られます。画像として表示するには、それらの値を [0, 255] のグレースペースに調整する必要があり、使用される式は次のとおりです。

ピクセルの新しい値 = 20*np.log(np.abs(スペクトル値))

コード例: Numpy でフーリエ変換を実装し、得ら​​れたスペクトル画像を観察します。

コードは以下のように表示されます。

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('lena.png',0)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20*np.log(np.abs(fshift))
plt.subplot(121)
plt.imshow(img, cmap = 'gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('result')
plt.axis('off')
plt.show()

実行結果:
元の画像とそのスペクトル画像を表示
ここに画像の説明を挿入

逆フーリエ変換を実装する

必要な注意のは、フーリエ変換中に numpy.fft.fftshift() 関数を使用してゼロ周波数成分をシフトする場合、逆フーリエ変換プロセスで numpy.fft.ifftshift() 関数を使用して、最初にゼロ周波数成分を移動します。周波数成分を元の位置に移動し、次に逆フーリエ変換を実行します。そのプロセスを図 14-10 に示します。

ここに画像の説明を挿入

関数 numpy.fft.ifftshift() は numpy.fft.fftshift() の逆関数であり、その構文形式は次のとおりです。

調整されたスペクトル = numpy.fft.ifftshift(生のスペクトル)

numpy.fft.ifft2() 関数は、逆フーリエ変換を実装し、空間複素数の配列を返すことができます。これは numpy.fft.fft2() の逆関数であり、この関数の構文は次のとおりです。

戻り値 = numpy.fft.ifft2 (周波数領域データ)

関数 numpy.fft.ifft2() の戻り値は依然として複雑な ndarray です。
逆フーリエ変換によって得られる空間ドメイン情報は複素配列であるため、[0, 255] グレースケール空間に調整する必要があります。使用される式は次のとおりです。

iimg = np.abs(逆フーリエ変換結果)

例: Numpy でフーリエ変換と逆フーリエ変換を実装し、逆フーリエ変換の結果画像を観察します。

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('lena.png',0)
#对图像进行傅里叶变换,结果是复数
f = np.fft.fft2(img)
#将低频部分移动到图像中心
fshift = np.fft.fftshift(f)
#将复数变化成实数
magnitude_spectrum = 20*np.log(np.abs(fshift))
#将傅里叶变换的结果进行反变换
ishift = np.fft.ifftshift(fshift)


#对傅里叶变换的结果进行反变换
iimg = np.fft.ifft2(ishift)

#取绝对值
iimg = np.abs(iimg)


plt.subplot(131),plt.imshow(img, cmap = 'gray')
plt.title('original'),plt.axis('off')

plt.subplot(132),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('magnitude_spectrum'),plt.axis('off')

plt.subplot(133),plt.imshow(iimg, cmap = 'gray')
plt.title('iimg'),plt.axis('off')

plt.show()

操作結果:

ここに画像の説明を挿入

ハイパスフィルタリングの例

画像の中には高周波信号と低周波信号が同時に存在します。

  • 低周波信号は、画像内のゆっくりと変化するグレースケール成分に対応します。たとえば、サバンナの画像では、低周波信号は
    色が均一になる傾向のある広大な草原に対応します。
  • 高周波信号は、画像内でますます速く変化するグレースケール成分に対応します。これは、グレースケールの急激な遷移によって引き起こされます。上のサバンナの画像にライオンもいる場合、高周波信号はライオンの端などの情報に相当します。

フィルターは特定の周波数成分を通過または拒否することができ、その動作モードに応じてローパス フィルターとハイパス フィルターに分けることができます。

  • 低い周波数の信号を通過させるフィルターをローパスフィルターと呼びます。ローパス フィルターは、高周波信号を減衰させ、低周波信号を通過させます会使图像变模糊
  • 高周波信号を通過させるフィルターをハイパスフィルターといいます。ハイパス フィルターは低周波信号を減衰させ、高周波信号を通過させます。これにより、画像の細部が鮮明になりますが、画像のコントラストが失われます。

フーリエ変換は画像の高周波信号と低周波信号を分離することができます

ここに画像の説明を挿入
図14-12の右図の中央にあるすべてのピクセル値をゼロに設定するには、最初にその中心位置の座標を計算し、次にその中心位置から30ピクセルのサイズの領域を選択する必要があります。座標を中心に上から下、左から右に移動し、この領域のピクセルを 0 に設定します。値は 0 に設定されます。

このフィルターの実装は次のとおりです。

rows, cols = img.shape
crow,ccol = int(rows/2) , int(cols/2)
fshift[crow-30:crow+30, ccol-30:ccol+30] = 0

例: Numpy で画像をフーリエ変換して周波数領域画像を取得します。そして、低周波成分の値を周波数領域で0として処理し、ハイパスフィルタリングを実現する。最後に、画像に対して逆フーリエ変換を実行して、復元された元の画像を取得します。

フーリエ変換の前後の画像の違いを観察してください。

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('lena.png',0)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
rows, cols = img.shape
crow,ccol = int(rows/2) , int(cols/2)
fshift[crow-30:crow+30, ccol-30:ccol+30] = 0
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('original'),plt.axis('off')
plt.subplot(122),plt.imshow(iimg, cmap = 'gray')
plt.title('iimg'),plt.axis('off')
plt.show()

操作結果:

ここに画像の説明を挿入

OpenCVはフーリエ変換を実装します

OpenCV 提供了函数 cv2.dft()和 cv2.idft()来实现傅里叶变换和逆傅里叶变换、以下で別途紹介します。

フーリエ変換を実装する

関数 cv2.dft() の構文形式は次のとおりです。

戻り結果 = cv2.dft (元の画像、変換されたロゴ)

この関数を使用するときは、パラメーターの使用仕様に注意する必要があります。

  • パラメーター「元の画像」については、まず np.float32() 関数を使用して画像を np.float32 形式に変換します。
  • 「変換フラグ」の値は通常「cv2.DFT_COMPLEX_OUTPUT」で、複素配列を出力するために使用されます。

関数 cv2.dft() によって返される結果は、フーリエ変換に Numpy を使用して取得される結果と一致していますが、返される値はデュアルチャネルであり、最初のチャネルは結果の実部で、2 番目のチャネルは結果
の虚数部。

関数 cv2.dft() の変換後、元の画像のスペクトル情報を取得します。
このとき、ゼロ周波数成分は中心にありませんが、処理の都合上、中心に移動する必要がありますが、これは関数 numpy.fft.fftshift() で実現できます。

例えば、次の文は、スペクトル画像 dft のゼロ周波数成分をスペクトルの中心に移動し、ゼロ周波数成分を中心としたスペクトル画像 dftshift を取得します。

dftShift = np.fft.fftshift(dft)

以上の処理を行うと、分光画像は実数部と虚数部からなる値のみとなる。表示するにはさらに処理が必要です。

函数 cv2.magnitude()可以计算频谱信息的幅度この関数の構文は次のとおりです。

戻り値 = cv2.magnitude (パラメータ 1、パラメータ 2)

式内の 2 つのパラメーターの意味は次のとおりです。

  • パラメータ 1: 浮動小数点型の x 座標値、つまり実数部。
  • パラメーター 2: 浮動小数点の y 座標値、つまり虚数部。パラメーター 1 と同じサイズ (値のサイズではなく、値のサイズ) を持つ必要があります。

関数 cv2.magnitude() の戻り値は、パラメーター 1 とパラメーター 2 の二乗の合計の平方根です。式は次のとおりです。

ここに画像の説明を挿入
式中、I は元の画像を表し、dst はターゲット画像を表します。

通常、スペクトル情報の大きさを取得した後、スペクトル情報を画像の形式で表示するには、さらに大きさの値を変換する必要があります。簡単に言うと、グレースケール画像の形式で表示できるように、振幅値をグレースケール画像のグレースケール空間 [0, 255] にマッピングする必要があります。

ここで使用される式は次のとおりです。

結果 = 20*np.log(cv2.magnitude(実部, 虚部))

以下は、読者が上記の処理を観察できるようにするための画像のフーリエ変換です。次のコードは、イメージ「lena」に対してフーリエ変換を実行し、大きさの値を計算し、大きさの値を正規化します。

import numpy as np
import cv2
img = cv2.imread('lena.png',0)
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
print(dft)
dftShift = np.fft.fftshift(dft)
print(dftShift)
result = 20*np.log(cv2.magnitude(dftShift[:,:,0],dftShift[:,:,1]))
print(result)

得られた値の範囲をそれぞれ図 14-14 に示します。で:

  • 左の図は関数 cv2.dft() で得られるスペクトル値を示しており、実数部と虚数部で構成されています。
  • 中央の図は、関数 cv2.magnitude() によって計算されたスペクトル振幅値を示していますが、これは標準画像グレースケール空間 [0, 255] にありません。
  • 右側の図は、関数 cv2.magnitude() によって計算されたスペクトル振幅値をさらに正規化した結果を示しており、値の範囲は [0, 255] になります。

ここに画像の説明を挿入

例: OpenCV 関数を使用して画像をフーリエ変換し、そのスペクトル情報を表示する

import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('lena.png',0)
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
dftShift = np.fft.fftshift(dft)
result = 20*np.log(cv2.magnitude(dftShift[:,:,0],dftShift[:,:,1]))
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('original'),plt.axis('off')
plt.subplot(122),plt.imshow(result, cmap = 'gray')
plt.title('result'), plt.axis('off')
plt.show()

操作結果:

  • 左の画像が元の画像です。
  • 右側の画像はスペクトル イメージで、関数 np.fft.fftshift() を使用してゼロ周波数成分をスペクトル イメージの中心にシフトした結果です。
    ここに画像の説明を挿入

逆フーリエ変換を実装する

OpenCV では、 を使用します函数 cv2.idft()实现逆傅里叶变换。この関数は、
フーリエ変換関数 cv2.dft() の逆関数です。その構文形式は次のとおりです。

戻り値 = cv2.idft (元のデータ)

画像をフーリエ変換した後、通常、ゼロ周波数成分はスペクトル画像の中心にシフトされます。関数 numpy.fft.fftshift() を使用してゼロ周波数成分をシフトした場合、関数 numpy.fft.ifftshift() を使用して
、逆フーリエ変換の前に
ゼロ周波数成分を元の位置に復元する必要があります。

また、逆フーリエ変換後も結果の値は依然として複素数であるため、
その大きさは関数 cv2.magnitude() を使用して計算する必要があることにも注意してください。

例: OpenCV 関数を使用して、画像をフーリエ変換および逆フーリエ変換し、元の画像と逆フーリエ変換後の画像を表示します。

import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('lena.png',0)
#对图像进行傅里叶变换
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
#将低频部分移动到图像中心
dftShift = np.fft.fftshift(dft)
#将复数变化成实数
ishift = np.fft.ifftshift(dftShift)
#将傅里叶变换的结果进行反变换
iImg = cv2.idft(ishift)

#取绝对值,取对数的目的为了将数据变化到较小的范围(比如0-255,并显示,结果是复数
iImg= cv2.magnitude(iImg[:,:,0],iImg[:,:,1])
print(iImg.shape)
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('original'), plt.axis('off')
plt.subplot(122),plt.imshow(iImg, cmap = 'gray')
plt.title('inverse'), plt.axis('off')
plt.show()

操作結果:

ここに画像の説明を挿入
右の画像は、元の画像 img をフーリエ変換および逆フーリエ変換した後に得られる画像です。

おすすめ

転載: blog.csdn.net/hai411741962/article/details/132213252
おすすめ