作为一份小小的礼物,我想向你展示借助 Ogre 和 OpenCV 自己制作增强现实变得多么容易。你应该知道,除了图形之外,我的另一个兴趣是计算机视觉。
演示将不依赖于 ARCore 或 ARKit 等专有解决方案 - 所有这些都将使用开源代码完成,你可以检查并学习。点击这里查看成品视频。
由于 OpenCV ovis 模块将 Ogre 和 OpenCV 结合在一起,这个演示可以在不到 50 行代码中完成。接下来,我将简要介绍所需的步骤。
NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割
1、视频捕捉
首先,我们必须捕获一些图像才能通过 AR 中的现实部分。在这里,OpenCV 为我们提供了一个统一的 API,你可以将其用于网络摄像头、工业相机或预先录制的视频:
import cv2 as cv
imsize = (1280, 720) # the resolution to use
cap = cv.VideoCapture(0)
cap.set(cv.CAP_PROP_FRAME_WIDTH, imsize[0])
cap.set(cv.CAP_PROP_FRAME_HEIGHT, imsize[1])
img = cap.read()[1] # grab an image
2、相机跟踪
然后,我们必须设置 AR 中最关键的部分:摄像头跟踪。为此,我们将使用 ArUco 标记 - 围绕 Sinbad 的 QR 状四边形。毫不奇怪,OpenCV 附带了这种视觉算法:
adict = cv.aruco.Dictionary_get(cv.aruco.DICT_4X4_50)
# extract 2D marker-corners from image
corners, ids = cv.aruco.detectMarkers(img, adict)[:2]
# convert corners to 3D transformations [R|t]
rvecs, tvecs = cv.aruco.estimatePoseSingleMarkers(corners, 5, K, None)[:2]
如果仔细观察代码,就会发现我们使用了一个未定义的变量“K”——这是相机特有的内参矩阵。如果你想要精确的结果,则应校准相机以测量这些结果。例如,使用 calibdb.net 上的网络服务,如果你的相机已知,它也会为你提供参数。
但是,如果你只是想继续,则可以使用以下值,这些值应大致匹配 1280x720px 的任何网络摄像头:
import numpy as np
K = np.array(((1000, 0, 640), (0, 1000, 360), (0, 0, 1.)))
3、添加3D模型
现在我们有了图像和相应的相机 3D 变换——只缺少增强部分。这就是 Ogre/ovis 发挥作用的地方:
# reference the 3D mesh resources
cv.ovis.addResourceLocation("packs/Sinbad.zip")
# create an Ogre window for rendering
win = cv.ovis.createWindow("OgreWindow", imsize, flags=cv.ovis.WINDOW_SCENE_AA)
win.setBackground(img)
# make Ogre renderings match your camera images
win.setCameraIntrinsics(K, imsize)
# create the virtual scene, consisting of Sinbad and a light
win.createEntity("figure", "Sinbad.mesh", tvec=(0, 0, 5), rot=(1.57, 0, 0))
win.createLightEntity("sun", tvec=(0, 0, 100))
# position the camera according to the first marker detected
win.setCameraPose(tvecs[0].ravel(), rvecs[0].ravel(), invert=True)
你可以在这里找到上述步骤的完整源代码,它们完美地组合到主循环中。或者,查看此 Ogre 示例,它适用于通过 pip 安装的 Ogre 和 OpenCV。
要记录结果,你可以使用 win.getScreenshot()
并将其转储到 cv.VideoWriter
中 - 与名称相反,这是实时工作的。
扩展上述代码以使用 cv.aruco.GridBoard
(如视频中所示)留给读者作为练习,因为这更多是在 OpenCV 方面。
此外,如果你更愿意在 Android 上使用 ARCore,有一个示例介绍如何将 SurfaceTexture 与 Ogre 结合使用。使用此示例,你应该能够修改 arcore-sdk 中的 hello_ar_java 示例以使用 Ogre。