LoginSignup
9
3

More than 1 year has passed since last update.

OpenCVとMatplotlibでAR(拡張現実)する

Last updated at Posted at 2022-12-12

OpenCVとMatplotlibでAR(拡張現実)できるか挑戦してみた

去年のアドベントカレンダーでは100行で作るARと題して、できるだけシンプルにARを実装する挑戦をしました。
今年は、MatplotlibでARを実装する挑戦をしました。
OpenCVで3Dデータを用いたARにはOpenGLを使うことがよくあると思いますが、OpenGLを使用せずMatplotlibの3DグラフでARができないか挑戦しました。

完成デモ

完成したものはこちらです。ARで描画しているのはMatplotlibの3Dグラフです。ARマーカーの傾きに応じグラフの見え方も変わっているのがわかるでしょうか。


ここから作り方について紹介します。

環境

Windows11(カメラ付き)でPython3.10を使用しました。

PS C:\> python --version
Python 3.10.8

コードはgithubにあります

コード類はgithubに格納しました。

環境の準備

Windows環境の準備

PowerShellで以下のコマンドを実行しPythonの必要モジュールをインストールします。

最初にvenv環境を作り、作成したvenv環境OpenCVMatplotlibARを起動します。

mkdir .venv
cd .venv
python -m venv OpenCVMatplotlibAR
PS C:\Users\hoge> .venv\OpenCVMatplotlibAR\Scripts\Activate.ps1
(OpenCVMatplotlibAR) PS C:\Users\hoge> 

venv環境 OpenCVMatplotlibARに必要モジュールをインストールします。
モジュールのインストールは本コードをまとめたgithubのrequirementsファイルを使用します。

(OpenCVMatplotlibAR) PS C:\Users\hoge> cd repo
(OpenCVMatplotlibAR) PS C:\Users\hoge\repo> git clone https://github.com/zgw426/AugmentedReality_with_OpenCV_Matplotlib.git
(OpenCVMatplotlibAR) PS C:\Users\hoge\repo> cd AugmentedReality_with_OpenCV_Matplotlib
(OpenCVMatplotlibAR) PS C:\Users\hoge\repo\AugmentedReality_with_OpenCV_Matplotlib> pip install -r requirements_fixed-version.txt

これでWindows環境の準備は完了です。

ARマーカーの準備

ARマーカーの作成は、こちらの記事を参考に0番と1番の画像を作成します。

これでARマーカーの準備は完了です。

実行してみる

実際にコードを実行してみます。

Step01.2DのMatplotlibグラフでARする

スクリプトが動作するかの確認です。元画像sample.pngに対しARを実行し、その結果をout-sample.pngとして出力します。

(OpenCVMatplotlibAR) PS C:\Users\hoge\repo\AugmentedReality_with_OpenCV_Matplotlib> python 01_matplot2d_not-camera.py
DONE : 
        inputfile is sample.png
        outputfile is out-sample.png
(OpenCVMatplotlibAR) PS C:\Users\hoge\repo\AugmentedReality_with_OpenCV_Matplotlib>

以下は、元画像sample.pngと出力画像out-sample.pngです。
このように、ARマーカーにグラフが描画されれば成功です。

image.png

Step02.カメラ映像と2DのMatplotlibグラフでARする

Windows搭載のカメラからの映像にMatplotlibグラフをARで描画します。以下を実行するとウィンドウが開きカメラ映像が表示されます。ARマーカーを映すと2Dグラフが描画されます。

(OpenCVMatplotlibAR) PS C:\Users\hoge\repo\AugmentedReality_with_OpenCV_Matplotlib> python 02_matplot2d_no-transparency.py

この動画のように2Dグラフが表示されれば成功です。
開いたウィンドうは q キーで終了します。

Step03.3DのMatplotlibグラフでARする

次は3DグラフでARします。

(OpenCVMatplotlibAR) PS C:\Users\hoge\repo\AugmentedReality_with_OpenCV_Matplotlib> python 03_matplot3d_no-transparency.py

この動画のように3Dグラフが表示されれば成功です。
開いたウィンドうは q キーで終了します。

Step04.3Dの透過処理を追加してMatplotlibグラフでARする

Step03では白い背景色のため立体物を描画してる感じがしないので背景を透過します。またグラフの軸や目盛も不要なので消しました。

(OpenCVMatplotlibAR) PS C:\Users\hoge\repo\AugmentedReality_with_OpenCV_Matplotlib> python 04_matplot3d_transparency.py

この動画のように3Dグラフが表示されれば成功です。
開いたウィンドうは q キーで終了します。

※Step04は冒頭で紹介したデモと同じです。

補足

3DグラフでAR(Step03, Step04)の仕組みを簡単に説明します。
要はARマーカーの傾きにあわせて3Dグラフも傾けています。

  • Step03の処理フロー概要
    • (1) ARマーカーを検出した際にARマーカーの傾きを算出
    • (2) 算出した傾きをもとに3Dグラフの傾ける
    • (3) 3Dグラフの画像を生成
    • (4) 生成した画像をARマーカーにマッピング

3Dグラフの作成と画像生成は以下の関数で実施しています。引数のroll_elev,pitch_azimがARマーカーの傾きから算出した値です。

ARマーカーに傾きに応じた3Dグラフの生成
def graph_3d(roll_elev, pitch_azim):
    t = np.linspace(0, np.pi * 4, 50)
    x = np.cos(t)
    y = np.sin(t)
    z = np.linspace(0,1,50)

    fig = plt.figure()
    ax = fig.add_subplot(projection='3d')
    ax.view_init(elev=roll_elev, azim=pitch_azim)

    plt.cla()
    ax.plot(x, y, z, marker='o', markersize=5, color='blue')

    fig.canvas.draw()
    img_array = np.array(fig.canvas.renderer.buffer_rgba())
    img_return = cv2.cvtColor(img_array, cv2.COLOR_RGBA2BGR)

    # メモリ解放
    plt.clf()
    plt.close()

    return img_return

Step04は、Step03の処理フロー(4)にて透過処理を追加で行います。
透過処理の関数はこちらです。

透過処理の関数
def putSprite_npwhere(back, front4, pos):
    """透過処理"""
    x, y = pos
    fh, fw = front4.shape[:2]
    bh, bw = back.shape[:2]
    x1, y1 = max(x, 0), max(y, 0)
    x2, y2 = min(x+fw, bw), min(y+fh, bh)
    if not ((-fw < x < bw) and (-fh < y < bh)) :
        return back
    front3 = front4[:, :, :3]
    front_roi = front3[y1-y:y2-y, x1-x:x2-x]
    roi = back[y1:y2, x1:x2]
    tmp = np.where((front_roi==(255,255,255))|(front_roi==(0,0,0)), roi, front_roi)  # 255x3:黒, 0x3:白
    back[y1:y2, x1:x2] = tmp

    return back

今回は以上です。
起動したvenv環境OpenCVMatplotlibARdeactivateコマンドで終了します。

(OpenCVMatplotlibAR) PS C:\Users\hoge\repo\AugmentedReality_with_OpenCV_Matplotlib> deactivate
PS C:\Users\hoge\repo\AugmentedReality_with_OpenCV_Matplotlib> 

今後もOpenCVでARを挑戦していきます

今回はMatplotlibでしたが、他の画像生成系のモジュールでもに同様のことができそうに思いました。他のモジュールでも挑戦しようかと思います。

自己紹介

OpenCVで壁に穴をあけたりしています。こちらのデモは2枚の壁に穴をあけています。いつか高層ビルの1階から屋上まで穴をあけたいと思っています。

9
3
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
9
3