mainvisual

自分は今日、大学のゼミでで画像研究の一貫として、「メディアンフィルタをOpenCVで実装してみよう」 というのがありました。(もちろん、cv::medianBlurは使いませんよ) 課題の内容は、OpenCVで読み込んだデータにピクセル単位でアクセスし、 メディアンフィルタを用いた平滑化を実装すること。です。

前にOpenCVをかじっていたこともあり、比較的順調に課題を終えることができました。 しかし、忘れている部分もあったので、ここでどんなことに注意していけばいいかをまとめようと思います.

カラー画像対応のメディアンフィルタ実装記事はこちら

まずはソースコードから

メディアンフィルタはグレースケールとカラーの両方大丈夫です。 しかし、これらの2つは、OpenCVでは取り扱いが少々異なります。

今回は、話を簡単にするために、グレースケールの場合を載せようと思います。

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;


void sort(int arr[], int arr_len){
  for(int i=0; i<arr_len-1; i++){
    for(int j=arr_len-1; j>i; j--){
      if(arr[i] > arr[j]){
        int t = arr[j];
        arr[j] = arr[i];
        arr[i] = t;
      }
    }
  }
}


int main(int argc, char *argv[]) {


    if(argc < 2){
      cerr << "引数は1つ指定する必要があります" << endl;
      cerr << "./a.out <FILE PATH>" << endl;
      return -1;
    }

    // 第1引数から、ファイルのパスを取得
    string path_name = argv[1];

    // グレースケールで読み込むように、設定
    int const CV_LOAD_IMAGE_GRAYSCALE = 0;

    // グレースケール(3チャンネル)で読み込み
    Mat src = imread(path_name, CV_LOAD_IMAGE_GRAYSCALE);


    // エラーチェック
    if (!src.data) return -1;


    Mat dst = src.clone();

    for(int y=1; y<src.rows-1; y++){
      for(int x=1; x<src.cols-1; x++){
        int data[9];

        for(int n=-1; n<=1; n++){
          for(int m=-1; m<=1; m++){
            int p = src.at<uchar>(y+n, x+m);
            data[(m+1) + 3*(n+1)] = p;
          }
        }

        sort(data, 9);
        dst.at<uchar>(y, x) = data[4];

      }
    }


    /* 画像の表示 */
    imshow("Show src image", src);
    imshow("Show dst image", dst);
    /* 入力待機 */
    waitKey(0);
    return 0;
}

使い方

このソースコードをファイルにコピペし、次のコマンドを実行してください

g++ $(pkg-config --cflags opencv) -lopencv_core -lopencv_highgui -lopencv_imgproc main.cpp $(pkg-config --libs opencv)
./a.out <IMAGE PATH>

a.outというバイナリができますので、適当な画像のパスを引数に入れて、実行してみてください!