feat: add segment label tool (#5164)

This commit is contained in:
Pedro Köhler 2025-07-09 15:11:54 -03:00 committed by GitHub
parent d19cd6ec7b
commit ac852485cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 351 additions and 340 deletions

540
bun.lock

File diff suppressed because it is too large Load Diff

View File

@ -46,8 +46,8 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^3.24.0",
"@cornerstonejs/core": "^3.24.0",
"@cornerstonejs/adapters": "^3.28.2",
"@cornerstonejs/core": "^3.28.2",
"@kitware/vtk.js": "32.12.0",
"react-color": "^2.19.3"
}

View File

@ -46,8 +46,8 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^3.24.0",
"@cornerstonejs/core": "^3.24.0",
"@cornerstonejs/adapters": "^3.28.2",
"@cornerstonejs/core": "^3.28.2",
"@kitware/vtk.js": "32.12.0",
"react-color": "^2.19.3"
}

View File

@ -46,9 +46,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^3.24.0",
"@cornerstonejs/core": "^3.24.0",
"@cornerstonejs/tools": "^3.24.0",
"@cornerstonejs/adapters": "^3.28.2",
"@cornerstonejs/core": "^3.28.2",
"@cornerstonejs/tools": "^3.28.2",
"classnames": "^2.3.2"
}
}

View File

@ -42,8 +42,8 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/core": "^3.24.0",
"@cornerstonejs/tools": "^3.24.0",
"@cornerstonejs/core": "^3.28.2",
"@cornerstonejs/tools": "^3.28.2",
"classnames": "^2.3.2"
}
}

View File

@ -38,7 +38,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.4",
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/dicom-image-loader": "^3.24.0",
"@cornerstonejs/dicom-image-loader": "^3.28.2",
"@ohif/core": "3.11.0-beta.74",
"@ohif/ui": "3.11.0-beta.74",
"dcmjs": "^0.42.0",
@ -51,12 +51,12 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^3.24.0",
"@cornerstonejs/ai": "^3.24.0",
"@cornerstonejs/core": "^3.24.0",
"@cornerstonejs/labelmap-interpolation": "^3.24.0",
"@cornerstonejs/polymorphic-segmentation": "^3.24.0",
"@cornerstonejs/tools": "^3.24.0",
"@cornerstonejs/adapters": "^3.28.2",
"@cornerstonejs/ai": "^3.28.2",
"@cornerstonejs/core": "^3.28.2",
"@cornerstonejs/labelmap-interpolation": "^3.28.2",
"@cornerstonejs/polymorphic-segmentation": "^3.28.2",
"@cornerstonejs/tools": "^3.28.2",
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
"@kitware/vtk.js": "32.12.0",
"html2canvas": "^1.4.1",

View File

