cornerstonejs / cornerstoneTools

[Deprecated] Use Cornerstone3D Instead https://cornerstonejs.org/
MIT License
579 stars 456 forks source link

How to display a bitmap segmentation with brushtool? #895

Closed coolwulf closed 5 years ago

coolwulf commented 5 years ago

Hi, I am new to use this and I am now puzzled on how to display a predefined bitmap mask with brushtool to show segmentation. Could anyone share some example codes? Thanks.

sisobus commented 5 years ago

Hi, I solved it like this. example

cornerstone.loadImage(imageId).then(image => {
    cornerstone.displayImage(element, image);

    cornerstoneTools.mouseInput.enable(element);
    cornerstoneTools.mouseWheelInput.enable(element);
    cornerstoneTools.pan.activate(element, 2);
    cornerstoneTools.zoom.activate(element, 4);
    cornerstoneTools.brush.activate(element, 1);

    cornerstoneTools.touchInput.enable(element);
    cornerstoneTools.panTouchDrag.activate(element);
    cornerstoneTools.zoomTouchPinch.activate(element);
}).then(() => {
    let pixelData = new Uint8ClampedArray(width * height * channel);
    for (let i = 128; i < 256; i++) {
        for (let j = 256; j < 384; j++) {
            pixelData[i*width + j] = 1;
        }
    }
    const toolState = cornerstoneTools.getToolState(element, 'brush');
    if (toolState) {
        toolState.data[0].pixelData = [...pixelData];
    } else {
        cornerstoneTools.addToolState(element, 'brush', { pixelData });
    }
    cornerstone.updateImage(element);
});

If You use 4 channel png image encoded base64 as bitmap mask, I recommend this library. :)

coolwulf commented 5 years ago

@sisobus Thank you a lot for your answer. However I am currently trying to implement cornerstoneTools 3.x instead of 2.x. I added the brushTool using

cornerstoneTools.addTool(cornerstoneTools[`BrushTool`]);
cornerstoneTools.setToolActive('Brush', { mouseButtonMask });

However when I try to get the tool state using

const toolState = cornerstoneTools.getToolState(element, 'Brush');

I got undefined. Any ideas? Thanks.

sisobus commented 5 years ago

@coolwulf I implemented the code below for solving this problem in cornerstoneTools 3.x.

cornerstone.loadImage(imageId).then(image => {
    cornerstone.displayImage(element, image);
    const brushTool = cornerstoneTools.BrushTool;
    const zoomWheelTool = cornerstoneTools.ZoomMouseWheelTool;

    cornerstoneTools.addTool(brushTool);
    cornerstoneTools.addTool(zoomWheelTool);
    cornerstoneTools.setToolActive('Brush', { mouseButtonMask: 1 });
    cornerstoneTools.setToolActive('ZoomMouseWheel', { mouseButtonMask: 1 })
}).then(() => {
    let pixelData = new Uint8ClampedArray(width * height * channel);
    for (let i = 128; i < 256; i++) {
        for (let j = 256; j < 384; j++) {
            pixelData[i*width + j] = 1;
        }
    }
    let toolState = cornerstoneTools.getToolState(element, 'brush');
    if (toolState) {
        toolState.data[0].pixelData = [...pixelData];
    } else {
        cornerstoneTools.addToolState(element, 'brush', { pixelData });
        toolState = cornerstoneTools.getToolState(element, 'brush');
    }
    toolState.data[0].invalidated = true;
    cornerstone.updateImage(element);
});

Hmm.., I don't know why tool type name is not 'Brush' but 'brush' in getToolState. example

sisobus commented 5 years ago

@coolwulf I found the function name of getReferencedToolDataName in brush tool.

