Thank you. I was able to find the rectangle icon in Scissors.
Is there any way to modify the rectangle after making one on the image?
I would like to make a cube in the 3D volume or 2D rectangle on 2D image but it apparently makes a column in 3D volume.
In addition, I would like to make the rectangle available in AIAA (by Nvidia) instead of Markups so that the user can define rectangle in the 2D image or a cube in the 3D volume then the trained CNN will take the cropped rectangle or cube to predict the mask.
Would it be possible? and how could I use the rectangle in my codes in AIAA?
I am very new to Slicer development and still struggling with understanding a whole architecture.
Any advice would be very helpful!
Yes, you can use any effects to modify the segment. You can also use Surface cut effect with smoothing disabled, to adjust corners of the rectangle or prism before applying it.[quote=“Yusuke, post:3, topic:13286”]
I would like to make a cube in the 3D volume or 2D rectangle on 2D image but it apparently makes a column in 3D volume
[/quote]
You can use the Scissors effect on an orthogonal slice to crop the column to the desired region (erase outside). You can also choose to restrict painting a single slice or a specified thickness.
In a AIAA module, you can define an input box by placing 6 markups fiducial points.
You can enforce a markups plane to be a square by adding an observer to it. The observer’s callback function is executed whenever a control point is changed and then you can move other control points accordingly.
Inwould recommend to check out markups examples in script repository.
I understood that I can add some function to observer using planeNode.AddObserver() but I’m still not quite sure how I can force the plane to be a square.
Could you please point me some script that change the point in plane node to be a square if you have one?
Unfortunately, the documentation has not been updated for a while (you can track progress here). Until this gets fixed, you can find documentation in header files or you can use help command in Python:
>>> help(slicer.vtkMRMLMarkupsPlaneNode)
Help on class vtkMRMLMarkupsPlaneNode in module vtkSlicerMarkupsModuleMRMLPython:
class vtkMRMLMarkupsPlaneNode(vtkMRMLMarkupsNode)
| vtkMRMLMarkupsPlaneNode - MRML node to represent a plane markup
|
| Superclass: vtkMRMLMarkupsNode
|
| Plane Markups nodes contain three control points. Visualization
| parameters are set in the vtkMRMLMarkupsDisplayNode class.
|
| Markups is intended to be used for manual marking/editing of point
| positions.
|
| Coordinate systems used:
| - Local: Local coordinates
| - World: All parent transforms on node applied to local.
| - Plane: Plane coordinate space (Origin of plane at 0,0,0, XYZ axis
| aligned to XYZ unit vectors). Can have additional offset/rotation
| compared to local.\ingroup Slicer_QtModules_Markups
|
| Method resolution order:
| vtkMRMLMarkupsPlaneNode
| vtkMRMLMarkupsNode
| MRMLCorePython.vtkMRMLDisplayableNode
| MRMLCorePython.vtkMRMLTransformableNode
| MRMLCorePython.vtkMRMLStorableNode
| MRMLCorePython.vtkMRMLNode
| vtkCommonCorePython.vtkObject
| vtkCommonCorePython.vtkObjectBase
| builtins.object
|
| Methods defined here:
|
| CopyContent(...)
| V.CopyContent(vtkMRMLNode, bool)
| C++: void CopyContent(vtkMRMLNode *node, bool deepCopy=true)
| override;
|
| Copy node content (excludes basic data, such as name and node
| references).
| \sa vtkMRMLNode::CopyContent
|
| CreateNodeInstance(...)
| V.CreateNodeInstance() -> vtkMRMLNode
| C++: vtkMRMLNode *CreateNodeInstance() override;
|
| MRMLNode methods
|
| GetAutoSizeScalingFactor(...)
| V.GetAutoSizeScalingFactor() -> float
| C++: virtual double GetAutoSizeScalingFactor()
|
| The plane size multiplier used to calculate the size of the
| plane. This is only used when the size mode is auto. Default is
| 1.0.
|
| GetAxes(...)
| V.GetAxes([float, float, float], [float, float, float], [float,
| float, float])
| C++: void GetAxes(double x[3], double y[3], double z[3])
|
| The direction vectors defined by the markup points. Calculated as
| follows and then transformed by the offset matrix: X: Vector from
| 1st to 0th point. Y: Cross product of the Z vector and X vectors.
| Z: Cross product of the X vector and the vector from the 2nd to
| 0th point.
|
| GetAxesWorld(...)
| V.GetAxesWorld([float, float, float], [float, float, float],
| [float, float, float])
| C++: void GetAxesWorld(double x[3], double y[3], double z[3])
|
| GetClosestPointOnPlaneWorld(...)
| V.GetClosestPointOnPlaneWorld((float, float, float), [float,
| float, float], bool) -> float
| C++: double GetClosestPointOnPlaneWorld(const double posWorld[3],
| double closestPosWorld[3], bool infinitePlane=true)
|
| Get the closest position on the plane in world coordinates.
| Returns the signed distance from the input point to the plane.
| Positive distance is in the direction of the plane normal, and
| negative distance is in the opposite direction.
| \param posWorld input position
| \param closestPosWorld: output found closest position
| \param infinitePlane if false, the closest position will be
| restricted to the plane bounds
| \return Signed distance from the point to the plane. Positive
| distance is in the direction of the plane normal
|
| GetIcon(...)
| V.GetIcon() -> string
| C++: const char *GetIcon() override;
|
...
You need to adjust the control points. First control point defines the plane center, second control point defines X axis direction and size, and third control point defines Y axis direction and size.
Thank you Andras,
I tried to change the control point as they are changed.
However, I found changing other control points every time a control point was moved is very slow.
The codes are below and this is just sample codes.
Your code was slow because it recursively called itself (setting control point position triggers control point changed event). You can break this recursion by adding a flag (slicer.updatingControlPoint):
There are many options. For example you can store the previous planeToWorldMatrix, update it with the new center point position, and get the two new point positions by transforming (sideLength,0,0,1) and (0,sideLength,0,1) points by this updated planeToWorldMatrix.
In your original codes, when I move the center point in the rectangle, the other two points will be located in the same as the center point, which made the rectangle converge into one point.
In my codes above, when I move the center point in the rectangle, the size and the orient of the rectangle will be changed.
Could you elaborate on this?
My understanding is that what you mentioned is what my codes are doing.