Direction indicator

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Direction indicator

Michael Doube
Dear all,

I'm thinking about implementing a direction indicator to show the
orientation of the body that the image is from.  I mainly work with
anatomy, so the anatomical directions (medial, lateral, dorsal, ventral
etc.) are most interesting, but there's nothing stopping it from showing
compass directions (north, south, east, west) or anything else.

One way around this might be to rotate the image, but this would mean
interpolating pixels, which is bad.

My ideal would be to have a cross with text labels at the ends, that you
can move by grabbing the centre or rotate by grabbing the ends.  You
could also change the labels with a right click or a menu item
somewhere.  A bit like the zoom indicator but interactive.  It would
also have to exist without interference from ROIs or fiddling about with
the ROI Manager.

I had a go at doing this with Line and TextRoi, and the Overlay class
but only succeeded at showing the lines and text boxes; I couldn't grab
the handles and it behaves like an ROI by disappearing...

Any hints at how to achieve this better would be appreciated,

Michael

Abortive attempt follows...
---------------------------
package org.doube.geometry;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

import ij.ImagePlus;
import ij.gui.Line;
import ij.gui.Overlay;
import ij.gui.Roi;
import ij.gui.TextRoi;

/**
  * Indicator to show anatomic directions such as medial, proximal, cranial
  *
  * Instantiate 2 line ROI's, lock their lengths, lock their midpoint to
always
  * be the same position.
  *
  * @author Michael Doube
  *
  */
@SuppressWarnings("serial")
public class AnatomicAxes {

        private static final String[][] axisLabels = { { "medial", "lateral" },
                        { "cranial", "caudal" }, { "rostral", "caudal" },
                        { "dorsal", "ventral" }, { "anterior", "posterior" },
                        { "superior", "inferior" }, { "proximal", "distal" },
                        { "dorsal", "palmar" }, { "dorsal", "plantar" },
                        { "dorsal", "volar" }, { "axial", "abaxial" } };

        /** Common midpoint */
        private int x, y;

        /** Axis length */
        private int length;
        private ImagePlus imp;
        private Line line1, line2;

        /** TextRoi labels for axes */
        private TextRoi tr1, tr2, tr3, tr4;

        private Graphics g;
        private Overlay overlay;

        public AnatomicAxes(ImagePlus imp) {
                this.imp = imp;
                int w = imp.getWidth();
                int h = imp.getHeight();
                this.length = Math.min(w, h) / 4;
                this.x = w / 2;
                this.y = h / 2;
                this.line1 = new Line(x, y - length, x, y + length);
                this.line2 = new Line(x - length, y, x + length, y);
                TextRoi.setFont("SansSerif", 10, Font.PLAIN, true);
                this.tr1 = new TextRoi(x, y - length - 10, axisLabels[0][0]);
                this.tr2 = new TextRoi(x, y + length + 10, axisLabels[0][1]);
                this.tr3 = new TextRoi(x - length - 10, y, axisLabels[1][0]);
                this.tr4 = new TextRoi(x + length + 10, y, axisLabels[1][1]);
                this.overlay = new Overlay();
                overlay.add(line1);
                overlay.add(line2);
                overlay.add(tr1);
                overlay.add(tr2);
                overlay.add(tr3);
                overlay.add(tr4);
                for (Roi r : overlay.toArray()){
                        r.setImage(this.imp);
                }
                overlay.setStrokeColor(new Color(0, 0, 255));
                this.imp.setOverlay(overlay);
                this.g = this.imp.getCanvas().getGraphics();
                create();
        }

        public void create() {
                for (Roi r : overlay.toArray())
                        r.draw(this.g);
        }

        public void reflect() {
                // TODO method stub
                // get whichever line is selected
                // swap the labels
        }

}
Reply | Threaded
Open this post in threaded view
|

Re: Direction indicator

Rasband, Wayne (NIH/NIMH) [E]
On Sep 14, 2010, at 4:50 PM, Michael Doube wrote:

> Dear all,
>
> I'm thinking about implementing a direction indicator to show the
> orientation of the body that the image is from.  I mainly work with
> anatomy, so the anatomical directions (medial, lateral, dorsal, ventral
> etc.) are most interesting, but there's nothing stopping it from showing
> compass directions (north, south, east, west) or anything else.
>
> One way around this might be to rotate the image, but this would mean
> interpolating pixels, which is bad.
>
> My ideal would be to have a cross with text labels at the ends, that you
> can move by grabbing the centre or rotate by grabbing the ends.  You
> could also change the labels with a right click or a menu item
> somewhere.  A bit like the zoom indicator but interactive.  It would
> also have to exist without interference from ROIs or fiddling about with
> the ROI Manager.
>
> I had a go at doing this with Line and TextRoi, and the Overlay class
> but only succeeded at showing the lines and text boxes; I couldn't grab
> the handles and it behaves like an ROI by disappearing...
>
> Any hints at how to achieve this better would be appreciated,

