OpenCVで没入型拡張現実体験を作成する方法

拡張現実(AR)は、現実世界環境にデジタル情報を重ね合わせることによって現実と仮想コンテンツを融合します。近年、コンピュータビジョンと画像処理の進歩により、ARアプリケーションの開発が容易になりました。

OpenCVは人気の高いオープンソースのコンピュータビジョンライブラリです。魅力的なAR体験を作成するのに役立つツールとアルゴリズムを提供します。ARプログラムを作成するには、投影画像を選択し、物理的なプレースホルダオブジェクトを検出し、ARコンテンツを投影してレンダリングします。

環境の設定

コーディングを開始する前に、開発環境を準備する必要があります。まず、仮想環境を作成してから、このターミナルコマンドを実行してNumPyとOpenCVをインストールします。

pip install opencv-contrib-python numpy

コンピュータビジョンの機能にはOpenCVを使用し、コードの後半でNumPyを使用してホモグラフィー行列を計算します。

opencv-contrib-pythonライブラリをインストールし、opencv-pythonをインストールしないようにしてください。これは、opencv-pythonには、拡張現実プログラムを作成するために大きく依存するcv2.arucoモジュールがないためです。

完全なソースコードはGitHubリポジトリにあります。

必要なライブラリのインポート

新しいPythonファイルを作成します。スクリプトの冒頭で、OpenCVとNumPyをインポートします。

import numpy as np
import cv2

これらのライブラリをインポートすると、コード内でその関数を呼び出すことができます。

オーバーレイ画像の選択

ARシーンに仮想オブジェクトをレンダリングするときは、アプリケーションが検出されたマーカーに投影する画像が必要です。cv2.imread関数を使用してオーバーレイ画像を読み込みます。

overlay_image = cv2.imread('your_overlay_image.jpg')

3Dモデルを動的に生成するなど、他の方法を使用してオーバーレイ画像を取得することもできます。

ArUcoマーカーの検出

オーバーレイ画像を選択したら、ビデオフィード内で画像をオーバーレイする位置を決定する必要があります。ここで、ArUcoマーカーの出番です。ArUcoマーカーは、コンピュータビジョンのアルゴリズムで簡単に検出できる一意のIDパターンを持つ正方形のマーカーです。

アプリがマーカーを検出すると、その場所に画像を投影するなど、応答できます。以下は、ArUcoマーカーの例です。

ビデオフィード内のArUcoマーカーを検出する関数を作成します。この関数は、ビデオフィードをグレースケールに変換する必要があります。次に、マーカーサイズとマーカーの合計数に基づいてArUco辞書を取得します。最後に、フィード内のマーカーを検出する必要があります。

def findArucoMarkers(image, markerSize=6, totalMarkers=250):
# Convert the image to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Get the Aruco dictionary based on the marker size and total markers
dictionary_key = getattr(cv2.aruco, f'DICT_{markerSize}X'
f'{markerSize}_{totalMarkers}')
aruco_dictionary = cv2.aruco.getPredefinedDictionary(dictionary_key)
# Set the Aruco detector parameters
aruco_params = cv2.aruco.DetectorParameters()
# Detect Aruco markers in the grayscale image
marker_corners, marker_ids, _ = cv2.aruco.detectMarkers(gray, aruco_dictionary,
parameters=aruco_params)
return marker_corners, marker_ids

この関数は、検出されたマーカーのコーナーとIDを返します。

マーカーへのオーバーレイ画像の投影

ビデオフレーム内のマーカーを検出したら、オーバーレイ画像をマーカーに投影する必要があります。これを実現するには、画像とビデオフレーム間のホモグラフィー行列を計算する関数を作成します。これは、オーバーレイ画像をビデオフレーム内の検出されたArUcoマーカーに揃える幾何学的変換を確立するためです。

次に、ホモグラフィーに基づいてオーバーレイ画像を変形する必要があります。次に、オーバーレイ領域を定義するためのマスクを作成し、最後に、マスクされたオーバーレイ画像をビデオフレームとブレンドします。