@ -1728,6 +1728,17 @@ function commandsModule({
}
});
},
toggleSegmentLabel: ({ toggle }) => {
const toolGroupIds = toolGroupService.getToolGroupIds();
toolGroupIds.forEach(toolGroupId => {
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId);
if (toggle) {
toolGroup.setToolActive(cornerstoneTools.SegmentLabelTool.toolName);
} else {
toolGroup.setToolDisabled(cornerstoneTools.SegmentLabelTool.toolName);
}
});
},
toggleUseCenterSegmentIndex: ({ toggle }) => {
let labelmapTools = getLabelmapTools({ toolGroupService });
labelmapTools = labelmapTools.filter(tool => !tool.toolName.includes('Eraser'));
@ -2331,6 +2342,7 @@ function commandsModule({
hydrateSecondaryDisplaySet: actions.hydrateSecondaryDisplaySet,
getVolumeIdForDisplaySet: actions.getVolumeIdForDisplaySet,
triggerCreateAnnotationMemo: actions.triggerCreateAnnotationMemo,
toggleSegmentLabel: actions.toggleSegmentLabel,
};
return {

View File

@ -38,6 +38,7 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser
const [previewEdits, setPreviewEdits] = useState(false);
const [toggleSegmentEnabled, setToggleSegmentEnabled] = useState(false);
const [useCenterAsSegmentIndex, setUseCenterAsSegmentIndex] = useState(false);
const [shouldShowLabelOnHover, setShouldShowLabelOnHover] = useState(false);
const handlePreviewEditsChange = checked => {
setPreviewEdits(checked);
commandsManager.run('toggleSegmentPreviewEdit', { toggle: checked });
@ -53,6 +54,11 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser
commandsManager.run('toggleUseCenterSegmentIndex', { toggle: checked });
};
const handleToggleShowLabelOnHover = checked => {
setShouldShowLabelOnHover(checked);
commandsManager.run('toggleSegmentLabel', { toggle: checked });
};
return (
<div className="bg-muted flex flex-col gap-4 border-b border-b-[2px] border-black px-2 py-3">
<div className="flex items-center gap-2">
@ -78,6 +84,14 @@ export default function getSegmentationPanelCustomization({ commandsManager, ser
/>
<span className="text-base text-white">Hover on segment border to activate</span>
</div>
<div className="flex items-center gap-2">
<Switch
checked={shouldShowLabelOnHover}
onCheckedChange={handleToggleShowLabelOnHover}
/>
<span className="text-base text-white">Show segment label on mouse hover</span>
</div>
</div>
);
},

View File

@ -40,6 +40,7 @@ import {
WindowLevelRegionTool,
SegmentSelectTool,
RegionSegmentPlusTool,
SegmentLabelTool,
} from '@cornerstonejs/tools';
import { LabelmapSlicePropagationTool, MarkerLabelmapTool } from '@cornerstonejs/ai';
import * as polySeg from '@cornerstonejs/polymorphic-segmentation';
@ -104,6 +105,7 @@ export default function initCornerstoneTools(configuration = {}) {
addTool(WindowLevelRegionTool);
addTool(PlanarFreehandContourSegmentationTool);
addTool(SegmentSelectTool);
addTool(SegmentLabelTool);
addTool(LabelmapSlicePropagationTool);
addTool(MarkerLabelmapTool);
addTool(RegionSegmentPlusTool);
@ -162,6 +164,7 @@ const toolNames = {
PlanarFreehandContourSegmentation: PlanarFreehandContourSegmentationTool.toolName,
SegmentBidirectional: SegmentBidirectionalTool.toolName,
SegmentSelect: SegmentSelectTool.toolName,
SegmentLabel: SegmentLabelTool.toolName,
LabelmapSlicePropagation: LabelmapSlicePropagationTool.toolName,
MarkerLabelmap: MarkerLabelmapTool.toolName,
RegionSegmentPlus: RegionSegmentPlusTool.toolName,

View File

@ -32,8 +32,8 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@cornerstonejs/core": "^3.24.0",
"@cornerstonejs/tools": "^3.24.0",
"@cornerstonejs/core": "^3.28.2",
"@cornerstonejs/tools": "^3.28.2",
"@ohif/core": "3.11.0-beta.74",
"@ohif/extension-cornerstone-dicom-sr": "3.11.0-beta.74",
"@ohif/extension-default": "3.11.0-beta.74",

View File

@ -95,6 +95,12 @@ function initDefaultToolGroup(extensionManager, toolGroupService, commandsManage
{
toolName: toolNames.AdvancedMagnify,
},
{
toolName: toolNames.SegmentLabel,
configuration: {
hoverTimeout: 1,
},
},
],
};

View File

@ -114,7 +114,16 @@ function createTools(utilityModule) {
{ toolName: toolNames.UltrasoundDirectional },
],
disabled: [{ toolName: toolNames.ReferenceLines }, { toolName: toolNames.AdvancedMagnify }],
disabled: [
{ toolName: toolNames.ReferenceLines },
{ toolName: toolNames.AdvancedMagnify },
{
toolName: toolNames.SegmentLabel,
configuration: {
hoverTimeout: 1,
},
},
],
};
}

View File

@ -53,7 +53,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.4",
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/dicom-image-loader": "^3.24.0",
"@cornerstonejs/dicom-image-loader": "^3.28.2",
"@emotion/serialize": "^1.1.3",
"@ohif/core": "3.11.0-beta.74",
"@ohif/extension-cornerstone": "3.11.0-beta.74",

View File

@ -37,8 +37,8 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.4",
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/core": "^3.24.0",
"@cornerstonejs/dicom-image-loader": "^3.24.0",
"@cornerstonejs/core": "^3.28.2",
"@cornerstonejs/dicom-image-loader": "^3.28.2",
"@ohif/ui": "3.11.0-beta.74",
"cornerstone-math": "0.1.9",
"dicom-parser": "^1.8.21"

View File

@ -1423,10 +1423,10 @@
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
"@cornerstonejs/adapters@^3.24.0":
version "3.24.0"
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-3.24.0.tgz#fdf4de330b74a0744cfa4b1994b8f583c7c2857b"
integrity sha512-iE2C6PD2TpibUwlBeJb2RRcItY8kv0K11Szs/zvELAyYRT3Am34qTmlQKI/o1l/dw9es/OSa5ce1P9Mxd8Orpg==
"@cornerstonejs/adapters@^3.28.2":
version "3.28.2"
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-3.28.2.tgz#9350efe3d01158566bf23d108e2376802b571911"
integrity sha512-SWa9l5KAPHIuzTmks64PtI9Ua86dmYbJNBjxqsvAbU9T5PGpaHUu0Qw5sW1WthnGsgk+cZEp2Uv1TkbgJjr5vQ==
dependencies:
"@babel/runtime-corejs2" "^7.17.8"
buffer "^6.0.3"
@ -1434,10 +1434,10 @@
gl-matrix "^3.4.3"
ndarray "^1.0.19"
"@cornerstonejs/ai@^3.24.0":
version "3.24.0"
resolved "https://registry.yarnpkg.com/@cornerstonejs/ai/-/ai-3.24.0.tgz#d07390ee0dba3927ec30526f24c36b46047e1e6a"
integrity sha512-vmpbnFyc0CaOyd212XXtRGEpGoFHB3oujofXuRXi+dxqVS3Jq5ch0yxJ0iyjT3yn0wpu02NNAaxI8ebZ1DO06Q==
"@cornerstonejs/ai@^3.28.2":
version "3.28.2"
resolved "https://registry.yarnpkg.com/@cornerstonejs/ai/-/ai-3.28.2.tgz#756b760fb74c4eeb4ac138ade908ca4e7d3acf16"
integrity sha512-eWX+6KYUbVVcq10BlsX07nmTWJIQo9YqNychr+jRHlCYqM9SBtSshCM4lcC2YMH+NTfOhw8+5PgqqDrxlUcUjQ==
dependencies:
"@babel/runtime-corejs2" "^7.17.8"
buffer "^6.0.3"
@ -1473,7 +1473,7 @@
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.7.tgz#784394d05d8cf735640e9c3baa206535ee8e0376"
integrity sha512-qvP4q4JDib7mi9r7LqKOwqz7YZ8gjtDX4ZCezeYf8+eb7MBXCz5uXAMeVF3yz9Axw4XiIMdB/pqXkm8tqCl13w==
"@cornerstonejs/core@^3.16.0", "@cornerstonejs/core@^3.24.0":
"@cornerstonejs/core@^3.16.0":
version "3.24.0"
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-3.24.0.tgz#6f184b5eedbf5cc2266bb899cf9454cd866b4e4e"
integrity sha512-Ep5hVrM5XMVuExL2i8tiVuFGqoi1QyaZpU3WzxqhH75nNpckSi/ZYqic4rI3qb/V4IKYv2R+8Gp4Jptl110u4A==
@ -1483,10 +1483,20 @@
gl-matrix "^3.4.3"
loglevel "^1.9.2"
"@cornerstonejs/dicom-image-loader@^3.24.0":
version "3.24.0"
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-3.24.0.tgz#d609055154676a515a1893f2140e1d144d4e334c"
integrity sha512-ATus6vP/bi7bCDigIJ6rk39pmw+6qaNS0eF/Tzki00/3xCY8a4zAYK5MqUPLrZb3ovc8D2qZHUT4x8na3ldyBw==
"@cornerstonejs/core@^3.28.2":
version "3.28.2"
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-3.28.2.tgz#a0070c32c1f49dbb4bc3038b2be8bc8a23986867"
integrity sha512-U6nMV5dlbiKja5xJpDWArBrCsHul8N+D5hBK+CQS9FnMdZSVEOcGu9cciaB7k19TuNbcs2ghU/+6WHRQN8WXzA==
dependencies:
"@kitware/vtk.js" "32.12.1"
comlink "^4.4.1"
gl-matrix "^3.4.3"
loglevel "^1.9.2"
"@cornerstonejs/dicom-image-loader@^3.28.2":
version "3.28.2"
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-3.28.2.tgz#ae04dc0384a6fed6a4b35e2d19c1eb06d38c4d31"
integrity sha512-o4G1KI3xQ485zqJHnZEKHoFD8ysTEaEtc7q6OP5JpQIyUqPgGH9deOubbENyE+iOy/NjVv1r3xdIQkJ4v9d2fw==
dependencies:
"@cornerstonejs/codec-charls" "^1.2.3"
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
@ -1498,22 +1508,22 @@
pako "^2.0.4"
uuid "^9.0.0"
"@cornerstonejs/labelmap-interpolation@^3.24.0":
version "3.24.0"
resolved "https://registry.yarnpkg.com/@cornerstonejs/labelmap-interpolation/-/labelmap-interpolation-3.24.0.tgz#efb5e75ab7c5e2c1cfbbd2e20f2f01239b334a1a"
integrity sha512-gKobUWITedLtr3AnoZ8XNQLnv+HnutL8De8bjk7NnhQr51TprU2KjOFbFAiDZJ3ckdrFdCW5z0z7VTolXNEshQ==
"@cornerstonejs/labelmap-interpolation@^3.28.2":
version "3.28.2"
resolved "https://registry.yarnpkg.com/@cornerstonejs/labelmap-interpolation/-/labelmap-interpolation-3.28.2.tgz#d11dad9996e9b2b8530da210f51b96acab861a8d"
integrity sha512-bGlggn831ycCbur2jcfphnRPiaRO01HwwynuQ9IUtxNjNdzCG6t+7/UxEf59pOltpBm+t7zpW5EiF0ir+LNbDg==
dependencies:
"@itk-wasm/morphological-contour-interpolation" "1.1.0"
itk-wasm "1.0.0-b.165"
"@cornerstonejs/polymorphic-segmentation@^3.24.0":
version "3.24.0"
resolved "https://registry.yarnpkg.com/@cornerstonejs/polymorphic-segmentation/-/polymorphic-segmentation-3.24.0.tgz#50dbe289bf80f112825489c3f8f15b2a4656589f"
integrity sha512-fRaz2MYyImpBIt6MuUPYOdrhxUvq7fgHfV5eoMt+cgUP15vUGfhzlcUXEk+2MzqFnk4WTh8nkFoCos1IWD1ZUg==
"@cornerstonejs/polymorphic-segmentation@^3.28.2":
version "3.28.2"
resolved "https://registry.yarnpkg.com/@cornerstonejs/polymorphic-segmentation/-/polymorphic-segmentation-3.28.2.tgz#fd33cb544178f057dc525ac6de5bc2c59e2220b1"
integrity sha512-OPWlSyIiSojh71rvlxFt7ZapeySeE2DZwxbriDgxpjTPJDoSRKmvg9FiShbdBcqYGWoIsGcAxucjhsFkQbs7MQ==
dependencies:
"@icr/polyseg-wasm" "0.4.0"
"@cornerstonejs/tools@^3.16.0", "@cornerstonejs/tools@^3.24.0":
"@cornerstonejs/tools@^3.16.0":
version "3.24.0"
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-3.24.0.tgz#7e4bb8a8e8a982316e8f53282441f888f26bb70b"
integrity sha512-KYkElmvmFwuskKnp9glUIwiHYyVfr1LCqOjhj1y1+rgzxAqlrfaGmS7y8KHOqGHzQwXMMoaEKzRGRviAS915tg==
@ -1522,6 +1532,15 @@
comlink "^4.4.1"
lodash.get "^4.4.2"
"@cornerstonejs/tools@^3.28.2":
version "3.28.2"
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-3.28.2.tgz#994510cc475415663a044665f30750a11d71d6fc"
integrity sha512-QgwZDPec8/9d3ZxVAXdLWpzCCaBx38/lyPAB+XrzIqkc+QHEozqCIyiQO1VtOk0UeIInbQ4NjkP9JrORkQNUrw==
dependencies:
"@types/offscreencanvas" "2019.7.3"
comlink "^4.4.1"
lodash.get "^4.4.2"
"@cspotcode/source-map-support@^0.8.0":
version "0.8.1"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"