const brushTool = cornerstoneTools.BrushTool;
const zoomWheelTool = cornerstoneTools.ZoomMouseWheelTool;
cornerstone.enable(element);
cornerstone.loadImage(imageId).then(image => {
    cornerstone.displayImage(element, image);

    cornerstoneTools.addTool(brushTool);
    cornerstoneTools.addTool(zoomWheelTool);
    cornerstoneTools.setToolActive('Brush', { mouseButtonMask: 1 });
    cornerstoneTools.setToolActive('ZoomMouseWheel', { mouseButtonMask: 1 })
}).then(() => {
    let pixelData = new Uint8ClampedArray(width * height * channel);
    for (let i = 128; i < 256; i++) {
        for (let j = 256; j < 384; j++) {
            pixelData[i*width + j] = 1;
        }
    }
    let toolState = cornerstoneTools.getToolState(
        element,
        brushTool.getReferencedToolDataName()
    );
    if (toolState) {
        toolState.data[0].pixelData = [...pixelData];
    } else {
        cornerstoneTools.addToolState(
            element,
            brushTool.getReferencedToolDataName(),
            { pixelData }
        );
        toolState = cornerstoneTools.getToolState(
            element,
            brushTool.getReferencedToolDataName()
        );
    }
    toolState.data[0].invalidated = true;
    cornerstone.updateImage(element);
})

example

coolwulf commented 5 years ago

@sisobus This works beautifully. Thanks a lot.

Best regards

dannyrb commented 5 years ago

@all-contributors please add @sisobus for answering questions ^_^

allcontributors[bot] commented 5 years ago

@dannyrb

I've put up a pull request to add @sisobus! :tada:

dannyrb commented 5 years ago

@JamesAPetts is this an example we should include on our examples page or in our docs?

coolwulf commented 5 years ago

@sisobus Actually I have one more question. I know you can change the brush color by using

cornerstoneTools.store.modules.brush.state.drawColorId=3;

But how can I change the added segmentation color? Thanks.

Best,

dannyrb commented 5 years ago

Hmm.. I guess you can change it directly that way. It's worth noting that the BaseBrushTool exposed a method to update the drawColorId:

https://github.com/cornerstonejs/cornerstoneTools/blob/master/src/tools/base/BaseBrushTool.js#L248-L284

how can I change the added segmentation color?

@JamesAPetts would likely know the answer to this.

coolwulf commented 5 years ago

@sisobus @dannyrb @JamesAPetts I found the answer to this just now.

how can I change the added segmentation color?

You have to add additional addToolState for brush tool then invalidate the corresponding one for specific color. Example code:

                    let toolState=cornerstoneTools.getToolState(
                        canvas,
                        cornerstoneTools[`BrushTool`].getReferencedToolDataName
                    );
                    if (toolState) {
                        toolState.data[0].pixelData = [...pixelData];
                    } else {
                        cornerstoneTools.addToolState(
                            canvas,
                            brushTool.getReferencedToolDataName(),
                            { }
                        );
                        cornerstoneTools.addToolState(
                            canvas,
                            brushTool.getReferencedToolDataName(),
                            { pixelData }
                        );                  
                        toolState = cornerstoneTools.getToolState(
                            canvas,
                            brushTool.getReferencedToolDataName()
                        );
                    }
                    toolState.data[1].invalidated = true;
                            cornerstone.updateImage(canvas);

This will display blue segmentation color (for drawColorId=1) instead of red (drawColorId=0).

Still. Thanks for everyone helping me here. I just started using this library and found it very useful.

JamesAPetts commented 5 years ago

@dannyrb

is this an example we should include on our examples page or in our docs?

Yeah its a nice generic case, we actually have similar utilities and examples in dcmjs for parsing DICOM SEG to cornerstone, but they are all DICOM specific.

@coolwulf

But how can I change the added segmentation color? Thanks.

TLDR, no one has implemented it yet, more detail:

The colormap is currently hard coded in the brush store here. It would be nice to have support for an infinite number of colors, and I already half implemented that here by generating interpolated colors past the defaults, but defaultSegmentationCount is still just hardcoded as 19. It'd also be nice to change the color of a segment via some UI. We could expose an api for this. Some sources (e.g. DICOM SEG) dictate what color and individual segment should be colored.

This should be rather trivial, just no one has got around to it yet. Its on my TODO list, but not right at the top of my current priorities.

JamesAPetts commented 5 years ago

Just a heads up:

how can I change the added segmentation color?

and

how to display a predefined bitmap mask with brushtool to show segmentation?

should be much much more straightforward in an upcomming major version: #953 .

Cheers, James

ashishbairwa commented 3 years ago

@JamesAPetts @sisobus Can you please provide some examples or hints to load 2d bitmap masks using those new tools that had merged in vNext? I'm trying to find some examples within the doc but couldn't find anything that is truly helpful.