Files
mt/tools/calculate_rf_sizes.py
Jan Kowalczyk 86d9d96ca4 wip
2025-09-09 14:15:16 +02:00

125 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
def calculate_receptive_field_size(layers):
"""
Parameters
----------
layers : list of dict
Each dict must contain
'kernel_size' : (k_h, k_w)
'stride' : (s_h, s_w)
'dilation' : (d_h, d_w) # optional; defaults to (1, 1)
Returns
-------
(rf_h, rf_w) : tuple of ints
Receptive-field size in pixels for height and width.
"""
rf_h = rf_w = 1 # start with a 1×1 pixel
jump_h = jump_w = 1 # effective stride so far
for layer in layers:
k_h, k_w = layer["kernel_size"]
s_h, s_w = layer["stride"]
d_h, d_w = layer.get("dilation", (1, 1)) # default = 1
# Dumoulin & Visin recurrence, now with dilation
rf_h += (k_h - 1) * d_h * jump_h
rf_w += (k_w - 1) * d_w * jump_w
jump_h *= s_h
jump_w *= s_w
return rf_h, rf_w
def calculate_angular_receptive_field(
rf_height: int,
rf_width: int,
vertical_res: int,
horizontal_res: int,
vertical_fov: float,
horizontal_fov: float,
) -> tuple[float, float]:
"""Calculate the angular size of a receptive field in degrees.
Args:
rf_height: Receptive field height in pixels
rf_width: Receptive field width in pixels
vertical_res: Vertical resolution of input in pixels
horizontal_res: Horizontal resolution of input in pixels
vertical_fov: Vertical field of view in degrees
horizontal_fov: Horizontal field of view in degrees
Returns:
tuple[float, float]: Angular size (height, width) in degrees
"""
# Calculate degrees per pixel for each axis
vertical_deg_per_pixel = vertical_fov / vertical_res
horizontal_deg_per_pixel = horizontal_fov / horizontal_res
# Calculate angular size of receptive field
rf_vertical_deg = rf_height * vertical_deg_per_pixel
rf_horizontal_deg = rf_width * horizontal_deg_per_pixel
return rf_vertical_deg, rf_horizontal_deg
def calculate_pixels_per_degree(resolution: int, fov: float) -> float:
"""Calculate pixels per degree for a given resolution and field of view.
Args:
resolution: Number of pixels
fov: Field of view in degrees
Returns:
float: Pixels per degree
"""
return resolution / fov
horizontal_resolution = 2048
horizontal_fov = 360.0
vertical_resolution = 32
vertical_fov = 31.76
lenet_network_config = [
{"name": "Conv1", "kernel_size": (5, 5), "stride": (1, 1), "dilation": (1, 1)},
{"name": "MaxPool1", "kernel_size": (2, 2), "stride": (2, 2), "dilation": (1, 1)},
{"name": "Conv2", "kernel_size": (5, 5), "stride": (1, 1), "dilation": (1, 1)},
{"name": "MaxPool2", "kernel_size": (2, 2), "stride": (2, 2), "dilation": (1, 1)},
]
# Calculate and print results for LeNet
rf_h, rf_w = calculate_receptive_field_size(lenet_network_config)
rf_vert_deg, rf_horiz_deg = calculate_angular_receptive_field(
rf_h, rf_w, vertical_resolution, horizontal_resolution, vertical_fov, horizontal_fov
)
print(f"SubTer LeNet RF size: {rf_h} × {rf_w} pixels")
print(f"SubTer LeNet RF angular size: {rf_vert_deg:.2f}° × {rf_horiz_deg:.2f}°")
asym_network_config = [
{"name": "Conv1", "kernel_size": (3, 17), "stride": (1, 1), "dilation": (1, 1)},
{"name": "MaxPool1", "kernel_size": (2, 2), "stride": (2, 2), "dilation": (1, 1)},
{"name": "Conv2", "kernel_size": (3, 17), "stride": (1, 1), "dilation": (1, 1)},
{"name": "MaxPool2", "kernel_size": (2, 2), "stride": (2, 2), "dilation": (1, 1)},
]
# Calculate and print results for Asymmetric network
rf_h, rf_w = calculate_receptive_field_size(asym_network_config)
rf_vert_deg, rf_horiz_deg = calculate_angular_receptive_field(
rf_h, rf_w, vertical_resolution, horizontal_resolution, vertical_fov, horizontal_fov
)
print(f"SubTer LeNet (Asymmetric kernels) RF size: {rf_h} × {rf_w} pixels")
print(
f"SubTer LeNet (Asymmetric kernels) RF angular size: {rf_vert_deg:.2f}° × {rf_horiz_deg:.2f}°"
)
# Calculate pixels per degree
horizontal_ppd = calculate_pixels_per_degree(horizontal_resolution, horizontal_fov)
vertical_ppd = calculate_pixels_per_degree(vertical_resolution, vertical_fov)
print("\nPixels per Degree:")
print(f"Horizontal: {horizontal_ppd:.2f} px/°")
print(f"Vertical: {vertical_ppd:.2f} px/°")
print()