Android原生实现:将视频叠加至检测图像对应顶点的技术问询
Android原生实现视频叠加到检测目标顶点位置的方案
核心思路
基于你已有的目标检测能力(支持3D模型/形状叠加),替换渲染载体为视频帧,通过视频解码+坐标映射+实时渲染三个核心环节实现需求,以下是具体步骤:
1. 视频帧解码(原生方式)
优先用MediaCodec做硬件解码,高效获取视频帧:
// 初始化MediaCodec解码器 val codec = MediaCodec.createDecoderByType("video/avc") val format = MediaFormat.createVideoFormat("video/avc", videoWidth, videoHeight) codec.configure(format, surface, null, 0) codec.start() // 解码循环中获取帧数据 while (true) { val inputBufferIndex = codec.dequeueInputBuffer(10000) if (inputBufferIndex >= 0) { // 填充视频数据到输入缓冲区 val inputBuffer = codec.getInputBuffer(inputBufferIndex) // ... 读取视频文件/流数据写入inputBuffer codec.queueInputBuffer(inputBufferIndex, 0, dataSize, presentationTimeUs, 0) } val outputBufferInfo = MediaCodec.BufferInfo() val outputBufferIndex = codec.dequeueOutputBuffer(outputBufferInfo, 10000) if (outputBufferIndex >= 0) { // 获取解码后的帧(若用Surface渲染则直接输出到Surface,若需处理帧可转Bitmap) codec.releaseOutputBuffer(outputBufferIndex, true) } }
如果需要更便捷的播放控制,也可以用ExoPlayer配合TextureView获取视频帧的SurfaceTexture。
2. 坐标映射与视频贴合
根据你的检测类型(2D图像检测/3D AR检测),选择对应的渲染方式:
2D图像检测场景
用Canvas的网格变形API,将视频帧贴合到检测到的不规则顶点区域:
// 假设targetVertices是检测到的4个顶点(按左上、右上、右下、左下顺序) val videoFrame: Bitmap = // 解码得到的视频帧 val meshVertices = FloatArray(8) // 存储4个点的x,y坐标 targetVertices.forEachIndexed { index, point -> meshVertices[2 * index] = point.x meshVertices[2 * index + 1] = point.y } // 绘制变形后的视频帧 canvas.drawBitmapMesh(videoFrame, 1, 1, meshVertices, 0, null, 0, null)
3D AR检测场景
复用你之前渲染3D模型的OpenGL ES流程,将视频帧作为纹理映射到平面Mesh上:
- 创建一个带纹理坐标的平面Mesh(和3D模型的顶点数据结构一致);
- 将解码后的视频帧更新到OpenGL纹理中;
- 根据检测到的目标顶点计算平面的模型矩阵(位置、旋转、缩放),确保平面完全贴合目标;
- 在
GLSurfaceView.Renderer的onDrawFrame中绘制该带视频纹理的平面。
3. 性能与同步优化
- 用硬件解码+纹理共享(
SurfaceTexture)减少数据拷贝,避免CPU过载; - 同步视频解码帧率与目标检测帧率,避免画面卡顿或错位;
- 动态调整视频帧的宽高比,匹配目标区域的比例,防止拉伸变形。
内容的提问来源于stack exchange,提问作者Ravi Maniyar
相关产品推荐
相关产品推荐

