ARCore与OpenGL增强图像场景下视频位置校准求助:如何将视频精准显示在识别到的图片帧内
嘿,第一次接触ARCore和OpenGL确实会有点绕,别担心,咱们一步步来解决这个视频位置不对的问题。核心问题其实是你的视频渲染四边形没有和增强图像的尺寸、位置正确对齐,下面是具体的解决思路和代码调整建议:
1. 基于增强图像的真实尺寸调整模型矩阵
你现在直接用了movieAnchor.getPose()的矩阵,但这个矩阵只提供了图像的位置和姿态,没有考虑图像本身的大小。ARCore的AugmentedImage类提供了getExtentX()(图像宽度,X轴方向)和getExtentZ()(图像高度,Z轴方向)方法,我们需要用这两个值来缩放视频渲染的四边形,让它刚好覆盖增强图像。
修改你drawAugmentedImages中的模型矩阵构建代码:
private void drawAugmentedImages(Frame frame, float[] projmtx, float[] viewmtx, float[] colorCorrectionRgba) { switch (augmentedImage.getTrackingState()) { case TRACKING: if (movieAnchor != null) { if (!viewRenderer.isStarted()) { viewRenderer.play("testvideo.mp4", this); } float[] modelMatrix = new float[16]; // 获取增强图像的中心姿态(代替anchor的pose,确保对齐图像中心) augmentedImage.getCenterPose().toMatrix(modelMatrix, 0); // 获取图像的真实尺寸 float imageWidth = augmentedImage.getExtentX(); float imageHeight = augmentedImage.getExtentZ(); // 创建缩放矩阵:将单位四边形缩放到图像的实际大小 float[] scaleMatrix = new float[16]; Matrix.setIdentityM(scaleMatrix, 0); // 假设你的ViewRenderer中默认四边形是1x1的单位正方形(顶点从-0.5到0.5) Matrix.scaleM(scaleMatrix, 0, imageWidth, imageHeight, 1.0f); // 将姿态矩阵和缩放矩阵相乘,得到最终的模型矩阵 Matrix.multiplyMM(modelMatrix, 0, modelMatrix, 0, scaleMatrix, 0); viewRenderer.update(modelMatrix); viewRenderer.draw(viewmtx, projmtx); } // ... 其他代码 } }
这里建议直接用augmentedImage.getCenterPose()而不是anchor的pose,因为anchor是绑定在图像上的,但中心姿态能更准确地对齐图像的中心点。
2. 检查ViewRenderer中的顶点坐标定义
你的ViewRenderer里的mQuadVertices(视频渲染的四边形顶点)决定了基础的四边形大小。如果默认的顶点是{-0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 0.0f}这样的单位正方形,那上面的缩放矩阵刚好能让它匹配图像尺寸。如果你的顶点是{-1f, -1f, 0.0f, ...}这样的2x2大小,那缩放矩阵需要改成imageWidth/2和imageHeight/2。
可以检查ViewRenderer中初始化mQuadVertices的代码,确保基础四边形是单位大小,这样后续的缩放计算更直观。
3. 对齐纹理坐标与图像宽高比(可选,解决拉伸问题)
如果你的视频和增强图像的宽高比不一致,视频会出现拉伸。你可以在setVideoDimensions方法中调整纹理坐标,让视频保持原比例,同时在图像范围内显示(比如加黑边)。这部分不是当前位置问题的核心,但解决位置后可以优化:
private void setVideoDimensions(float[] texMatrix, float imageAspect) { // 获取视频的宽高比 float videoAspect = (float) videoWidth / videoHeight; float scaleX = 1.0f; float scaleY = 1.0f; if (videoAspect > imageAspect) { // 视频更宽,按高度缩放,宽度裁剪 scaleX = imageAspect / videoAspect; } else { // 视频更高,按宽度缩放,高度裁剪 scaleY = videoAspect / imageAspect; } // 调整纹理坐标的缩放 Matrix.scaleM(texMatrix, 0, scaleX, scaleY, 1.0f); }
调用时把增强图像的宽高比augmentedImage.getExtentX() / augmentedImage.getExtentZ()传进去即可。
4. 参考ARCore示例的渲染逻辑
ARCore的Augmented Image示例中,AugmentedImageRenderer的draw方法里有完整的图像渲染逻辑,核心就是根据图像尺寸调整模型矩阵。你可以对比它的代码,确认自己的缩放和位移逻辑是否正确:
示例中的关键代码片段:
// 构建模型矩阵:平移+缩放 Matrix.translateM(modelMatrix, 0, 0.0f, 0.0f, image.getExtentZ() / 2); Matrix.scaleM(modelMatrix, 0, image.getExtentX(), image.getExtentX(), image.getExtentZ());
这个逻辑和我们上面的思路一致,都是先定位到图像中心,再缩放匹配图像大小。
5. 调试模型矩阵(排查问题)
如果调整后还是不对,可以打印modelMatrix的数值,或者计算视频四边形四个顶点的世界坐标,和增强图像的四个角坐标对比(用augmentedImage.getCornerPose(0)到getCornerPose(3)获取四个角的姿态),看看是否对齐。这样能快速定位是缩放不对还是位置偏移。
内容的提问来源于stack exchange,提问作者FlorianLv1

