OpenCVでフーリエ変換(dft)2 表示編
こんにちは、よりです。
今日は下記の記事で紹介したフーリエ変換をした後の画像の表示方法を紹介したいと思います。
yori1029.hatenablog.com
とはいえ手探りで頑張ってるので私のメモ程度のレベルです。
今回はさくさく行きましょう、表示するだけやし。
前回の記事を参照してもらうとわかるんですけど dft 後のデータって2チャンネルになってるし虚部があるから扱いにくいよなーって感じです。
それを何とかして、よく見るフーリエ変換後の画像にしていきたいと思います。
全体の流れとしては
って感じです。
今回フーリエ変換する画像はこちら。
正直全然大したことないので参考にしたサイトのURLとコードを載せます。
下記のサイトの関数 create_fourier_magnitude_image_from_complex を参考に書きました。
opencv_sample_list_jp/main.cpp at master · YusukeSuzuki/opencv_sample_list_jp · GitHub
それでは私のわかりにくいコードも載せます。
#include <iostream> #include <cmath> #include <string> #include <sstream> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <ctype.h> using namespace cv; using namespace std; int main(int argc, char **argv) { //入力 Mat image = cv::imread("lena.jpg", cv::IMREAD_GRAYSCALE); //フーリエ変換用Mat Mat furimg; //実部のみのimageと虚部を0で初期化したMatをRealImaginary配列に入れる Mat RealIamginary[] = { Mat_<float>(image), Mat::zeros(image.size(), CV_32F) }; //配列を合成 merge(RealIamginary, 2, furimg); //フーリエ変換 dft(furimg, furimg); //表示用 Mat divdisplay[2]; //フーリエ後を実部と虚部に分ける split(furimg, divdisplay); //表示用にすべて実数に Mat display; magnitude(divdisplay[0], divdisplay[1], display); //対数に変換する(そのため各ピクセルに1を加算) display += Scalar::all(1); log(display, display); //表示用に正規化 Mat outdisplay; normalize(display, outdisplay, 0, 1, CV_MINMAX); namedWindow("aftdft"); imshow("aftdft", outdisplay); waitKey(-1); return 0; }
実行すると下図が出てきます。
これは画像をフーリエ変換し、それを可視化したものです。
しかし普段みるフーリエ変換後の画像とは異なってますよね?
普段見るのは白い部分が中心にきてると思いますが、それは見やすいように変換している画像です。
では変換してみましょう。
追加した部分がわかるように書いたのでそこだけ見てもらえれば大丈夫です。
#include <iostream> #include <cmath> #include <string> #include <sstream> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <ctype.h> using namespace cv; using namespace std; int main(int argc, char **argv) { //入力 Mat image = cv::imread("lena.jpg", cv::IMREAD_GRAYSCALE); //フーリエ変換用Mat Mat furimg; //実部のみのimageと虚部を0で初期化したMatをRealImaginary配列に入れる Mat RealIamginary[] = { Mat_<float>(image), Mat::zeros(image.size(), CV_32F) }; //配列を合成 merge(RealIamginary, 2, furimg); //フーリエ変換 dft(furimg, furimg); //表示用 Mat divdisplay[2]; //フーリエ後を実部と虚部に分ける split(furimg, divdisplay); //表示用にすべて実数に Mat display; magnitude(divdisplay[0], divdisplay[1], display); //対数に変換する(そのため各ピクセルに1を加算) display += Scalar::all(1); log(display, display); //ここから下を追加 //___________________________________________ const int halfW = display.cols / 2; const int halfH = display.rows / 2; Mat tmp; Mat q0(display, Rect(0, 0, halfW, halfH)); Mat q1(display, Rect(halfW, 0, halfW, halfH)); Mat q2(display, Rect(0, halfH, halfW, halfH)); Mat q3(display, Rect(halfW, halfH, halfW, halfH)); q0.copyTo(tmp); q3.copyTo(q0); tmp.copyTo(q3); q1.copyTo(tmp); q2.copyTo(q1); tmp.copyTo(q2); //____________________________________________ //ここから上を追加 //表示用に正規化 Mat outdisplay; normalize(display, outdisplay, 0, 1, CV_MINMAX); namedWindow("aftdft"); imshow("aftdft", outdisplay); waitKey(-1); return 0; }
上記のものを実行すると下図がでてきます。
これで画像のフーリエ変換を可視化することができました!!