Take a look at the internal Orthogonal_Views plugin (Image>Stacks>Orthogonal Views). The source code is at

      http://imagej.nih.gov/ij/source/ij/plugin/Orthogonal_Views.java

It use overlays and the ImageCanvas.setCustomRoi() method to create custom cross-shaped selections on XY, YZ and XZ views.

-wayne


> Abortive attempt follows...
> ---------------------------
> package org.doube.geometry;
>
> import java.awt.Color;
> import java.awt.Font;
> import java.awt.Graphics;
>
> import ij.ImagePlus;
> import ij.gui.Line;
> import ij.gui.Overlay;
> import ij.gui.Roi;
> import ij.gui.TextRoi;
>
> /**
>  * Indicator to show anatomic directions such as medial, proximal, cranial
>  *
>  * Instantiate 2 line ROI's, lock their lengths, lock their midpoint to
> always
>  * be the same position.
>  *
>  * @author Michael Doube
>  *
>  */
> @SuppressWarnings("serial")
> public class AnatomicAxes {
>
> private static final String[][] axisLabels = { { "medial", "lateral" },
> { "cranial", "caudal" }, { "rostral", "caudal" },
> { "dorsal", "ventral" }, { "anterior", "posterior" },
> { "superior", "inferior" }, { "proximal", "distal" },
> { "dorsal", "palmar" }, { "dorsal", "plantar" },
> { "dorsal", "volar" }, { "axial", "abaxial" } };
>
> /** Common midpoint */
> private int x, y;
>
> /** Axis length */
> private int length;
> private ImagePlus imp;
> private Line line1, line2;
>
> /** TextRoi labels for axes */
> private TextRoi tr1, tr2, tr3, tr4;
>
> private Graphics g;
> private Overlay overlay;
>
> public AnatomicAxes(ImagePlus imp) {
> this.imp = imp;
> int w = imp.getWidth();
> int h = imp.getHeight();
> this.length = Math.min(w, h) / 4;
> this.x = w / 2;
> this.y = h / 2;
> this.line1 = new Line(x, y - length, x, y + length);
> this.line2 = new Line(x - length, y, x + length, y);
> TextRoi.setFont("SansSerif", 10, Font.PLAIN, true);
> this.tr1 = new TextRoi(x, y - length - 10, axisLabels[0][0]);
> this.tr2 = new TextRoi(x, y + length + 10, axisLabels[0][1]);
> this.tr3 = new TextRoi(x - length - 10, y, axisLabels[1][0]);
> this.tr4 = new TextRoi(x + length + 10, y, axisLabels[1][1]);
> this.overlay = new Overlay();
> overlay.add(line1);
> overlay.add(line2);
> overlay.add(tr1);
> overlay.add(tr2);
> overlay.add(tr3);
> overlay.add(tr4);
> for (Roi r : overlay.toArray()){
> r.setImage(this.imp);
> }
> overlay.setStrokeColor(new Color(0, 0, 255));
> this.imp.setOverlay(overlay);
> this.g = this.imp.getCanvas().getGraphics();
> create();
> }
>
> public void create() {
> for (Roi r : overlay.toArray())
> r.draw(this.g);
> }
>
> public void reflect() {
> // TODO method stub
> // get whichever line is selected
> // swap the labels
> }
>
> }
Reply | Threaded
Open this post in threaded view
|

Re: Direction indicator

Michael Doube
>> I'm thinking about implementing a direction indicator to show the
>> orientation of the body that the image is from.
>> Any hints at how to achieve this better would be appreciated,
>
> Take a look at the internal Orthogonal_Views plugin (Image>Stacks>Orthogonal Views). The source code is at
>
>        http://imagej.nih.gov/ij/source/ij/plugin/Orthogonal_Views.java
>
> It use overlays and the ImageCanvas.setCustomRoi() method to create custom cross-shaped selections on XY, YZ and XZ views.
>
> -wayne

I had a go at this today using Orthogonal_Views and ContrastAdjuster and
have a PlugInFrame that rotates blue crosshairs with a slider.

http://github.com/mdoube/BoneJ/blob/directionOverlay/src/org/doube/geometry/AnatomicAxes.java

Text disappears after rotating though, so my labels don't work, and I
can't add an ordinary ROI to the image (which is also annoying in
Orthogonal_Views).  So it would be better if the direction indicator was
independent of the ROI stuff, like the zoomIndicator.

Michael
Reply | Threaded
Open this post in threaded view
|

Re: Direction indicator

Michael Doube
On 15/09/10 17:56, Michael Doube wrote:
>>> I'm thinking about implementing a direction indicator to show the
>>> orientation of the body that the image is from.

As a follow-up I now have a working plugin that does this in a nice way.
  It's still in development, but if anyone is interested to look at the
code, it is here:

http://github.com/mdoube/BoneJ/raw/directionOverlay/src/org/doube/geometry/Orienteer.java

It should "compile and run" on any ImageJ installation after deleting
the package declaration in the first line.

Michael