MENU

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);
}

入力画像

src

出力画像

dst

薔薇の花びらの輪郭が強調されているのがわかるかと思います。

代表的な線形フィルタ

ぼかしフィルタ


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}
};