Skip to content

Commit a14f4b9

Browse files
Merge pull request #103 from Computer-Aided-Validation-Laboratory/dev
Improvement to Blender calibration tool
2 parents 640076b + 6845517 commit a14f4b9

File tree

6 files changed

+48
-11
lines changed

6 files changed

+48
-11
lines changed

src/pyvale/blendercalibrationdata.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ class CalibrationData:
1212
angle_lims: tuple = (-10, 10)
1313
angle_step: int = 5
1414
plunge_lims: tuple = (-5, 5)
15-
plunge_step: int = 5
15+
plunge_step: int = 5
16+
x_limit: float | None = None
17+
y_limit: float | None = None

src/pyvale/blenderscene.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,14 @@ def add_camera(self, cam_data:CameraData) -> bpy.data.objects:
9494
new_cam.dof.use_dof = True
9595
new_cam.dof.aperture_fstop = cam_data.fstop
9696

97+
new_cam.clip_end = ((cam_data.pos_world[2] - cam_data.roi_cent_world[2])
98+
+ 100)
99+
97100
bpy.context.scene.camera = camera
98101
return camera
99102

100103
def add_stereo_system(self, stereo_system: CameraStereo) -> tuple[bpy.data.objects,
101104
bpy.data.objects]:
102-
# TODO: Correct docstring
103105
"""A method to add a stereo camera system within Blender, given an
104106
instance of the CameraStereo class (that describes a stereo system).
105107

src/pyvale/blendertools.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,9 @@ def render_calibration_images(render_data: RenderData,
332332
A dataclass containing the parameters needed to render the images
333333
calibration_data : CalibrationData
334334
A dataclass containing the parameters by which to move the calibration
335-
target. These inclcude the plungle depth and rotation angle.
335+
target. These inclcude the plungle depth and rotation angle. It also
336+
inlcludes optional x and y limits for the movement of the calibration
337+
target (if None they will be initialised from the FOV).
336338
part : bpy.data.objects
337339
The Blender part object, in this instance the calibration target.
338340
@@ -371,15 +373,17 @@ def render_calibration_images(render_data: RenderData,
371373
plunge = calibration_data.plunge_lims[0] + calibration_data.plunge_step * ii
372374
# Plunge
373375
(FOV_x, FOV_y) = CameraTools.blender_FOV(render_data.cam_data[0])
374-
x_limit = int(round((FOV_x / 2) - (part.dimensions[0] / 2)))
375376

376-
y_limit = int(round((FOV_y / 2) - (part.dimensions[1] / 2)))
377+
if calibration_data.x_limit is None:
378+
calibration_data.x_limit = int(round((FOV_x / 2) - (part.dimensions[0] / 2)))
379+
if calibration_data.y_limit is None:
380+
calibration_data.y_limit = int(round((FOV_y / 2) - (part.dimensions[1] / 2)))
377381

378382
for x in np.arange(-1, 2):
379-
x *= x_limit
383+
x *= calibration_data.x_limit
380384
# Move in x-dir
381385
for y in np.arange(-1, 2):
382-
y *= y_limit
386+
y *= calibration_data.y_limit
383387
# Move in y-dir
384388
part.location = ((x, y, plunge))
385389
part.location[2] = plunge
@@ -415,6 +419,24 @@ def render_calibration_images(render_data: RenderData,
415419
print('Total number of calibration images = ' + str(render_counter))
416420
return render_counter
417421

422+
def check_for_GPU() -> bool:
423+
"""A method to check whether the machine has a GPU or not.
424+
425+
Returns
426+
-------
427+
bool
428+
Returns True if a GPU is present, returns False if only a CPU is
429+
present.
430+
"""
431+
accepted_gpus = ["CUDA", "OPTIX", "HIP", "METAL", "ONEAPI"]
432+
cycles_prefs = bpy.context.preferences.addons["cycles"].preferences
433+
cycles_prefs.refresh_devices()
434+
for device in cycles_prefs.devices:
435+
print(f"Name: {device.name}, Type: {device.type}, Use: {device.use}")
436+
if device.type in accepted_gpus:
437+
return True
438+
return False
439+
418440

419441

420442

src/pyvale/examples/renderblender/ex3_1_blendercalibration.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,11 @@
135135
# %%
136136
# The parameters for the calibration target's movement can then be set. This is
137137
# done by setting the minimum and maximum angle and plunge limits, as well as
138-
# the step value that they should be increased by.
138+
# the step value that they should be increased by. The x and y limit of the
139+
# calibration target's movement (from the origin) can also be set if you wish to
140+
# perform a calibration for a constrained optical setup. If these limits are not
141+
# passed in they will be initialised from the FOV to cover the whole FOV of the
142+
# cameras.
139143

140144
calibration_data = pyvale.CalibrationData(angle_lims=(-10, 10),
141145
angle_step=5,

tests/blender/test_blenderregression_2D.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from scipy.spatial.transform import Rotation
1212
import pyvale
1313
import mooseherder as mh
14+
import bpy
1415

1516
# NOTE: These test may fail if you are not running bpy 4.4.0
1617
# It is a known issue that the render outputs between bpy 4.2.0 and 4.4.0 slightly
@@ -244,7 +245,7 @@ def test_max_bounces_happy(bounces, output, request, sample_scene, tmp_path):
244245
render_data=render_data)
245246
output = request.getfixturevalue(output)
246247

247-
npt.assert_array_equal(image_array, output)
248+
npt.assert_allclose(image_array, output, atol=1)
248249

249250
def test_max_bounces_unhappy(sample_scene, tmp_path):
250251
bounces = 2.5
@@ -265,6 +266,11 @@ def test_max_bounces_unhappy(sample_scene, tmp_path):
265266
)
266267
def test_render_engine(engine, output, request, sample_scene, tmp_path):
267268
(_, _, cam_data, scene) = sample_scene
269+
if engine == pyvale.RenderEngine.EEVEE:
270+
gpu_present = pyvale.BlenderTools.check_for_GPU()
271+
if gpu_present is False:
272+
pytest.skip("Unsupported hardware for EEVEE")
273+
268274
render_data = pyvale.RenderData(cam_data=cam_data,
269275
base_dir=tmp_path,
270276
engine=engine)
@@ -274,6 +280,7 @@ def test_render_engine(engine, output, request, sample_scene, tmp_path):
274280

275281
npt.assert_allclose(image_array, output, atol=2)
276282

283+
277284
@pytest.fixture
278285
def half_watt_lighting():
279286
return np.array([[33, 40, 35, 37, 43, 46, 47, 48, 46, 50, 53, 52, 51, 51, 52, 45,

tests/blender/test_blenderregression_3D.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def test_stereo_convenience_cameras(placement, output, request, sample_scene_no_
9090
render_data=render_data)
9191
output = request.getfixturevalue(output)
9292

93-
npt.assert_array_equal(image_array, output)
93+
npt.assert_allclose(image_array, output, atol=1)
9494

9595
def test_stereo_deformation(sample_stereo_scene, deformed_images, tmp_path):
9696
(stereo_system, part, render_mesh, scene) = sample_stereo_scene
@@ -103,7 +103,7 @@ def test_stereo_deformation(sample_stereo_scene, deformed_images, tmp_path):
103103
part=part,
104104
stage_image=True)
105105
image_array = image_arrays[:, :, 120:]
106-
npt.assert_array_equal(image_array, deformed_images)
106+
npt.assert_allclose(image_array, deformed_images, atol=1)
107107

108108
def test_cal_images():
109109
calibration_data = pyvale.CalibrationData(angle_lims=(-10, 10),

0 commit comments

Comments
 (0)