主要分为两个步骤
1.把视屏图像转为二次元图像
2.在正确的位置显示二次元图像
把视屏图像转为二次元图像
图像变化工具
在iOS中进行图像变换,这次我们使用OpenCV,也可以使用CIFilter和GPUImage滤镜,如果追求更炫酷的效果使用深度学习亦可。
图像变换的流程
我们在ARKit的Frame中获取的图片文件格式CVPixelBufferRef,首先需要把它转化为cv::Mat,然后用OpenCV的滤镜对图片进行一系列的转化,最后把生成的cv::Mat转换为UIImage贴到我们创建好的模型上。
CVPixelBufferRef转cv::Mat
iOS视频流中获取的CVPixelBufferRef采用的是YUV420格式,这是我遇到的第一个坑,不熟悉YUV420格式的同学需要自行去了解一下。YUV420转灰度图非常容易,直接提取Y plane的数据即可:
+ (cv::Mat) matFromImageBuffer: (CVImageBufferRef) buffer {
CVPixelBufferLockBaseAddress(buffer, 0);
void *address = CVPixelBufferGetBaseAddressOfPlane(buffer,0);
CGFloat cols = CVPixelBufferGetWidth(buffer);
CGFloat rows = (int) CVPixelBufferGetHeight(buffer);
cv::Mat cvMat(rows, cols, CV_8UC1, address, 0);
CVPixelBufferUnlockBaseAddress(buffer, 0);
return cvMat;
}
YUV420转RGB图就有些麻烦,需要对每个像素进行计算,突出的问题就是性能。因为在这个App中对彩图的细节没有要求,下面代码在转换的过程中把图片缩小到原图的16分之一。
OpenCV滤镜处理
网上有很多OpenCV滤镜处理的代码,选一些合适的即可,需要注意的是处理过程中如果使用了灰度图,处理结束时要转换回RGB色域。
我使用的滤镜代码
cv::Mat转换为UIImag
在正确的位置显示二次元图像
首先是在ARkit中添加一扇门,由一个SCNPlane和三个SCNBox组成。门有两种显示状态,视点在门里、视点在门外。
最初的方案是给SCNPlane贴图,裁剪出门应该显示的图像然后贴在SCNPlane上,结果效果不好,结症是门上贴图分辨率问题,尤其是距离门很近的时候。
替换方案是始终在视角的正前方放置一个屏幕,调整屏幕大小和距离使其看起来的大小和显示屏相当(视锥的一个截面)。
设置门里门外对这个屏幕的遮挡关系。
网友评论