我想我设法解决了我的问题。让我解释一下我是如何做到的,如果可能对其他人有用。如果您发现这种方法有误,我将不胜感激您的反馈或任何进一步的线索。
我决定为我的虚拟广告牌分配以米为单位的物理尺寸。 这次讨论帮助我了解了 iPhone 4 相机的参数:焦距和 CCD 传感器的尺寸。更重要的是,这些值还帮助我为我的 AR 应用程序计算了合适的 FOV(请参阅计算相机的视角)。
这个网站帮助我计算了在 CCD 传感器上产生的物理对象图像的毫米大小。因此,如果我的广告牌具有以米为单位的宽度和高度,并且它们与相机的距离以及相机的焦距是已知的,我可以在传感器上计算它们的尺寸。
(焦距 * 物体尺寸)/ 镜头到物体的距离 = 图像尺寸(在传感器上)
double CalculatePhysicalObjectImageDimensionOnCCD(double cameraFocalLength_mm, double physicalObjectDimension_m, double distanceFromPhysicalObject_m)
{
double physicalObjectDimension_mm = physicalObjectDimension_m * 1000;
double distanceFromPhysicalObject_mm = distanceFromPhysicalObject_m * 1000;
return (cameraFocalLength_mm * physicalObjectDimension_mm) / distanceFromPhysicalObject_mm;
}
我对这件事知之甚少,所以我不确定我当时采用的方法是否可行,但我只是决定计算一下 iPhone 屏幕与 CCD 传感器的尺寸相比要大多少。因此,通过一个简单的数学运算,我得到了传感器与屏幕的尺寸比。因为传感器和屏幕的宽高比似乎不一样,所以我用一种胡思乱想的方式计算了这个比例:
double GetCCDToScreenSizeRatio(double sensorWidth, double sensorHeight, double screenWidth, double screenHeight)
{
return sqrt(screenWidth * screenHeight) / sqrt(sensorWidth * sensorHeight);
}
然后我得到的比率可以被视为一个乘数。首先,我计算传感器上虚拟广告牌的尺寸,然后将其乘以比率。这样我就可以得到广告牌的实际大小(以像素为单位)。就是这样。因此,当我仅通过提供广告牌的宽度和与广告牌的距离来调用下面的函数时,它会返回在屏幕上查看的广告牌的宽度(以像素为单位)。广告牌的高度相同以获得两个尺寸。
const double CCD_DIM_LONGER_IPHONE4 = 4.592; //mm
const double CCD_DIM_SHORTER_IPHONE4 = 3.450; //mm
const double FOCAL_LENGTH_IPHONE4 = 4.28; //mm
double CalculatePhysicalObjectImageDimensionOnScreen_iPhone4(double physicalObjectDimension_m, double distanceFromPhysicalObject_m)
{
double screenWidth = [UIScreen mainScreen].bounds.size.width;
double screenHeight = [UIScreen mainScreen].bounds.size.height;
return CalculatePhysicalObjectImageDimensionOnScreen(FOCAL_LENGTH_IPHONE4, physicalObjectDimension_m, distanceFromPhysicalObject_m, CCD_DIM_LONGER_IPHONE4, CCD_DIM_SHORTER_IPHONE4, screenWidth, screenHeight);
}
double CalculatePhysicalObjectImageDimensionOnScreen(double cameraFocalLength_mm, double physicalObjectDimension_m, double distanceFromPhysicalObject_m, double ccdSensorWidth, double ccdSensorHeight, double screenWidth, double screenHeight)
{
double ccdToScreenSizeRatio = GetCCDToScreenSizeRatio(ccdSensorWidth, ccdSensorHeight, screenWidth, screenHeight);
double dimensionOnCcd = CalculatePhysicalObjectImageDimensionOnCCD(cameraFocalLength_mm, physicalObjectDimension_m, distanceFromPhysicalObject_m);
return dimensionOnCcd * ccdToScreenSizeRatio;
}
与我以前愚蠢的线性缩放方法相比,它似乎完美无缺。顺便说一句,我还注意到,在 AR 视图上注册虚拟对象时,了解相机的 FOV 非常重要。以下是如何根据 CCD 传感器尺寸和焦距计算 FOV。
在任何地方都很难找到这些值!我想知道为什么它们不能以编程方式访问(至少我的研究表明它们不是)。似乎有必要准备硬编码值,然后检查运行应用程序的设备型号,以决定在进行上述所有计算时选择哪个值:-/。