Field of view(FOV)相关介绍(全网最全)+全景图像(Panorama Image)

一、FOV的宏观定义

Field of View(FOV),即视场角,是一个描述从特定观察点可以看到的区域的角度范围的概念。在不同的应用场景中,FOV有着不同的定义和计算方式:

1.在光学和成像领域

        FOV指的是相机镜头能够捕捉到的场景范围。它通常以角度来表示,可以分为垂直视场角(Vertical Field of View)、水平视场角(Horizontal Field of View)和对角视场角(Diagonal Field of View)。这些视场角的大小决定了光学仪器的视野范围,视场角越大,视野就越大。

2.人眼视觉

        FOV指的是人眼所观察的物体轮廓到人眼瞳孔中心连线的立体夹角。人的单眼的水平FOV最大可达到160°,双眼的水平FOV最大能够达到200°,而双眼重合的最大FOV约为120°。这个范围内,人眼可以通过双眼视差感知物体的3D状态。

3.虚拟现实(VR)产品

        FOV是一个重要的参数,它影响着用户的沉浸体验。90°视场角往往是VR沉浸体验的及格线,而120°视场角被普遍认为是达到部分沉浸式体验的标准,180°视场角则是VR达到完全沉浸的标准。

4.摄像头参数

        FOV也被称为视场角,它与焦距有关:焦距越长,视场角越小;焦距越短,视场角越大。这对于视野范围来说,焦距越长,视野范围越远;焦距越短,视野范围越近。

5.显微镜场景

        FOV被译为视场直径/宽度,使用长度单位,指使用显微镜观察时所看到的明亮的圆形范围,以及在显微镜下看到的圆形视场内所能容纳被检物体的实际范围。

二、计算机视觉中的FOV

        FOV的最广泛应用为计算机视觉领域,在计算机视觉领域,Field of View(FOV)指的是相机或传感器能够捕捉到的图像或场景的区域。这个概念对于理解相机如何感知和解释世界至关重要。

1.FOV理论

         在计算机视觉中,相机通常被建模为一个针孔相机模型,其中FOV是由相机的内部参数(如焦距和传感器尺寸)和外部参数(如相机相对于场景的位置和朝向)决定的。FOV决定了相机一次能够捕捉到多少场景。一个较大的FOV意味着相机可以捕捉到更宽广的场景,而较小的FOV则只能捕捉到场景的一部分。

        FOV与相机传感器的尺寸和分辨率有关。对于给定的传感器尺寸,焦距越短,FOV越大;焦距越长,FOV越小。这意味着,如果传感器尺寸固定,改变焦距可以改变FOV。在实际应用中,不同的镜头(如广角镜头、标准镜头和长焦镜头)提供不同的FOV。广角镜头提供较大的FOV,适合捕捉宽广的场景,而长焦镜头提供较小的FOV,适合捕捉远处的细节。

        在立体视觉系统中,两个相机从略微不同的视角捕捉场景,以模拟人的双眼视觉。两个相机的FOV必须被仔细校准,以确保它们能够正确地重建3D场景。某些相机设计用于捕捉超过180°的FOV,如全景相机和鱼眼相机。这些相机可以捕捉到非常宽广的场景,但图像通常需要特殊的处理来纠正畸变。

2.虚拟现实(VR)中的FOV处理

        在虚幻引擎(UE4)中,不同VR头盔的FOV和分屏处理可以通过以下代码实现:

// 以Vive为例,其投影矩阵如下:
float Matrix[4][4] = {
    {0.756892, 0, 0, 0},
    {0, 0.681268, 0, 0},
    {-0.056316, 0.003274, 0, 1},
    {0, 0, -1, 0}
};
// 计算FOV
float s = 1 / (tan((fov / 2) * 3.14159 / 180));
fov = atan(1 / s) * 360 / 3.14159;

        这段代码展示了如何从投影矩阵中提取FOV值。

3.自动驾驶中的相机处理

         在Apollo自动驾驶平台中,相机模块的处理涉及到坐标变换和图像识别任务。以下是一个简化的示例代码,展示了如何调用这些模块进行图像检测和跟踪:

#include "perception/camera/lib/detector/detector.h"
#include "perception/camera/lib/tracker/tracker.h"
#include "perception/camera/lib/transformer/transformer.h"

// 初始化检测器、跟踪器和变换器
Detector detector("yolov3.cfg", "yolov3.weights");
Tracker tracker;
Transformer transformer;

这段代码展示了如何设置相机感知系统中的关键组件。

4.图像处理中的FOV应用

 使用OpenCV进行图像处理时,可以通过调整图像的边界来模拟FOV的效果。以下是一个示例代码,展示了如何对图像进行边界复制:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图片
