チーム20C1
課題名
ガウシアンフィルタとFFTの比較
研究者名
Ryota Yamada
Riku Yabe
概要
ガウシアンフィルタを通した画像に対して高速フーリエ変換を行い、
変換後の画像がフィルタのサイズに対してどのように変化するのかを比較する。
使用言語 とプログラム
・C++
→ Mandatory.cpp
→ mainwin.h
→ mainwin.cpp
→ window.h
→ window.cpp
・Java
→ Complex.java
→ FFT.java
→ FFT2D.java
→ ImageFFT.java
C++で画像処理したものをJavaのプログラムで高速フーリ変換を施した。
Javaのプログラムは、全てチーム15C2がFFT用に作成したものをそのまま利用している。
実行の流れは次のようになる。
1. C++で画像をフィルタに通す(フィルタのサイズはあらかじめコード内で指定する)
2. 手順1で処理した画像をJavaのプログラムでグレースケール画像に変換したのち、高速フーリエ変換。
Mandatory.cpp
#include "mainwin.h"
int main(int argc, char *argv[])
{
QApplication app(argc,argv);
MainWin m;
m.show();
return app.exec();
}
mainwin.h
#include <QtWidgets>
#include "window.h"
class MainWin : public QMainWindow
{
Q_OBJECT
public:
MainWin();
private slots:
void load();
void showResolution();
private:
QAction *loadAction, *saveAction, *exitAction;
QAction *grayAction, *ggaussianAction, *cgaussianAction;
QMenu *mFileMenu, *mFilterMenu;
QStatusBar *mBar;
Window *mWin;
QHBoxLayout *mHbox;
QVBoxLayout *mVbox;
QWidget *mTop;
};
mainwin.cpp
#include "mainwin.h"
#include <sstream>
MainWin::MainWin()
{
loadAction = new QAction("&Load", this);
saveAction = new QAction("&Save", this);
exitAction = new QAction("&Exit", this);
grayAction = new QAction("&Gray", this);
ggaussianAction = new QAction("&GrayGauss", this);
cgaussianAction = new QAction("&ColorGauss", this);
mWin = new Window();
mTop = new QWidget();
mHbox = new QHBoxLayout();
mVbox = new QVBoxLayout();
//ボタンの追加
mVbox->addWidget(mWin);
mVbox->addLayout(mHbox);
mTop->setLayout(mVbox);
//ボタンの処理
connect(loadAction, SIGNAL(triggered()), this, SLOT(load()));
connect(saveAction, SIGNAL(triggered()), mWin, SLOT(save()));
connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
//メニューの処理
connect(grayAction, SIGNAL(triggered()), mWin,
SLOT(gray()));
connect(ggaussianAction, SIGNAL(triggered()), mWin,
SLOT(ggaussian()));
connect(cgaussianAction, SIGNAL(triggered()), mWin,
SLOT(cgaussian()));
connect(grayAction, SIGNAL(triggered()), this,
SLOT(showResolution()));
connect(ggaussianAction, SIGNAL(triggered()), this,
SLOT(showResolution()));
connect(cgaussianAction, SIGNAL(triggered()), this,
SLOT(showResolution()));
//メニューバーの作成
mFileMenu = menuBar()->addMenu("&File");
mFileMenu->addAction(loadAction);
mFileMenu->addAction(saveAction);
mFileMenu->addSeparator();
mFileMenu->addAction(exitAction);
mFilterMenu = menuBar()->addMenu("&Filter");
mFilterMenu->addAction(grayAction);
mFilterMenu->addAction(ggaussianAction);
mFilterMenu->addAction(cgaussianAction);
//Widgetを中心に配置
setCentralWidget(mTop);
//ステータスバーの作成
mBar = statusBar();
}
void MainWin::load()
{
//ディレクトリから画像をロード
QStringList name =
QFileDialog::getOpenFileNames(
this,
"Load",
".",
"*.jpg");
mWin->setList(name);
showResolution();
}
void MainWin::showResolution()
{
//解像度の出力
if(mWin->mWidth != 0){
std::stringstream ss;
ss<<"解像度"<<mWin->mWidth<<"x"<<mWin->mHeight;
mBar->showMessage(ss.str().c_str());
}
}
window.h
#include <QtWidgets>
class Window : public QWidget
{
Q_OBJECT
public:
Window(QWidget *parent=0);
void setList(QStringList);
int mWidth = 0, mHeight = 0;
protected:
void paintEvent(QPaintEvent*);
public slots:
void save();
void gray();
void cgaussian();
void ggaussian();
private:
void load();
QImage mImage;
QStringList mList;
unsigned int mIdx = 0;
unsigned int mSize = 0;
};
window.cpp
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "window.h"
#define GAUSS_SIZE 3
Window::Window(QWidget *parent)
: QWidget(parent)
{
setMinimumSize(qApp->desktop()->size()/2);
}
void Window::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawImage(0,0,mImage);
}
void Window::setList(QStringList strs)
{
mList = strs;
mSize = strs.size();
mIdx = 0;
load();
}
void Window::load()
{
if(mSize != 0)
{
QString str = mList[mIdx];
if(!str.isEmpty())
{
if(QFile::exists(str))
{
//画像の読み込み
QImage im = QImage(str);
//画像の表示
mWidth = im.width(); mHeight = im.height();
mImage = im.scaled(qApp->desktop()->width()/2,
qApp->desktop()->height()/2,
Qt::KeepAspectRatio);
setMinimumSize(mImage.size());
update();
}
}
}
}
void Window::gray()
{
if(mSize != 0)
{
QString str = mList[mIdx];
if(!str.isEmpty())
{
if(QFile::exists(str))
{
//画像の読み込み
cv::Mat src = cv::imread(str.toStdString().c_str());
cv::Mat gry;
//グレースケール処理
cvtColor(src, gry, cv::COLOR_BGR2GRAY);
//QImage変換
QImage im = QImage(gry.data, gry.cols, gry.rows,
QImage::Format_Grayscale8);
im = im.convertToFormat(QImage::Format_RGB888);
//画像の表示
mWidth = im.width(); mHeight = im.height();
mImage = im.scaled(qApp->desktop()->width()/2,
qApp->desktop()->height()/2,
Qt::KeepAspectRatio);
setMinimumSize(mImage.size());
update();
}
}
}
}
void Window::ggaussian()
{
if(mSize != 0)
{
QString str = mList[mIdx];
if(!str.isEmpty())
{
if(QFile::exists(str))
{
//画像の読み込み
cv::Mat src = cv::imread(str.toStdString().c_str());
cv::Mat gry;
//グレースケール処理
cvtColor(src, gry, cv::COLOR_BGR2GRAY);
//ガウシアン処理
cv::Mat dst;
cv::Size k;
k.width = GAUSS_SIZE;
k.height = GAUSS_SIZE;
GaussianBlur(gry, dst, k, 0);
//QImage変換
QImage im = QImage(dst.data, dst.cols, dst.rows,
QImage::Format_Grayscale8);
im = im.convertToFormat(QImage::Format_RGB888);
//画像の表示
mWidth = im.width(); mHeight = im.height();
mImage = im.scaled(qApp->desktop()->width()/2,
qApp->desktop()->height()/2,
Qt::KeepAspectRatio);
setMinimumSize(mImage.size());
update();
}
}
}
}
void Window::cgaussian()
{
if(mSize != 0)
{
QString str = mList[mIdx];
if(!str.isEmpty())
{
if(QFile::exists(str))
{
//画像の読み込み
cv::Mat src = cv::imread(str.toStdString().c_str());
cv::Mat dst;
//ガウシアン処理
cv::Size k;
k.width = GAUSS_SIZE;
k.height = GAUSS_SIZE;
GaussianBlur(src, dst, k, 0);
//QImage変換
QImage im = QImage(dst.data, dst.cols, dst.rows,
QImage::Format_RGB888);
im = im.rgbSwapped();
//画像の表示
mWidth = im.width(); mHeight = im.height();
mImage = im.scaled(qApp->desktop()->width()/2,
qApp->desktop()->height()/2,
Qt::KeepAspectRatio);
setMinimumSize(mImage.size());
update();
}
}
}
}
void Window::save()
{
mImage.save("test.jpg");
}
画像の比較
以下の画像は全て、左:FFT前の画像、右:FFT後の画像 になっている。
・フィルタなし
・サイズ4
・サイズ8
・サイズ32
・サイズ512
考察
ガウシアンフィルタを適用した画像は、高速フーリエ変換を施すと早い段階から高周波成分が取り除かれていることが伺える。
これは、ガウシアンフィルタが重みを伴うフィルタだからだと考えられる。
モザイクのサイズが細かくなるにつれ、FFT後の画像が全体的に低周波(青色)の占める割合が多くなっていることがわかる。
これはがウシアンフィルタを通したことにより、画像全体での各画素値の差が元の画像に比べて減少していくからだと考えられる。
また、FFT後の画像は格子模様が見られるが、これはフィルタを通した後の画像を扱っているので、
フィルタのサイズに合わせて現れていると考えられる。
- 最終更新:2020-07-27 16:18:00