cornerstone3D icon indicating copy to clipboard operation
cornerstone3D copied to clipboard

Feat: Axis-based Image Stretching

Open arul-trenser opened this issue 2 months ago • 10 comments

Context

  • PR for the Feature Request: Axis-based Image Stretching #2287
  • This PR has been incorporated by FlyWheel.io.

Changes & Results

This PR introduces axis-based image stretching using camera projection matrix manipulation.

Usage Example

Stretch along the X-axis:

const { aspectRatio }  = viewport.getCamera()
viewport.setCamera({
    acpectRatio: [2, aspectRatio[1]]
})

Stretch along the X-axis:

const { aspectRatio }  = viewport.getCamera()
viewport.setCamera({
    acpectRatio: [aspectRatio[0], 2]
})

Testing

Basic Stretching along X and Y axis:

https://github.com/user-attachments/assets/20b3d859-fd03-4a7e-ac22-c08bd811723f

Segmentation Brush Tool Behavior in Stretched Viewport:

https://github.com/user-attachments/assets/9a5162e7-5ebe-496d-8f74-bbdd80ece85a

Circle ROI Tool Behavior in Stretched Viewport

https://github.com/user-attachments/assets/17ced2a7-09a9-47f3-879b-f3c80621c331

Checklist

PR

  • [x] My Pull Request title is descriptive, accurate and follows the semantic-release format and guidelines.

Code

  • [x] My code has been well-documented (function documentation, inline comments, etc.)

Public Documentation Updates

  • [] The documentation page has been updated as necessary for any public API additions or removals.

Tested Environment

  • [x] "OS: Windows 11
  • [x] "Node version: 22.19.0
  • [x] "Browser: Chrome 141.0.7390.123

arul-trenser avatar Nov 04 '25 05:11 arul-trenser

@sedghi when you have a moment, could you kindly review this PR at your earliest convenience? Thanks!

arul-trenser avatar Nov 10 '25 10:11 arul-trenser

how we can test it?

sedghi avatar Nov 10 '25 20:11 sedghi

how we can test it?

@sedghi Added an example demonstrating the stretch behavior in axialBasedImageStretching Also attached videos in the PR description

arul-trenser avatar Nov 11 '25 08:11 arul-trenser

Are you aware of other viewers how they do this feature? i'm trying to evaluate the result at least to some other library or product that has this feature

sedghi avatar Nov 11 '25 23:11 sedghi

