スポンサーリンク

ガウシアンフィルタについて(2)実装

#include <iostream>
#include <vector>

#include "ppmP3_read.hpp"

class Filter {

  //画像フィルタ
  std::vector< std::vector<float> > m_filter;

public:
  //! @brief コンストラクタ
  //! @param [in] カーネルの一辺のサイズ
  Filter(const int size) {

    m_filter.resize(size, std::vector<float>(size, 0));
  }

  //! @brief フィルタの数値を設定する関数
  //! @param [in] row 行番号
  //! @param [in] 一行分のデータ
  //! @return なし
  void set(int row, std::initializer_list<float> values) {

    int i = 0;
    for (auto v : values) {
      m_filter[row][i] = v;
      i++;
    }
  }

  //! @brief フィルタの全ての要素を割り算する
  //! @param [in] f 割る数
  void operator/=(const float f) {
    for (auto&& row : m_filter) {
      for (auto&& c : row) {
        c /= f;
      }
    }
  }

  //! @brief フィルタのカーネルの一辺のサイズ
  int size() const{ return m_filter.size(); }

  //! @brief フィルタの要素を取得
  //! @param [in] x -size()/2 から size()/2 までの整数
  //! @param [in] y -size()/2 から size()/2 までの整数 
  float get(int x, int y)const {
    int sz = size() / 2;
    return m_filter[x + sz][y + sz];
  }

  int posmin()const { return -size() / 2; }

  int posmax()const { return size() / 2; }

};
      
struct image {
  unsigned char* src;
  int width;
  int height;
  int pixelsize;
};
      
//! @brief 画像にフィルタを適用
//! @param [in] filter 画像フィルタ
//! @param [in] x フィルタを適用する画素の座標
//! @param [in] y フィルタを適用する画素の座標
//! @param [in] src 元画像
//! @param [in] ret 結果画像
void apply(const Filter& filter,int x, int y,const image& src, unsigned char* ret) {

  const int posmin = filter.posmin();
  const int posmax = filter.posmax();

  const int pixSize = src.pixelsize;

  unsigned char* retp= &ret[pixSize * (y * src.width + x)];
  for (int i = 0; i < pixSize; i++) {
    retp[i] = 0;
  }

  for (int fx = posmin; fx <= posmax; fx++) {
    for (int fy = posmin; fy <= posmax; fy++) {

      float g = filter.get(fx, fy);

      int yy = y + fy;
      int xx = x + fx;

      if (yy < 0 || xx < 0)
        continue;

      unsigned char* s = &src.src[pixSize * (yy * src.width + xx)];
 
      for (int i = 0; i < pixSize; i++) {
        retp[i] += s[i]*g;
      }
    }
  }

}
      
int main()
{

  int width;
  int height;
  int vmax;

  // 画像を読み込む
  unsigned char * img_src = ppmP3_read(
    "C:\\dev\\c.ppm",
    &width,
    &height,
    &vmax,
    [](const size_t count) {return new unsigned char[count]; }
  );
  std::vector<unsigned char> img_dst(width * height * 3);

#define F1
  //フィルタ作成
#ifdef F0 
  Filter ff(3);
  ff.set(0, { 1,2,1 });
  ff.set(1, { 2,4,2 });
  ff.set(2, { 1,2,1 });
  ff /= 16.f;
#elif defined(F1)
  Filter ff(5);
  ff.set(0, { 1, 4, 6, 4,1 });
  ff.set(1, { 4,16,24,16,4 });
  ff.set(2, { 6,24,36,24,6 });
  ff.set(3, { 4,16,24,16,4 });
  ff.set(4, { 1, 4, 6, 4,1 });
  ff /= 256.f;
#elif defined(F2)
  Filter ff(7);
  ff.set(0, {  1,  6, 15, 20, 15,  6,  1 });
  ff.set(1, {  6, 36, 90,120, 90, 36,  6 });
  ff.set(2, { 15, 90,225,300,225, 90, 15 });
  ff.set(3, { 20,120,300,400,300,120, 20 });
  ff.set(4, { 15, 90,225,300,225, 90, 15 });
  ff.set(5, { 6,  36, 90,120, 90, 36,  6 });
  ff.set(6, { 1,   6, 15, 20, 15,  6,  1 });
  ff /= 4096.f;

#endif

  //全てのピクセルにフィルタを適用
  for (size_t x = 0; x < width; x++) {
    for (size_t y = 0; y < height; y++) {
      apply(ff,x, y, image{ img_src, width,height,3 }, img_dst.data());
    }
  }

  //フィルタをかけた画像を保存
  pnmP3_Write("C:\\dev\\e.ppm", 255, width, height, img_dst.data());


  delete[]img_src;

}

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: