cornerstonejs / cornerstonetools Goto Github PK
View Code? Open in Web Editor NEWA framework for tools built on top of Cornerstone.
Home Page: https://tools.cornerstonejs.org/
License: MIT License
A framework for tools built on top of Cornerstone.
Home Page: https://tools.cornerstonejs.org/
License: MIT License
e.g. measurement added, measurement changed, measurement deleted
https://groups.google.com/forum/#!topic/cornerstone-platform/FqHDhtNRtEE
What is the point of processingTouch
? I never see it get set to true.
I've been working on developing a very basic DICOM viewer that restyles and extends the existing CornerstoneDemo project recently and seemed to have encountered an issue with IE compatibility.
I'm using the latest version of CornerstoneTools (0.6.2), the latest version of Cornerstone.js (0.7.7) and for the most part all of the tools have been working as expected (similar to the All Image Tools example) with the exception of Internet Explorer, where the measurement events (e.g. Length, Angle, etc.) do not appear to work at all.
The previously mentioned All Image Tools example has them working just as you might expect within Internet Explorer, but when using an approach similar to the CornerstoneDemo, you'll notice that functions like Length and Angle do not get picked up for it.
The code for each is roughly the same :
// Define the element (equivalent to the Viewport and contains the <canvas> element)
var element = $('#dicomImage').get(0);
// Event handlers and other code (omitted for brevity)
// Code to enable the length tool
$('#enableLength').click(function() {
activate('#enableLength')
disableAllTools();
cornerstoneTools.length.activate(element, 1);
});
// Length measurement
$('#length').on('click touchstart', function () {
disableAllTools();
// Test for a single viewport (targets the proper element, but none of the mouse events
// are triggered after this executes
cornerstoneTools.length.activate($('.viewport').get(0), 1);
//forEachViewport(function (element) {
// cornerstoneTools.length.activate(element, 1);
//});
});
I placed debugger;
and console.log(...)
calls throughout the inner functions to see if I could pick up on anything, but it's as if none of the mouse events at all are getting picked up within IE with Angle or Measurement selected.
Any ideas of something that I might be missing? I feel like it should be working (as it does in other browsers), but it may simply be my unfamiliarity with the project thus far that has caused me to miss something painfully obvious.
After trying for hours to make this work I post this here because maybe its a bug.
I have only one element to display images with the zoomTouchPinch tool attached. There are two images to be loaded there, one with cornerstoneWebImageLoader, the other with cornerstoneWADOImageLoader.
When I load the first image (it doesn't matter the order, it can be Web or WADO), it works as expected (expand fingers zoom in, contract fingers zoom out), then I switch (*) the image and zoomTouchPinch goes crazy allways zoomming out. It looks like this tool is not "reseted" properly before attaching to the new image.
*: The switching process follows these steps inside loadAndCacheImage:
// the next two lines refreshes the element. I don't know if there's a better way
cornerstone.disable(element);
cornerstone.enable(element);
cornerstone.displayImage(element, image);
cornerstoneTools.touchInput.enable(element);
cornerstoneTools.zoomTouchPinch.activate(element);
I've tried zoomTouchPinch.disable(element) before activate, but it doesn't fix the issue.
Simple angle touch tool doesn't work. When I tough the viewport only the first point is drawn and nothing else happenes.
How does the length measurement tool convert pixels into length units?
As discussed on the Google group, we need a way to mark certain stacks as 'uncacheable' so that developers can build sites that depend on dynamic image fusion.
Something like this:
var stack = {
currentImageIdIndex : 0,
imageIds: imageIds,
preventCache: true
};
cornerstoneTools.addToolState(element, 'stack', stack);
If this flag is set, all tools (e.g. Crosshairs, synchronizers...) that use loadAndCacheImage should use loadImage instead.
Relevant threads:
https://groups.google.com/forum/#!topic/cornerstone-platform/mst1b6ZB4T8
https://groups.google.com/forum/#!topic/cornerstone-platform/FHM4tWQcy8s
The CornerstoneToolsMouseWheel
event is triggered with incomplete data in Firefox. This is because the pageX
and pageY
properties are only available via e.originalEvent
.
The following patch works for me:
diff --git a/src/inputSources/mouseWheelInput.js b/src/inputSources/mouseWheelInput.js
index 8380ac9..437b0ab 100755
--- a/src/inputSources/mouseWheelInput.js
+++ b/src/inputSources/mouseWheelInput.js
@@ -22,7 +22,7 @@ var cornerstoneTools = (function ($, cornerstone, cornerstoneTools) {
}
var element = e.currentTarget;
- var startingCoords = cornerstone.pageToPixel(element, e.pageX, e.pageY);
+ var startingCoords = cornerstone.pageToPixel(element, e.pageX || e.originalEvent.pageX, e.pageY || e.originalEvent.pageY);
e = window.event || e; // old IE support
var wheelDelta = e.wheelDelta || -e.detail || -e.originalEvent.detail;
@@ -33,8 +33,8 @@ var cornerstoneTools = (function ($, cornerstone, cornerstoneTools) {
viewport: cornerstone.getViewport(element),
image: cornerstone.getEnabledElement(element).image,
direction : direction,
- pageX : e.pageX,
- pageY: e.pageY,
+ pageX : e.pageX || e.originalEvent.pageX,
+ pageY: e.pageY || e.originalEvent.pageY,
imageX : startingCoords.x,
imageY : startingCoords.y
};
@@ -61,4 +61,4 @@ var cornerstoneTools = (function ($, cornerstone, cornerstoneTools) {
};
return cornerstoneTools;
-}($, cornerstone, cornerstoneTools));
\ No newline at end of file
+}($, cornerstone, cornerstoneTools));
Currently for checking points near the ellipse ROI tool we use a rectangle. This makes the tool feel a bit awkward when you try to select it near the 'corners' of the ellipse.
The relevant block of code is
function pointNearTool(element, data, coords) {
// TODO: Find a formula for shortest distance between point and ellipse. Rectangle is close enough
var startCanvas = cornerstone.pixelToCanvas(element, data.handles.start);
var endCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
var rect = {
left: Math.min(startCanvas.x, endCanvas.x),
top: Math.min(startCanvas.y, endCanvas.y),
width: Math.abs(startCanvas.x - endCanvas.x),
height: Math.abs(startCanvas.y - endCanvas.y)
};
var distanceToPoint = cornerstoneMath.rect.distanceToPoint(rect, coords);
return (distanceToPoint < 5);
It can be found here:
https://github.com/chafey/cornerstoneTools/blob/master/src/imageTools/ellipticalRoi.js#L24
What we should do is:
Get the region bounded by two ellipses: the current ellipse, and another generated ellipse that is slightly larger in all directions. If the point lies inside the larger ellipse but not the smaller one, it should be considered 'nearby' the small ellipse.
This calculation can be done using the equation here: http://math.stackexchange.com/questions/76457/check-if-a-point-is-within-an-ellipse/76463#76463
Some way of "saving" the transformed image to PNG, etc.
For example, see:
Along the lines of the rectangle ROI but with the ability to specify multiple knot points.
Something like this: http://ttic.uchicago.edu/~smaji/projects/mturk/interfaces/segmentation/person.html?category-image=person,2011_000745_10.jpg which has some cool features for detecting a closed polygon and indicating such (floating dot gets larger when near initial point).
Also see OsiriX which has the feature albeit with some smoothing offered:
https://osirixpluginbasics.wordpress.com/2010/11/27/polygon-roi-tcpolygon-topolygon-tpencil/
We need an API to store / retrieve the enabled/activated tools for each mouse button. This will make it easier for users to switch tools in their applications.
Brought up here:
https://groups.google.com/forum/#!topic/cornerstone-platform/6JVm2Jb59SI
Already in the "backlog", but I'm creating this ticket to track feature.
Other than the very comprehensive cornerstoneDemo, are there any examples of using cornerstoneTools
with a full set of the supported tools? For example a simple image viewer that has something comparable to:
The examples listed here seems to pretty simplistic when compared to the full demo.
I have a series of images, for example, image1, image2 and image3. If I draw a rectangle ROI on image1, I want this ROI also shown on image2 and image3. I wonder If it is possible?
I've tried it with IE and Firefox but it doesn't work. Only the arrow is drawn but the modal with the text box doesn't appear.
I get this error message in the console:
TypeError: dialog.get(...).showModal is not a function (index.html:132:8)
Synchronizers should listen for CornerstoneElementDisabled and remove any sources/targets to these elements. This would save time manually removing elements from Synchronizers.
This is now part of #111
Length tool doesn't show the length in mm but in pixels only. The issue is present in MG series only.
You can use this image for testing:
Hi,
I think there is an issue with the arrowAnnotateTouch tool, when I try to activate it, it says: Uncaught ReferenceError: eventData is not defined
It seems to be the line:
$(element).on('CornerstoneToolsDragStartActive', eventData, touchDownActivateCallback);
...in the src/imageTools/annotation.js file. Or I am doing something wrong? It looks like eventData isn't in the scope.
Thanks in advance!
Since the changes made in 2015.12.18 tools such as length, ellipse, rectangle, angle don't work
I want to write some text on image
I want to save image after modification like measurement,highlight ,probe
Multiple highlight on image
will you please help me out
thanks
I've found after a bit of testing that the annotations that appear with each of the major measurements (e.g. Length, Angles, etc.) appear to be quite far off from the actual areas that are being measured. This can often cause the measurements to be left off the canvas entirely as seen below :
When troubleshooting the issue, I found that each of the X,Y coordinates seemed to usually be off by about ~1000 pixels and when explicitly subtracting those values :
// Adjustment for annotations (Line 3053 of cornerstoneTools.js)
context.fillText(text, textX - 1000, textY - 1000);
After doing this the annotations usually appeared at a much more reasonable location :
I know that this is by no means an attempt to fix or resolve this issue (or an appropriate way to handle it I believe). Something is likely wrong with how these values are being calculated. I noticed the issue first appeared after the latest release of the core library (cornerstone.js). It's likely a result of the `fontParameters.fontScale' variable being often quite small (~0.1) which could be causing the midpoint values to balloon up :
var textX = (data.handles.start.x + data.handles.end.x) / 2 / fontParameters.fontScale;
var textY = (data.handles.start.y + data.handles.end.y) / 2 / fontParameters.fontScale;
This may simply be something minor in the core that isn't being read properly or a variable that isn't being set, but I thought it was worth bringing up.
See this thread:
https://groups.google.com/forum/#!topic/cornerstone-platform/lcvUVzikNsE
We should handle this better - perhaps by preventing the handlers from being added if they are already on there, or at least a console warning. Should also consider this for other enable()/disable() pairs too
I've been playing around with using a single container that contains multiple viewports that I add a "synced" attribute to in order to iterate through them and add them to a synchronizer. However, it doesn't seem to be working as expected.
I'm only using the scrollStack
tool for example purposes and the behavior that I am looking for is "when one of the synced elements is scrolled, all of the elements will scroll up", however the current behavior seems to have all of the elements scrolling independently (e.g. if you scroll the first viewport to the 50th image, when you try to scroll another one of the elements, it will begin at the 50th element). So it seems that the actual index is being synced between the viewports, but the actual viewports do not all scroll at the same time (which is the expected behavior).
A rough example of the code that I am using to wire up this syncronizer looks like the following :
// Create a syncronizer
imageViewer.syncronizers.push(new cornerstoneTools.Synchronizer("CornerstoneNewImage", cornerstoneTools.stackImageIndexSynchronizer));
// Activate all of the view ports (within the new template that was added)
$('.viewport.synced', viewportTemplate).each(function () {
var element = $(this).get(0);
cornerstone.enable(element);
// Populate the number of view ports that need to be populated
if (imageIndex < $('.viewport.synced', viewportTemplate).length && imageIndex < activeStack.imageIds.length) {
// Store the current instance on the element
$(this).attr('data-instance', imageIndex);
// Pull the specific image to be loaded for this stack (relative to the appropriate position)
var image = imageViewer.images[activeStack.imageIds[imageIndex++]];
// Add this viewport to the collection of viewports (along with the stack / series it is associated with)
imageViewer.viewports.push({ Viewport: element, Series: activeStack });
// Display the image on the viewer element
if (image != undefined) {
// Load the image and wire up the appropriate tools, adding the element to the syncronizer
cornerstone.displayImage(element, image);
cornerstoneTools.addStackStateManager(element, ['stack']);
cornerstoneTools.addToolState(element, 'stack', activeStack);
cornerstoneTools.stackScroll.activate(element, 1);
cornerstoneTools.stackScrollWheel.activate(element);
imageViewer.syncronizers[0].add(element);
}
// Details omitted for brevity
}
});
When comparing this to the available example within the tooling, it seems that all of the similar behaviors are being taken :
// Define these elements (equivalent to the synced viewports above)
var axialElement1 = $('#axial1').get(0);
var axialElement2 = $('#axial2').get(0);
var axialElement3 = $('#axial3').get(0);
// Grab the image ids from the stack (present in the activeStack above)
var axialImageIds = [ 'example://1', 'example://2']
var axialStack1 = { currentImageIdIndex : 0, imageIds: axialImageIds };
var axialStack2 = { currentImageIdIndex : 0, imageIds: axialImageIds };
var axialStack3 = { currentImageIdIndex : 0, imageIds: axialImageIds };
// Define a syncronizer to use (present in the imageViewer.syncronizers collection above)
var synchronizer = new cornerstoneTools.Synchronizer("CornerstoneNewImage", cornerstoneTools.stackImageIndexSynchronizer);
// Enable each element
cornerstone.enable(axialElement1);
cornerstone.enable(axialElement2);
cornerstone.enable(axialElement3);
// Enable elements for this element
cornerstoneTools.mouseInput.enable(axialElement1);
cornerstoneTools.mouseWheelInput.enable(axialElement1);
cornerstoneTools.mouseInput.enable(axialElement2);
cornerstoneTools.mouseWheelInput.enable(axialElement2);
cornerstoneTools.mouseInput.enable(axialElement3);
cornerstoneTools.mouseWheelInput.enable(axialElement3);
// Images are already loaded within the imageViewer.images collection (so grab them)
cornerstone.loadImage(axialImageIds[0]).then(function(image) {
// display this image (equivalent to being called within the loop)
cornerstone.displayImage(axialElement1, image);
cornerstone.displayImage(axialElement2, image);
cornerstone.displayImage(axialElement3, image);
// set the stack as tool state (being set above as well)
cornerstoneTools.addStackStateManager(axialElement1, ['stack']);
cornerstoneTools.addStackStateManager(axialElement2, ['stack']);
cornerstoneTools.addStackStateManager(axialElement3, ['stack']);
// Is the issue that these are all targeting the same stack? Should they be independent elements?
cornerstoneTools.addToolState(axialElement1, 'stack', axialStack1);
cornerstoneTools.addToolState(axialElement2, 'stack', axialStack2);
cornerstoneTools.addToolState(axialElement3, 'stack', axialStack3);
// Enable all tools we want to use with this element
cornerstoneTools.stackScroll.activate(axialElement1, 1);
cornerstoneTools.stackScrollWheel.activate(axialElement1);
cornerstoneTools.stackScroll.activate(axialElement2, 1);
cornerstoneTools.stackScrollWheel.activate(axialElement2);
cornerstoneTools.stackScroll.activate(axialElement3, 1);
cornerstoneTools.stackScrollWheel.activate(axialElement3);
// Done above as well
synchronizer.add(axialElement1);
synchronizer.add(axialElement2);
synchronizer.add(axialElement3);
}
Is there anything in particular that looks to be missing or that I should be looking into as to why each of the elements may not be all syncing as expected. Any ideas or insight would be helpful and I would be glad to try and provide some additional examples if needed.
Hi, what does the error "uncaught exception: stackPrefetch: batch failed for element: dicomImage0" mean?, in my browser's develoer's tools -> network I don't see any 404 error when loading wado images.
I haven't got that far in my code but I suspect they just perform whatever button 1 action is select in addition to pan and zoom. Noted on IE11, Firefox 32, and Chrome.
After annotating some images with areas of near white, I noticed the default non-active color for annotations is also white, so they completely disappear when overlying white areas. This is particularly a problem when an arrowhead or measurement overlies a white area.
Using a non-grayscale default color like red could work for most cases, but probably the best solution would be to draw all annotations with a contrasting "shadow". Not sure how you would prefer to architect this as each tool handles drawing on its own. Perhaps simply a custom function to handle line drawing that references a tool config to decide whether to draw the shadow?
Pinching to zoom does not seem to function on Windows 8.1 Surface 2 Pro using IE 11, Firefox 29.0 and Chrome 33.0.1750.154 m. Zoom actions appears to be intercepted by the browser first so the entire viewport zooms up. Very similar experience with the Mac desktop using the Apple Trackpad try to do the pinching motion. (I know I am asking for too much, but this is just for the record to build the future test cases.)
Window/Level only worked on Firefox 29. Also in the display, I could not easily close the window in FF 29. This may be due to the fact that I had the Touch mode on on the FF 29.
I'm not 100% sure but I think that the bug appears on images which don't have 1:1 resolution (for example 800x500, 733x888...). The problem is that the text appears too far away from the ellipse. See the attached images.
The rectangle tool doesn't have this problem.
I have tried the ellipse on 512x512 images and it works just fine
This is related to / explanation for:
cornerstonejs/cornerstone#16 (comment)
See:
http://stackoverflow.com/a/6722031/2638485
but basically this call is not correct if scale != 1
:
context.rect(0, 0, context.canvas.clientWidth, context.canvas.clientHeight);
which it likely won't be after setToPixelCoordinateSystem
.
With the latest build of Erik's hammerjs branch of the repository, it appears to have some unexpected (at least in my mind) behaviors associated with it after the recent changes.
Many of the tools will appear to relate to one another after one event has stopped and another one has began (using the same tool) as seen below :
As I mentioned previously, this only arose after using the latest cornerstoneTools changes with the hammerjs branch. The two may have some conflicting issues or may have simply not been ready to interact with one another as of yet, but I thought I would make the issue at least known.
If I draw a ROI on an image, could I just save this area to a png file?
I was fiddling around and got my app locked up.
the range function needs assertions because it can end up in a long loop.
suggested patch:
function range(lowEnd, highEnd) {
// Javascript version of Python's range function
// http://stackoverflow.com/questions/3895478/does-javascript-have-a-method-like-range-to-generate-an-array-based-on-suppl
//don't allow undefined / null to be passed to this function.
lowEnd = lowEnd||0;
highEnd = highEnd||0;
var arr = [],
c = highEnd - lowEnd + 1;
c=c>0?c:0;//lets not do this.
while ( c-- ) {
arr[c] = highEnd--;
}
return arr;
}
I tried fixing it by changing line 39 like this:
var wheelDelta = e.wheelDelta || -e.detail || (e.originalEvent != undefined && - e.originalEvent.detail) || -e.deltaY;
It actually works but I'm not sure if it's the right way.
Reported by Rafael Faria Schedit
Steps to reproduce:
Observed: Stack prefetch does not occur (check network window in chrome)
Expected: Stack prefetch should occur on Sag T1 window
When changing WW, WC or zooming in on the All Image Tools Example, the caption text is not changing.
It seems that onViewportUpdated
is not being called.
Reference:
See https://groups.google.com/forum/#!topic/cornerstone-platform/U1JRmgzeiLU
I tried the "zoom (pinch)" at
https://rawgit.com/chafey/cornerstoneTools/master/examples/alltouchtools/index.html
but it moves too fast and the library doesn't provide a way to tune the pinch sensitivity.
I would like to add a "Reset" button, to remove all the drawings and modifications made by the user to the image. I looked at the code and I have found "disable" and "deactivate" functions only, but they don't work. When I select again one of the tools used, the drawings appear again.
Is there a method I can use to reset everything?
Thanks!
See discussing here:
https://groups.google.com/forum/#!topic/cornerstone-platform/xfCE9A3Dkbo
When viewing https://rawgit.com/chafey/cornerstoneTools/master/examples/allImageTools/index.html I get:
Mixed Content: The page at 'https://rawgit.com/chafey/cornerstoneTools/master/examples/allImageTools/index.html' was loaded over HTTPS, but requested an insecure stylesheet 'http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css'. This request has been blocked; the content must be served over HTTPS.
which is caused by:
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
This can be fixed by changing the href
to: //netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css
For a given input image and a set of transforms and annotations applied, have some way of serializing out these transforms and annotations so that they can be re applied to the same image later.
Is it possible to let the user draw in the black spaces outside the image? I mean, if an image is taller then larger, there are two black spaces to the left and to the right of the image, and I would like the user to be able to draw (a rectangle, an ellipse etc.) there.
Is there any option to do it or can you point me in the right direction to change the code in order to reach the goal? Is it also possible to align the image to the left instead of centering it in the viewer?
Thanks!
Pinching to zoom does not seem to function on Windows 8.1 Surface 2 Pro using IE 11, Firefox 29.0 and Chrome 33.0.1750.154 m. Zoom actions appears to be intercepted by the browser first so the entire viewport zooms up. Very similar experience with the Mac desktop using the Apple Trackpad try to do the pinching motion. (I know I am asking for too much, but this is just for the record to build the future test cases.)
Window/Level only worked on Firefox 29. Also in the display, I could not easily close the window in FF 29. This may be due to the fact that I had the Touch mode on on the FF 29.
It would be nice to have cross mark (plus sign) displayed on the image while using crosshair tool. The cross should appear on mousedown and move to new position position on mousemove. The size of cross can be 1x1 cm independent of monitor resolution.
Hi again!
There is a typo error at line:
cornerstoneTools.touchmoveHandle(touchEventData, measurementData.handles.end, function() {
This causes an undef isn't a function, because the function name is touchMoveHandle().
By the way, the config.getTextCallback function seems undefined too (lines:
if (measurementData.annotationText === undefined) {
config.getTextCallback(doneChangingTextCallback);
}
)
But I don't know how to fix it
Thanks.
Already in the "backlog", but I'm creating this ticket to track feature.
Annotations such as:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.