img = cv2.imread('image.jpg')
# 设置边界大小
top, bottom, left, right = 50, 50, 50, 50
# 复制边界
replicate = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REPLICATE)
# 反射边界
reflect = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REFLECT)
# 显示原图和边界处理后的图像
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.subplot(122), plt.imshow(replicate), plt.title('Replicate')
plt.show()

这段代码展示了如何使用OpenCV对图像进行边界复制和反射处理,以模拟不同的FOV效果。

5.增强现实(AR)中的FOV配置

在Oculus Rift开发中,可以调整FOV以适应不同的渲染需求。以下是一个示例代码,展示了如何设置FOV:

ovrFovPort fov;
// 确定fov。
...
ovrMatrix4f projMatrix = ovrMatrix4f_Projection(fov, znear, zfar, isRightHanded);

这段代码展示了如何在Oculus Rift中设置投影矩阵,以适应不同的FOV需求。

三、典型三分类

1.三参数定义        

        水平视场角(HFOV)、垂直视场角(VFOV)和对角视场角(DFOV)是视场角(Field of View,简称FOV)的三种分类,它们分别描述了相机或镜头在不同方向上能够覆盖的场景范围。在计算机视觉中,计算水平视场角(HFOV)、垂直视场角(VFOV)和对角视场角(DFOV)通常涉及到相机的内参,包括焦距(f_x, f_y)和传感器尺寸(s_w, s_h)。这三个参数共同定义了相机镜头的视场范围,对于不同的应用场景,如监控、摄影、虚拟现实等,这些参数都是非常重要的。例如,在监控系统中,一个较宽的HFOV可以覆盖更广的水平范围,而在某些特定的摄影场景中,可能需要一个较窄的VFOV来聚焦于特定区域。DFOV则提供了一个综合的视角范围,它通常用于描述镜头的广角特性。

2.水平视场角(HFOV)

        指的是相机镜头在水平方向上能够覆盖的视角范围。这个角度是由镜头的焦距和传感器的宽度决定的。

import math

def calculate_hfov(focal_length_x, sensor_width):
    """
    计算水平视场角(HFOV)
    
    参数:
    focal_length_x -- 水平焦距
    sensor_width -- 传感器宽度
    
    返回:
    hfov -- 水平视场角,单位为度
    """
    hfov = 2 * math.atan(sensor_width / (2 * focal_length_x)) * (180 / math.pi)
    return hfov

# 假设相机的焦距为1000像素,传感器宽度为4000像素
focal_length_x = 1000
sensor_width = 4000
hfov = calculate_hfov(focal_length_x, sensor_width)
print(f"水平视场角(HFOV): {hfov:.2f} 度")

3.垂直视场角(VFOV)

        指的是相机镜头在垂直方向上能够覆盖的视角范围。这个角度是由镜头的焦距和传感器的高度决定的。

def calculate_vfov(focal_length_y, sensor_height):
    """
    计算垂直视场角(VFOV)
    
    参数:
    focal_length_y -- 垂直焦距
    sensor_height -- 传感器高度
    
    返回:
    vfov -- 垂直视场角,单位为度
    """
    vfov = 2 * math.atan(sensor_height / (2 * focal_length_y)) * (180 / math.pi)
    return vfov

# 假设相机的焦距为1000像素,传感器高度为3000像素
focal_length_y = 1000
sensor_height = 3000
vfov = calculate_vfov(focal_length_y, sensor_height)
print(f"垂直视场角(VFOV): {vfov:.2f} 度")

4.对角视场角(DFOV)

        指的是相机镜头在对角线方向上能够覆盖的视角范围。这个角度是由镜头的焦距、传感器的宽度和高度共同决定的。   

def calculate_dfov(focal_length_x, focal_length_y, sensor_width, sensor_height):
    """
    计算对角视场角(DFOV)
    
    参数:
    focal_length_x -- 水平焦距
    focal_length_y -- 垂直焦距
    sensor_width -- 传感器宽度
    sensor_height -- 传感器高度
    
    返回:
    dfov -- 对角视场角,单位为度
    """
    # 计算传感器对角线长度
    diagonal = math.sqrt(sensor_width**2 + sensor_height**2)
    dfov = 2 * math.atan(diagonal / (2 * math.sqrt(focal_length_x**2 + focal_length_y**2))) * (180 / math.pi)
    return dfov

# 使用之前的焦距和传感器尺寸
dfov = calculate_dfov(focal_length_x, focal_length_y, sensor_width, sensor_height)
print(f"对角视场角(DFOV): {dfov:.2f} 度")

四、全景图像生成

        生成360度水平FOV(Field of View,视场角)和180度垂直FOV的全景图像,通常涉及到图像拼接技术,将多个视角的图像合并成一个无缝的全景图。以下是一些关键技术和方法的介绍,以及它们如何应用于生成全景图像的示例。

