OpenCVで線形フィルタ処理と代表的なフィルタの種類11個
画像加工の基本とも言える線形フィルタのプログラムです。非常に簡単なので、使える場面もいろいろありそうです。
ソースコード
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
int main()
{
cv::Mat src = cv::imread("src.jpg", 0);
if(src.empty())
{
std::cout << "not found" << std::endl;
return -1;
}
// 線形フィルタ
double filter[][3] =
{
{1, 2, -2},
{-2, 0, 2},
{1, 2, -2}
};
// 入力画像と同じサイズの画像を0で初期化
cv::Mat dst = cv::Mat::zeros(src.rows, src.cols, CV_8U);
// 配列外アクセスが起きないように
for(int j = 1; j < src.rows - 1; j++)
{
for(int i = 1; i < src.cols - 1; i++)
{
int tmp = 0;
for(int jj = -1; jj < 1; jj++)
{
for(int ii = -1; ii < 1; ii++)
{
tmp += src.at<uchar>(j + jj, i + ii) * filter[jj + 1][ii + 1];
}
}
if(tmp < 0) tmp = -tmp; // 負の場合は絶対値をとる
if(tmp > 255) tmp = 255; // 255を超えないようにする
dst.at<uchar>(j, i) = tmp;
}
}
cv::namedWindow("FILTER", cv::WINDOW_AUTOSIZE);
cv::imshow("FILTER", dst);
cv::waitKey(0);
}
入力画像
出力画像
薔薇の花びらの輪郭が強調されているのがわかるかと思います。
代表的な線形フィルタ
ぼかしフィルタ
double filter[][3] =
{
{0, 1, 0},
{1, 1, 1},
{0, 1, 0}
};
平均化/平滑化フィルタ
double filter[][3] =
{
{1/9, 1/9, 1/9},
{1/9, 1/9, 1/9},
{1/9, 1/9, 1/9}
};
double filter[][5] =
{
{1/25, 1/25, 1/25, 1/25, 1/25},
{1/25, 1/25, 1/25, 1/25, 1/25},
{1/25, 1/25, 1/25, 1/25, 1/25},
{1/25, 1/25, 1/25, 1/25, 1/25},
{1/25, 1/25, 1/25, 1/25, 1/25}
};
加重平均化フィルタ
double filter[][3] =
{
{1/16, 2/16, 1/16},
{2/16, 4/16, 2/16},
{1/16, 2/16, 1/16}
};
double filter[][5] =
{
{1/256, 4/256, 6/256, 4/256, 1/256},
{4/256, 16/256, 24/256, 16/256, 4/256},
{6/256, 24/256, 36/256, 24/256, 6/256},
{4/256, 16/256, 24/256, 16/256, 4/256},
{1/256, 4/256, 6/256, 4/256, 1/256},
};
横方向微分フィルタ
double filter[][3] =
{
{0, 0, 0},
{0, -1, 1},
{0, 0, 0}
};
double filter[][3] =
{
{0, 0, 0},
{1, -1, 0},
{0, 0, 0}
};
double filter[][3] =
{
{0, 0, 0},
{-1/2, 0, -1/2},
{0, 0, 0}
};
縦方向微分フィルタ
double filter[][3] =
{
{0, 1, 0},
{0, -1, 0},
{0, 0, 0}
};
double filter[][3] =
{
{0, 0, 0},
{0, -1, 0},
{0, 1, 0}
};
double filter[][3] =
{
{0, 1/2, 0},
{0, 0, 0},
{0, -1/2, 0}
};
横方向2次微分フィルタ
double filter[][3] =
{
{0, 0, 0},
{1, -2, 1},
{0, 0, 0}
};
縦方向2次微分フィルタ
double filter[][3] =
{
{0, 1, 0},
{0, -2, 0},
{0, 1, 0}
};
横方向プリューウィットフィルタ
double filter[][3] =
{
{-1, 0, 1},
{-1, 0, 1},
{-1, 0, 1}
};
縦方向プリューウィットフィルタ
double filter[][3] =
{
{1, 1, 1},
{0, 0, 0},
{-1, -1, -1}
};
横方向ソーベルフィルタ
double filter[][3] =
{
{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}
};
縦方向ソーベルフィルタ
double filter[][3] =
{
{1, 2, 1},
{0, 0, 0},
{-1, -2, -1}
};
斜め方向ソーベルフィルタ
double filter[][3] =
{
{0, 1, 2},
{-1, 0, 1},
{-2, -1, 0}
};
double filter[][3] =
{
{2, 1, 0},
{1, 0, -1},
{0, -1, -2}
};
ラプラシアンフィルタ
double filter[][3] =
{
{0, 1, 0},
{1, -4, 1},
{0, 1, 0}
};
鮮鋭化フィルタ
double filter[][3] =
{
{0, -1, 0},
{-1, 5, -1},
{0, -1, 0}
};
double filter[][3] =
{
{-1, -1, -1},
{-1, 9, -1},
{-1, -1, -1}
};
エンボスフィルタ
double filter[][3] =
{
{-1, 0, 0},
{0, 1, 0},
{0, 0, 0}
};
横方向ロバーツフィルタ
double filter[][3] =
{
{0, 0, 0},
{0, 1, 0},
{0, 0, -1}
};
縦方向ロバーツフィルタ
double filter[][3] =
{
{0, 0, 0},
{0, 0, 1},
{0, -1, 0}
};