1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

p5.js でカメラ画像のアスペクト比は保ちつつキャンバスにピッタリ合うように表示位置・サイズを調整する

Posted at

記事の内容はタイトルの通りです。

p5.js でカメラ画像を使った作品をよく使うのですが、例えば以下のようなシェーダーを絡めた処理や、その他 AI・機械学習を組み合わせた処理を行った場合に、解像度の高い画像を使うと処理が重たくなることがあります。

その場合に、処理する画像の解像度をあまり高くしないで処理するということがありました。
一方で、展示イベントなどに出した際に、カメラ映像は 640x480 などの解像度を使ったとしても表示上は画面いっぱいか、それに近いサイズで表示させたいという場合があります(※ カメラ画像のアスペクト比は変えないようにしつつ)。

このような場合に、処理する画像は画面いっぱいのサイズより小さいものを使っていても、表示では画面いっぱいに表示する、ということを行うプログラムをメモとして残してみます。

パターン1: キャンバスサイズが固定

まずはキャンバスサイズが固定の場合の例です。

まずはプログラムを示します。こちらは、キャンバスのサイズは 700x800(や、900x500)で、それに対してカメラ画像は 640x480 のサイズにしたものです。

let capture;

function setup() {
  createCanvas(700, 800);
  // createCanvas(900, 500);

  capture = createCapture(VIDEO);
  capture.size(640, 480);
  capture.hide();
}

function draw() {
  background(220);

  // キャンバスとカメラ映像のアスペクト比に基づくスケーリング比を計算
  let scaleX = width / capture.width;
  let scaleY = height / capture.height;
  let scale = min(scaleX, scaleY); // 幅と高さの比率のうち、小さい方を選択

  // スケーリングされた映像のサイズを計算
  let scaledWidth = capture.width * scale;
  let scaledHeight = capture.height * scale;
  // スケーリングされた映像を中央に配置するためのもの
  let offsetX = (width - scaledWidth) / 2;
  let offsetY = (height - scaledHeight) / 2;

  image(capture, offsetX, offsetY, scaledWidth, scaledHeight);
}

内容的には、以下のようなことをやっています。

  1. カメラ画像のアスペクト比を保ってキャンバスサイズの縦・横のそれぞれに合わせてスケーリングした場合の、比率の値が小さい方を選択
  2. 上記の比率を使ってカメラ画像をスケーリング
  3. スケーリングしたカメラ画像を画面中央に表示するような、画像描画の基準点からのオフセットを計算
  4. 上で求めたパラメータを使ってカメラ画像を表示

これを実行すると、以下のようにカメラ映像をスケーリングした後キャンバス上で余った部分が、カメラ画像の上下か左右のどちらかに均等に割りふられる形になっているのが分かります。

image.png

これで、スケーリングした後のカメラ画像が、キャンバスの中央に表示されました。

パターン2: キャンバスサイズがウィンドウサイズに合わせて変わる場合(リサイズも考慮)

次は、キャンバスサイズがウィンドウサイズに合わせたものになる場合です。
そして、リサイズが行われた場合の対処も考慮します。

メインの処理部分は、上で提示したものとあまり変わらないのですが、プログラムは以下のようになります。

let capture;
let scale;
let offsetX, offsetY;

function setup() {
  createCanvas(windowWidth, windowHeight);

  capture = createCapture(VIDEO);
  capture.size(640, 480);
  capture.hide();

  calculateLayout();
}

function draw() {
  background(220);

  image(
    capture,
    offsetX,
    offsetY,
    capture.width * scale,
    capture.height * scale
  );
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  calculateLayout();
}

function calculateLayout() {
  // キャンバスとカメラ映像のアスペクト比に基づくスケーリング比を計算
  scale = min(width / capture.width, height / capture.height);

  // スケーリングされた映像のサイズを計算
  let scaledWidth = capture.width * scale;
  let scaledHeight = capture.height * scale;

  // スケーリングされた映像を中央に配置するためのオフセットを計算
  offsetX = (width - scaledWidth) / 2;
  offsetY = (height - scaledHeight) / 2;
}

windowResized() の処理の際にも、スケーリングの比率・オフセットの再計算をする、というのを忘れず行う必要があります。

こちらの実行結果は省略しますが、ウィンドウサイズを変更しても、カメラ画像のアスペクト比は維持されつつキャンバスに合わせてスケーリングされる、という結果を確認できます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?