Hi, We work with systems that have different vertical/horizontal scales. For example, with Optical Coherence Topography (https://eyewiki.org/Optical_Coherence_Tomography) scans, it is common to display the image at 2:1 (vertical/horizontal) aspect ration. The scans often have 2x->4x vertical resolution compared to the horizontal scale. This allows better visualisation of pathology in the vertical/depth axis. We also allow users to change the aspect ratio between 1:1 and 4:1 to account for different vendor devices and scan types. Below are 2 images that demonstrate this.

1:1 Aspect Ratio Screenshot 2025-11-12 at 11 23 17 am

the same scan at 2:1 Aspect Ratio Screenshot 2025-11-12 at 11 23 30 am

jmannau avatar Nov 12 '25 00:11 jmannau

@jmannau lovely, would you be able to test this PR against the viewer you have?

sedghi avatar Nov 12 '25 15:11 sedghi

Happy to. But we’re very short on time until the new year. I’ll see what we can do

jmannau avatar Nov 12 '25 18:11 jmannau

@jmannau We are aiming to include this change along with the CS3D dependent version of the upcoming OHIF 3.12 release, which is expected to be released later this year. When you have the opportunity, could you please prioritize reviewing this MR and share any feedback? Your input would be greatly appreciated and help us to timely include it in the next release.

Thank you!

sen-trenser avatar Nov 17 '25 05:11 sen-trenser

We need to define some requirements as part of this change for what it is that the circle, sphere and elliptical tools are doing. The sphere I believe should always be a sphere in world coordinates, as otherwise it does weird things to the shape. That means it should show as an ellipse if displaying world coordinates does not result in an aspect ratio of 1:1 for the rows/columns.

Circle and circle brushes are harder because of the differences in how things get saved. The circle brush is never saved in image coordinates, so I think we could fairly easily display a circle in the current transformed coordinates. Circle annotations are saved as both MPR in world coordinates and as index coordinates. This needs some documentation in a requirements section for exactly what it is that is meant by "sphere" "circle brush" and "circle tool" under MPR/co-planar modes with index, canvas and world coordinates at different aspect ratios.

wayfarer3130 avatar Dec 17 '25 16:12 wayfarer3130

For the volume (mpr and 3d) use cases, we should define what the aspect ratio means and how it applies in terms of the transform. In general, one can have 3 vectors that the transform is applied along, and those 3 are orthonormal, with a scaling factor defining them. I think this is something we need to figure out how to incorporate into the transform directly rather than trying to figure out which axial/sagittal/coronal it is closest to. That may actually be easier if we used a generic canvas stretch direction vector and orthogonal scale vector rather than x,y scaling. That way the transform for rotation simply rotates the stretch vector.

wayfarer3130 avatar Dec 17 '25 16:12 wayfarer3130

For the volume (mpr and 3d) use cases, we should define what the aspect ratio means and how it applies in terms of the transform. In general, one can have 3 vectors that the transform is applied along, and those 3 are orthonormal, with a scaling factor defining them. I think this is something we need to figure out how to incorporate into the transform directly rather than trying to figure out which axial/sagittal/coronal it is closest to. That may actually be easier if we used a generic canvas stretch direction vector and orthogonal scale vector rather than x,y scaling. That way the transform for rotation simply rotates the stretch vector.

@wayfarer3130 Thank you for the detailed review and for outlining a more generalised approach to handling aspect ratio and scaling for volume, MPR, and 3D use cases. We appreciate the architectural insight and the time spent analysing this area.

We would like to clarify that this pull request is intentionally scoped to enabling stretch behavior for the acquisition orientation only. The suggestion to introduce a generic stretch direction vector, and rotate it based on orthogonal scaling vectors across MPR viewports represents a broader design change that goes beyond the original intent of this contribution.

Incorporating this approach would require a rework of the existing transform model and interaction logic, effectively constituting a separate feature rather than an incremental improvement to the current implementation. It may also refined for behaviors related to other tools in MPR views. Addressing these changes extend beyond the intended scope of this contribution and cannot be incorporated within this pull request without significantly expanding its complexity and impact.

Given this, we would like to ask whether it would be acceptable to proceed with this PR as scoped, without incorporating the suggested generalised stretch behavior.

Thank you again for the review and for maintaining the project.

sen-trenser avatar Dec 22 '25 16:12 sen-trenser

We need to define some requirements as part of this change for what it is that the circle, sphere and elliptical tools are doing. The sphere I believe should always be a sphere in world coordinates, as otherwise it does weird things to the shape. That means it should show as an ellipse if displaying world coordinates does not result in an aspect ratio of 1:1 for the rows/columns.

Circle and circle brushes are harder because of the differences in how things get saved. The circle brush is never saved in image coordinates, so I think we could fairly easily display a circle in the current transformed coordinates. Circle annotations are saved as both MPR in world coordinates and as index coordinates. This needs some documentation in a requirements section for exactly what it is that is meant by "sphere" "circle brush" and "circle tool" under MPR/co-planar modes with index, canvas and world coordinates at different aspect ratios.

@wayfarer3130 In stretched viewports, annotation tools operate in world coordinates, so a Circle ROI defined by a world-space center and radius may render as an ellipse, preserving true physical geometry. The segmentation brush cursor is computed in canvas coordinates and always appears as a perfect circle regardless of stretching. The brush should draw perfect circles, not ellipses, regardless of image stretching. When the image is stretched or shrunk, the drawn segments should stretch or shrink proportionally with the image.

For clarity, the attached video shows the current behavior of the Circle tool, Circle brush, and Sphere brush in a stretched viewport, as implemented in this PR.

https://github.com/user-attachments/assets/1f4ed234-074a-482d-9b05-c16273f9f2f6

arul-trenser avatar Dec 23 '25 11:12 arul-trenser

@wayfarer3130 Thanks for the feedback! I’ve applied the suggested changes and included the documentation. Looking forward to your thoughts; please review and approve if everything looks good.

arul-trenser avatar Dec 23 '25 11:12 arul-trenser