Processingで魚眼

魚眼のことがちょっとだけ分かった。Processingたのしい。

魚眼でレナさん

f:id:licheng:20181116083006p:plain

メモ

f:id:licheng:20181116200111j:plain

スケッチ

PImage srcImg; // 元画像
PImage dstImg; // 処理後の画像
int W,H; // 画像のサイズ
int R; // レンズの半径
int D; // レンズの中心から投影面までの距離

void settings() {
  // Processing 3系ではsizeに変数を使う場合は
  // setup()でははくsettings()で
  srcImg = loadImage("lena.jpg");
  W = srcImg.width;
  H = srcImg.height;
  R = int(W * 0.6);
  D = int(R * 0.3); // 小さいほど大きく歪む
  dstImg = createImage(W, H, RGB);
  size(W, H);
}

void setup() {
}

void draw() {
  // マウス座標をレンズの中心とする
  int x0 = mouseX;
  int y0 = mouseY;

  float x,y; //写像前の座標
  // 写像後の座標
  for(int Y = 0; Y < H; Y++){
    for(int X = 0; X < W; X++){
      color c;
      
      // レンズの中心からの相対座標
      int dX = X - x0;
      int dY = Y - y0;
      float d = sqrt(dX*dX + dY*dY);
      if(d <= R){
        // 写像:元画像→魚眼画像
        // X = R*x/√(D^2+x^2+y^2)
        // Y = R*y/√(D^2+x^2+y^2)
        // 逆写像:魚眼画像→元画像
        // x = D*X/√(R^2-X^2-Y^2)
        // y = D*Y/√(R^2-X^2-Y^2)
        float Z = sqrt(R*R - dX*dX - dY*dY);
        x = x0 + (D*dX) / Z;
        y = y0 + (D*dY) / Z;
        
        if(x>=0 && x<W && y>=0 && y<H){
          c = srcImg.get(int(x), int(y));
        }else{
          c = color(0); // 元画像の外側なら黒塗り
        }
      }else{
        c = color(0); // レンズの外側なら黒塗り
      }
      dstImg.set(X, Y, c);
    }
  }
  image(dstImg, 0, 0);
}