1.FOV生成

        以下是一个生成360度水平FOV和180度垂直FOV的全景图像的示例代码,这个示例代码使用了Python语言和OpenCV库来生成全景图像。

import cv2
import numpy as np

# 假设我们有两个图像,im1和im2,它们将被用来创建全景图
im1 = cv2.imread('image1.jpg')
im2 = cv2.imread('image2.jpg')

# 将图像转换为灰度图,用于特征匹配
gray1 = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)

# 使用SIFT算法检测特征点
sift = cv2.SIFT_create()
keypoints1, descriptors1 = sift.detectAndCompute(gray1, None)
keypoints2, descriptors2 = sift.detectAndCompute(gray2, None)

# 特征点匹配
bf = cv2.BFMatcher()
matches = bf.knnMatch(descriptors1, descriptors2, k=2)

# 应用比率测试以筛选好的匹配点
good_matches = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        good_matches.append(m)

# 根据匹配的特征点,估计单应性矩阵
src_pts = np.float32([keypoints1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
dst_pts = np.float32([keypoints2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)
H, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)

# 将第二幅图像变换到第一幅图像的视角
height, width, channels = im1.shape
im2_reg = cv2.warpPerspective(im2, H, (width + im2.shape[1], height))

# 将变换后的第二幅图像与第一幅图像拼接,形成全景图
pano = np.hstack((im1, im2_reg))

# 保存全景图
cv2.imwrite('panorama.jpg', pano)

2. 图像拼接技术

图像拼接技术是生成全景图像的基础,它包括以下几个步骤:

  • 图像匹配(Registration):确定不同图像之间的几何对应关系。
  • 重投影(Reprojection):将一系列图像转换到一个共同的坐标系中。
  • 缝合(Stitching):合并重叠部分的像素值,生成更大的画布图像。
  • 融合(Blending):减少接缝的可见性,使图像间的过渡自然。

3. 全景图像的典型模型

        全景图像,也称为3D实景,是通过拼接水平方向360度和垂直方向180度的多张照片形成的。这种图像可以让用户通过鼠标控制浏览方向,实现全方位的互动式观察,仿佛身临其境。

3.1 PanFusion:双分支全景图像扩散生成

        PanFusion是一种双分支扩散模型,它利用Stable Diffusion模型的自然图像生成知识,并将其与全景分支注册,以生成360度图像。这个模型通过独特的跨注意力机制(EPPA)最小化在协作去噪过程中的失真,从而生成高质量的全景图像。

3.2 PanoFree:无需调优生成多视角图片

        PanoFree是一种无需调优的多视角图像生成技术,它支持生成长图、360度图、天空盒图等多视角全景图。PanoFree通过迭代的变形和修补过程,依次生成多视角图像,解决了一致性问题和因错误累积而导致的伪影问题。

3.3 PanoDiff:从窄视场图片生成全景图

        PanoDiff是一种从一张或多张未标注pose的NFoV(Narrow Field of View)图像生成360°全景图的方法。它包括一个两阶段角度预测模块和一个基于隐式扩散模型的全景生成网络,使用不完整的全景图和文本提示作为控制信号,并利用几何增强方案来确保生成图像的全景图几何属性。

4.FOV合成示例

        以下是一个简化的示例代码,展示了如何使用OpenCV库来拼接两张图像以形成一个简单的全景图:

import cv2
import numpy as np

# 读取两张图像
image1 = cv2.imread('image1.jpg')
image2 = cv2.imread('image2.jpg')

# 将图像转换为灰度图
gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

# 使用SIFT算法检测特征点
sift = cv2.SIFT_create()
keypoints1, descriptors1 = sift.detectAndCompute(gray1, None)
keypoints2, descriptors2 = sift.detectAndCompute(gray2, None)

# 特征点匹配
bf = cv2.BFMatcher()
matches = bf.knnMatch(descriptors1, descriptors2, k=2)

# 应用比率测试以筛选好的匹配点
good_matches = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        good_matches.append(m)

# 根据匹配的特征点,估计单应性矩阵
src_pts = np.float32([keypoints1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
dst_pts = np.float32([keypoints2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)
H, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)

# 将第二幅图像变换到第一幅图像的视角
height, width, channels = image1.shape
im2_reg = cv2.warpPerspective(image2, H, (width + image2.shape[1], height))

# 将变换后的第二幅图像与第一幅图像拼接,形成全景图
pano = np.hstack((image1, im2_reg))

# 保存全景图
cv2.imwrite('panorama.jpg', pano)

        这段代码通过特征点匹配和单应性矩阵变换,将两张图像拼接成一个简单的全景图。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摆烂仙君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值