如何解决AR相机测距
我有一个关于 AR(增强现实)的问题。
我想知道如何显示 AR 相机和目标对象之间的距离信息(如中心计...)。 (使用智能手机)
我可以在 Unity 中做到这一点吗?我应该使用 AR Foundation 吗?和 ARcore?怎么写代码?
我试图找到一些相关代码(如下),但它似乎就像在对象和对象之间打印信息,与“AR 相机”无关...
var other : Transform;
if (other) {
var dist = Vector3.Distance(other.position,transform.position);
print ("Distance to other: " + dist);
}
再次感谢!
解决方法
这是 Unity 和 AR Foundation 4.1 的操作方法。 此示例脚本在深度纹理的中心打印以米为单位的深度,并适用于 ARCore 和 ARKit:
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
public class GetDepthOfCenterPixel : MonoBehaviour {
// assign this field in inspector
[SerializeField] AROcclusionManager manager = null;
IEnumerator Start() {
while (ARSession.state < ARSessionState.SessionInitializing) {
// manager.descriptor.supportsEnvironmentDepthImage will return a correct value if ARSession.state >= ARSessionState.SessionInitializing
yield return null;
}
if (!manager.descriptor.supportsEnvironmentDepthImage) {
Debug.LogError("!manager.descriptor.supportsEnvironmentDepthImage");
yield break;
}
while (true) {
if (manager.TryAcquireEnvironmentDepthCpuImage(out var cpuImage) && cpuImage.valid) {
using (cpuImage) {
Assert.IsTrue(cpuImage.planeCount == 1);
var plane = cpuImage.GetPlane(0);
var dataLength = plane.data.Length;
var pixelStride = plane.pixelStride;
var rowStride = plane.rowStride;
Assert.AreEqual(0,dataLength % rowStride,"dataLength should be divisible by rowStride without a remainder");
Assert.AreEqual(0,rowStride % pixelStride,"rowStride should be divisible by pixelStride without a remainder");
var numOfRows = dataLength / rowStride;
var centerRowIndex = numOfRows / 2;
var centerPixelIndex = rowStride / (pixelStride * 2);
var centerPixelData = plane.data.GetSubArray(centerRowIndex * rowStride + centerPixelIndex * pixelStride,pixelStride);
var depthInMeters = convertPixelDataToDistanceInMeters(centerPixelData.ToArray(),cpuImage.format);
print($"depth texture size: ({cpuImage.width},{cpuImage.height}),pixelStride: {pixelStride},rowStride: {rowStride},pixel pos: ({centerPixelIndex},{centerRowIndex}),depthInMeters of the center pixel: {depthInMeters}");
}
}
yield return null;
}
}
float convertPixelDataToDistanceInMeters(byte[] data,XRCpuImage.Format format) {
switch (format) {
case XRCpuImage.Format.DepthUint16:
return BitConverter.ToUInt16(data,0) / 1000f;
case XRCpuImage.Format.DepthFloat32:
return BitConverter.ToSingle(data,0);
default:
throw new Exception($"Format not supported: {format}");
}
}
}
,
我也在研究 AR 深度图像,基本思想是:
- 获取图片使用API,通常格式为Depth16;
- 将图像分割成短缓冲区,因为 Depth16 表示每个像素为 16 位;
- 获取距离值,这个值存储在每个shortbuffer的低13位,你可以通过做(shortbuffer & 0x1ff)来做到这一点,然后你就可以得到每个像素的距离,正常情况下以毫米为单位。
通过对所有像素执行此操作,您可以创建深度图像并将其存储为 jpg 或其他格式,以下是使用 AR 引擎获取距离的示例代码:
try (Image depthImage = arFrame.acquireDepthImage()) {
int imwidth = depthImage.getWidth();
int imheight = depthImage.getHeight();
Image.Plane plane = depthImage.getPlanes()[0];
ShortBuffer shortDepthBuffer = plane.getBuffer().asShortBuffer();
File sdCardFile = Environment.getExternalStorageDirectory();
Log.i(TAG,"The storage path is " + sdCardFile);
File file = new File(sdCardFile,"RawdepthImage.jpg");
Bitmap disBitmap = Bitmap.createBitmap(imwidth,imheight,Bitmap.Config.RGB_565);
for (int i = 0; i < imheight; i++) {
for (int j = 0; j < imwidth; j++) {
int index = (i * imwidth + j) ;
shortDepthBuffer.position(index);
short depthSample = shortDepthBuffer.get();
short depthRange = (short) (depthSample & 0x1FFF);
//If you only want the distance value,here it is
byte value = (byte) depthRange;
byte value = (byte) depthRange ;
disBitmap.setPixel(j,i,Color.rgb(value,value,value));
}
}
//I rotate the image for a better view
Matrix matrix = new Matrix();
matrix.setRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(disBitmap,imwidth,matrix,true);
try {
FileOutputStream out = new FileOutputStream(file);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG,90,out);
out.flush();
out.close();
MainActivity.num++;
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
,
虽然答案很好,但对于这个问题来说可能太复杂和高级了,这个问题是关于 ARCamera 和另一个对象之间的距离,而不是关于像素的深度和它们的遮挡。
transform.position
为您提供将脚本附加到的任何游戏对象在层次结构中的位置。因此,将脚本附加到 ARCamera 对象。显然,other
应该是目标对象。
或者,您可以使用检查器变量或 GetComponent
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。