def superimposeImageOnMarkers(video_frame, aruco_markers, overlay_image,
video_width, video_height):
frame_height, frame_width = video_frame.shape[:2]
if len(aruco_markers[0]) != 0:
for i, marker_corner in enumerate(aruco_markers[0]):
marker_corners = marker_corner.reshape((4, 2)).astype(np.int32)
# マーカーの角の周りにポリゴンを描画します
cv2.polylines(video_frame, [marker_corners], True, (0, 255, 0), 2)
# マーカーの左上の角にマーカーIDをテキストとして追加します
cv2.putText(video_frame, str(aruco_markers[1][i]),
tuple(marker_corners[0]),
cv2.FONT_HERSHEY_SIMPLEX,0.5, (0, 255, 0), 2)
# ホモグラフィー行列を検出して、オーバーレイ画像をマーカーにマッピングします
homography_matrix, _ = cv2.findHomography(
np.array([[0, 0], [video_width, 0], [video_width, video_height],
[0, video_height]], dtype="float32"), marker_corners)
# ホモグラフィー行列を使用して、オーバーレイ画像をマーカーに揃えて変形します
warped_image = cv2.warpPerspective(overlay_image, homography_matrix,
(frame_width, frame_height))
# マスクを作成して、変形された画像をマーカー領域にのみ適用します
mask = np.zeros((frame_height, frame_width), dtype="uint8")
cv2.fillConvexPoly(mask, marker_corners, (255, 255, 255), cv2.LINE_AA)
masked_warped_image = cv2.bitwise_and(warped_image, warped_image,
mask=mask)
# ビデオフレームに逆マスクを適用します
masked_video_frame = cv2.bitwise_and(video_frame, video_frame,
mask=cv2.bitwise_not(mask))
# マスクされた変形された画像とマスクされたビデオフレームを結合します
video_frame = cv2.add(masked_warped_image, masked_video_frame)
return video_frame

この関数は、検出されたArUcoマーカーにオーバーレイ画像を重ねたビデオフレームを返します。

ARコンテンツのレンダリング

ARコンテンツをレンダリングするには、マーカー検出と画像投影のステップを組み合わせた関数を作成します。この関数は、ビデオフレームを継続的にキャプチャし、ArUcoマーカーを検出する必要があります。次に、オーバーレイ画像をマーカーに重ね合わせる必要があります。

def processVideoFeed(overlay_image):
# ビデオフィードの寸法を設定します
video_height = 480
video_width = 640
# ビデオキャプチャを開きます
video_capture = cv2.VideoCapture(0)
# オーバーレイ画像を読み込んでリサイズします
overlay_image = cv2.resize(overlay_image, (video_width, video_height))
while video_capture.isOpened():
# ビデオキャプチャからフレームを読み取ります
ret, video_frame = video_capture.read()
if ret:
# ビデオフレーム内のArucoマーカーを検出します
aruco_markers = findArucoMarkers(video_frame, totalMarkers=100)
# ビデオフレーム内のマーカーにオーバーレイ画像を重ね合わせます
video_frame = superimposeImageOnMarkers(video_frame, aruco_markers,
overlay_image, video_width,
video_height)
# オーバーレイ付きのビデオフレームを表示します
cv2.imshow("Camera Feed", video_frame)
# ループを終了するための「q」キーの押下をチェックします
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()

この関数は、結果のビデオフレームを表示し、現実世界に仮想オブジェクトが表示されているという錯覚を生み出します。

プログラムを実行するには、processVideoFeed関数を実行します。

# ビデオフィードの処理を開始します
processVideoFeed(overlay_image)

このビデオで、プログラムの出力例を確認できます。

ビデオフィードのマーカーは、コードで指定したものと同じマーカーサイズとマーカーの合計プロパティを持つ必要があります。

拡張現実はどこで応用されているか

さまざまな業界や分野で、拡張現実を使用して顧客体験を向上させています。これらの業界で使用されているARアプリケーションにより、顧客は製品が現実世界でどのように見えるかを視覚化することができます。

テクノロジーを実用的に使用するには、このタイプのアプリケーションに慣れる必要があります。