主要分為兩個(gè)步驟
1.把視屏圖像轉(zhuǎn)為二次元圖像
2.在正確的位置顯示二次元圖像
把視屏圖像轉(zhuǎn)為二次元圖像
圖像變化工具
在iOS中進(jìn)行圖像變換,這次我們使用OpenCV,也可以使用CIFilter和GPUImage濾鏡,如果追求更炫酷的效果使用深度學(xué)習(xí)亦可。
圖像變換的流程
我們?cè)贏RKit的Frame中獲取的圖片文件格式CVPixelBufferRef,首先需要把它轉(zhuǎn)化為cv::Mat,然后用OpenCV的濾鏡對(duì)圖片進(jìn)行一系列的轉(zhuǎn)化,最后把生成的cv::Mat轉(zhuǎn)換為UIImage貼到我們創(chuàng)建好的模型上。
CVPixelBufferRef轉(zhuǎn)cv::Mat
iOS視頻流中獲取的CVPixelBufferRef采用的是YUV420格式,這是我遇到的第一個(gè)坑,不熟悉YUV420格式的同學(xué)需要自行去了解一下。YUV420轉(zhuǎn)灰度圖非常容易,直接提取Y plane的數(shù)據(jù)即可:
+ (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轉(zhuǎn)RGB圖就有些麻煩,需要對(duì)每個(gè)像素進(jìn)行計(jì)算,突出的問題就是性能。因?yàn)樵谶@個(gè)App中對(duì)彩圖的細(xì)節(jié)沒有要求,下面代碼在轉(zhuǎn)換的過程中把圖片縮小到原圖的16分之一。
OpenCV濾鏡處理
網(wǎng)上有很多OpenCV濾鏡處理的代碼,選一些合適的即可,需要注意的是處理過程中如果使用了灰度圖,處理結(jié)束時(shí)要轉(zhuǎn)換回RGB色域。
我使用的濾鏡代碼
cv::Mat轉(zhuǎn)換為UIImag
在正確的位置顯示二次元圖像
首先是在ARkit中添加一扇門,由一個(gè)SCNPlane和三個(gè)SCNBox組成。門有兩種顯示狀態(tài),視點(diǎn)在門里、視點(diǎn)在門外。
最初的方案是給SCNPlane貼圖,裁剪出門應(yīng)該顯示的圖像然后貼在SCNPlane上,結(jié)果效果不好,結(jié)癥是門上貼圖分辨率問題,尤其是距離門很近的時(shí)候。
替換方案是始終在視角的正前方放置一個(gè)屏幕,調(diào)整屏幕大小和距離使其看起來的大小和顯示屏相當(dāng)(視錐的一個(gè)截面)。
設(shè)置門里門外對(duì)這個(gè)屏幕的遮擋關(guān)系。