Skip to content

Commit

Permalink
ENH: Manual camera placement
Browse files Browse the repository at this point in the history
  • Loading branch information
NicerNewerCar committed Aug 28, 2023
1 parent f1508d4 commit 7002eee
Show file tree
Hide file tree
Showing 3 changed files with 381 additions and 84 deletions.
54 changes: 54 additions & 0 deletions AutoscoperM/AutoscoperM.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def setup(self):
# Pre-processing Library Buttons
self.ui.tiffGenButton.connect("clicked(bool)", self.onGeneratePartialVolumes)
self.ui.vrgGenButton.connect("clicked(bool)", self.onGenerateVRG)
self.ui.manualVRGGenButton.connect("clicked(bool)", self.onManualVRGGen)
self.ui.configGenButton.connect("clicked(bool)", self.onGenerateConfig)
self.ui.segmentationButton.connect("clicked(bool)", self.onSegmentation)

Expand Down Expand Up @@ -609,6 +610,59 @@ def onLoadPV(self):
volumeNode.SetAndObserveTransformNodeID(transformNode.GetID())
self.logic.showVolumeIn3D(volumeNode)

def onManualVRGGen(self):
markupsNode = self.ui.mVRG_markupSelector.currentNode()
volumeNode = self.ui.volumeSelector.currentNode()
segmentationNode = self.ui.mVRG_segmentationSelector.currentNode()
mainOutputDir = self.ui.mainOutputSelector.currentPath
viewAngle = self.ui.mVRG_viewAngleSpin.value
clippingRange = (self.ui.mVRG_ClippingRangeSlider.minimum, self.ui.mVRG_ClippingRangeSlider.maximum)
width = self.ui.vrgRes_width.value
height = self.ui.vrgRes_height.value
vrgDir = self.ui.vrgSubDir.text
cameraDir = self.ui.cameraSubDir.text
self.logic.validateInputs(
markupsNode=markupsNode,
volumeNode=volumeNode,
segmentationNode=segmentationNode,
mainOutputDir=mainOutputDir,
viewAngle=viewAngle,
clippingRange=clippingRange,
width=width,
height=height,
vrgDir=vrgDir,
cameraDir=cameraDir,
)
self.logic.validatePaths(mainOutputDir=mainOutputDir)
self.logic.createPathsIfNotExists(os.path.join(mainOutputDir, vrgDir), os.path.join(mainOutputDir, cameraDir))

volumeImageData, bounds = self.logic.extractSubVolumeForVRG(
volumeNode, segmentationNode, cameraDebugMode=self.ui.camDebugCheckbox.isChecked()
)

cameras = RadiographGeneration.generateCamerasFromMarkups(
markupsNode,
bounds,
clippingRange,
viewAngle,
[width, height],
self.ui.camDebugCheckbox.isChecked(),
)

self.logic.generateVRGForCameras(
cameras,
volumeImageData,
os.path.join(mainOutputDir, vrgDir),
width,
height,
progressCallback=self.updateProgressBar,
)

self.updateProgressBar(100)

for cam in cameras:
IO.generateCameraCalibrationFile(cam, os.path.join(mainOutputDir, cameraDir, f"cam{cam.id}.yaml"))


#
# AutoscoperMLogic
Expand Down
51 changes: 48 additions & 3 deletions AutoscoperM/AutoscoperMLib/RadiographGeneration.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,8 @@ def generateNCameras(
camera.vtkCamera.SetPosition(points.GetPoint(i))
camera.vtkCamera.SetFocalPoint(center)
camera.vtkCamera.SetViewAngle(30)
# Set the far clipping plane to be the distance from the camera to the far side of the volume
camera.vtkCamera.SetClippingRange(0.1, r + largestDimension)
# camera.vtkCamera.SetClippingRange(0.1, 1000)
camera.vtkCamera.SetViewUp(0, 1, 0) # Set the view up to be the y axis
camera.vtkCamera.SetViewUp(0, 1, 0)
camera.id = i
camera.imageSize = imageSize
cameras.append(camera)
Expand All @@ -144,6 +142,53 @@ def generateNCameras(
return cameras


def generateCamerasFromMarkups(
fiduaicalNode: slicer.vtkMRMLMarkupsFiducialNode,
volumeBounds: list[int],
clippingRange: tuple[int],
viewAngle: int,
imageSize: tuple[int] = (512, 512),
cameraDebug: bool = False,
) -> list[Camera]:
"""
Generate cameras from a markups fiducial node
:param fiduaicalNode: Markups fiducial node
:type fiduaicalNode: slicer.vtkMRMLMarkupsFiducialNode
:param volumeBounds: Bounds of the volume
:type volumeBounds: list[int]
:param clippingRange: Clipping range
:type clippingRange: tuple[int]
:param viewAngle: View angle
:type viewAngle: int
:param imageSize: Image size. Defaults to [512,512].
:type imageSize: list[int]
:param cameraDebug: Whether or not to show the cameras in the scene. Defaults to False.
:type cameraDebug: bool
:return: List of cameras
"""
center = [
(volumeBounds[0] + volumeBounds[1]) / 2,
(volumeBounds[2] + volumeBounds[3]) / 2,
(volumeBounds[4] + volumeBounds[5]) / 2,
]
n = fiduaicalNode.GetNumberOfControlPoints()
cameras = []
for i in range(n):
camera = Camera()
camera.vtkCamera.SetPosition(fiduaicalNode.GetNthControlPointPosition(i))
camera.vtkCamera.SetFocalPoint(center)
camera.vtkCamera.SetViewAngle(viewAngle)
camera.vtkCamera.SetClippingRange(clippingRange[0], clippingRange[1])
camera.vtkCamera.SetViewUp(0, 1, 0)
camera.id = fiduaicalNode.GetNthControlPointLabel(i)
camera.imageSize = imageSize
if cameraDebug:
_createFrustumModel(camera)
cameras.append(camera)
return cameras


def generateVRG(
camera: Camera,
volumeImageData: vtk.vtkImageData,
Expand Down
Loading

0 comments on commit 7002eee

Please sign in to comment.