1 minute read

fovx์— ํ•ด๋‹นํ•˜๋Š” camera_angle_x๋งŒ ์žˆ์œผ๋ฉด image์˜ height, width๋กœ fovy๋„ ๊ณ„์‚ฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • NeRF dataset์˜ transforms_train.json, transforms_test.json์—์„œ ["camera_angle_x"]๋Š” fovx ์ž…๋‹ˆ๋‹ค.
  • fovx์™€ image์˜ height width๋ฅผ ์•Œ๋ฉด fovy๊ฐ€ ๊ณ„์‚ฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
# 3dgs/scene/dataset_readers.py

def readCamerasFromTransforms(path, transformsfile, white_background, extension=".png"):
    cam_infos = []

    with open(os.path.join(path, transformsfile)) as json_file:
        contents = json.load(json_file)
        fovx = contents["camera_angle_x"]

        frames = contents["frames"]
        for idx, frame in enumerate(frames):

...

            fovy = focal2fov(fov2focal(fovx, image.size[0]), image.size[1])
            FovY = fovy 
            FovX = fovx
# 3dgs/utils/graphic_utils.py

def fov2focal(fov, pixels):
    return pixels / (2 * math.tan(fov / 2))

def focal2fov(focal, pixels):
    return 2*math.atan(pixels/(2*focal))

๊ฐ ๋‹จ๊ณ„๋ฅผ ์š”์•ฝํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์ˆ˜ํ‰ ์‹œ์•ผ๊ฐ(fovx)์™€ ์ด๋ฏธ์ง€์˜ ๊ฐ€๋กœ ํ”ฝ์…€ ์ˆ˜(width)๋ฅผ ์ด์šฉํ•˜์—ฌ ์ดˆ์  ๊ฑฐ๋ฆฌ(focal length) ๊ณ„์‚ฐ:
    focal_length = fov2focal(fovx, image_width)
    
  2. ๊ณ„์‚ฐ๋œ ์ดˆ์  ๊ฑฐ๋ฆฌ์™€ ์ด๋ฏธ์ง€์˜ ์„ธ๋กœ ํ”ฝ์…€ ์ˆ˜(height)๋ฅผ ์ด์šฉํ•˜์—ฌ ์ˆ˜์ง ์‹œ์•ผ๊ฐ(fovy) ๊ณ„์‚ฐ:
    fovy = focal2fov(focal_length, image_height)
    

์ „์ฒด ์ฝ”๋“œ ์˜ˆ์ œ

import math

def fov2focal(fov, pixels):
    return pixels / (2 * math.tan(fov / 2))

def focal2fov(focal, pixels):
    return 2 * math.atan(pixels / (2 * focal))

# ์ฃผ์–ด์ง„ ๊ฐ’
fovx = ...  # ์ˆ˜ํ‰ ์‹œ์•ผ๊ฐ (radians ๋‹จ์œ„)
image_width = ...  # ์ด๋ฏธ์ง€์˜ ๊ฐ€๋กœ ํ”ฝ์…€ ์ˆ˜
image_height = ...  # ์ด๋ฏธ์ง€์˜ ์„ธ๋กœ ํ”ฝ์…€ ์ˆ˜

# ์ˆ˜ํ‰ ์‹œ์•ผ๊ฐ์„ ์ด์šฉํ•˜์—ฌ ์ดˆ์  ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ
focal_length = fov2focal(fovx, image_width)

# ์ดˆ์  ๊ฑฐ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ˆ˜์ง ์‹œ์•ผ๊ฐ ๊ณ„์‚ฐ
fovy = focal2fov(focal_length, image_height)

print("fovx:", fovx)
print("fovy:", fovy)

์˜ˆ์ œ

  • fovx = 90๋„ (radians ๋‹จ์œ„๋กœ ๋ณ€ํ™˜ ์‹œ ์•ฝ 1.5708 rad)
  • image_width = 1920 ํ”ฝ์…€
  • image_height = 1080 ํ”ฝ์…€
import math

def fov2focal(fov, pixels):
    return pixels / (2 * math.tan(fov / 2))

def focal2fov(focal, pixels):
    return 2 * math.atan(pixels / (2 * focal))

# ์ฃผ์–ด์ง„ ๊ฐ’
fovx = math.radians(90)  # ์ˆ˜ํ‰ ์‹œ์•ผ๊ฐ 90๋„
image_width = 1920  # ์ด๋ฏธ์ง€์˜ ๊ฐ€๋กœ ํ”ฝ์…€ ์ˆ˜
image_height = 1080  # ์ด๋ฏธ์ง€์˜ ์„ธ๋กœ ํ”ฝ์…€ ์ˆ˜

# ์ˆ˜ํ‰ ์‹œ์•ผ๊ฐ์„ ์ด์šฉํ•˜์—ฌ ์ดˆ์  ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ
focal_length = fov2focal(fovx, image_width)

# ์ดˆ์  ๊ฑฐ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ˆ˜์ง ์‹œ์•ผ๊ฐ ๊ณ„์‚ฐ
fovy = focal2fov(focal_length, image_height)

print("fovx:", math.degrees(fovx), "degrees")
print("fovy:", math.degrees(fovy), "degrees")
  • ์œ„ ์ฝ”๋“œ ์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” fovy ๊ฐ’์ด ์•ฝ 53.13๋„๋กœ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ€๋กœ ์‹œ์•ผ๊ฐ 90๋„, ์ด๋ฏธ์ง€ ๋น„์œจ 16:9(1920x1080)์—์„œ์˜ ์„ธ๋กœ ์‹œ์•ผ๊ฐ์ž…๋‹ˆ๋‹ค.

์š”์•ฝ

  • ์ˆ˜ํ‰ ์‹œ์•ผ๊ฐ(fovx)๊ณผ ์ด๋ฏธ์ง€์˜ ๊ฐ€๋กœ, ์„ธ๋กœ ํ”ฝ์…€ ์ˆ˜๋ฅผ ์•Œ๋ฉด, ์ˆ˜์ง ์‹œ์•ผ๊ฐ(fovy)์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋ฅผ ํ†ตํ•ด ์นด๋ฉ”๋ผ์˜ ์ „์ฒด ์‹œ์•ผ๊ฐ์„ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Leave a comment