package com.indago.iddea.controller.action; import net.imglib2.Cursor; import net.imglib2.IterableInterval; import net.imglib2.algorithm.labeling.AllConnectedComponents; import net.imglib2.img.array.ArrayImg; import net.imglib2.img.array.ArrayImgFactory; import net.imglib2.img.sparse.NtreeImgFactory; import net.imglib2.labeling.Labeling; import net.imglib2.labeling.LabelingType; import net.imglib2.labeling.NativeImgLabeling; import net.imglib2.type.NativeType; import net.imglib2.type.logic.BitType; import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.integer.IntType; import net.imglib2.view.IntervalView; import net.imglib2.view.Views; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.indago.iddea.view.display.JHotDrawInteractiveDisplay2D; import com.indago.iddea.view.overlay.ObjectInfo; import com.indago.iddea.view.overlay.ObjectInfoOverlay; import com.indago.iddea.view.overlay.ObjectInfoTransformOverlay; import com.indago.iddea.view.overlay.ObjectSetInfo; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.geom.Point2D; import java.util.*; import java.util.List; /** * Created by moon on 16/04/14. */ public class LabelObjectAction extends AbstractAction implements MouseMotionListener, ChangeListener { final JHotDrawInteractiveDisplay2D display; IntervalView intervalView; ObjectInfoTransformOverlay objectLabel = null; ObjectInfoOverlay objectInfo = null; LinkedHashMap<Point, ObjectInfo> objectMap = new LinkedHashMap<Point, ObjectInfo>(); LinkedHashMap<Point, Integer> junctionPoint = new LinkedHashMap<Point, Integer>(); LinkedHashMap<Integer, ObjectSetInfo> junctionMap = new LinkedHashMap<Integer, ObjectSetInfo>(); ArrayList<ObjectSetInfo> objSetLists = null; ArrayList<ObjectInfo> objLists = null; public LabelObjectAction(JHotDrawInteractiveDisplay2D display, IntervalView view) { this.display = display; this.intervalView = view; objectLabel = new ObjectInfoTransformOverlay(); objectInfo = new ObjectInfoOverlay(); display.addOverlayRenderer(objectLabel); objectInfo.updateInfo("Detecting started.", new Date().toString()); display.addOverlayRenderer(objectInfo); display.addMouseMotionListener(this); } @Override public void actionPerformed(ActionEvent actionEvent) { detect(); } public void detect() { // Green channel picked-up (Endpoint) objLists = detectEndpoints(Views.hyperSlice(intervalView, 2, 1)); setEndpointVisible(true); // Red channel (Junction) objSetLists = detectJunctions(Views.hyperSlice(intervalView, 2, 2)); setJunctionVisible(true); } public < T extends RealType< T > & NativeType< T > & Comparable<T> > ArrayList<ObjectSetInfo> detectJunctions(IntervalView<T> v) { junctionPoint.clear(); junctionMap.clear(); long[] dimensions = new long[] { v.dimension(0), v.dimension(1) }; ArrayImgFactory<BitType> imgFactory = new ArrayImgFactory< BitType >(); ArrayImg< BitType, ? > image = imgFactory.create( dimensions, new BitType() ); Labeling< Integer > labeling = new NativeImgLabeling< Integer, IntType >( new NtreeImgFactory< IntType >().create( dimensions, new IntType() ) ); ArrayList<ObjectSetInfo> objLists = new ArrayList<ObjectSetInfo>(); IterableInterval< T > input = Views.iterable(v); Cursor< T > cursorInput = input.localizingCursor(); Cursor< BitType > c = image.localizingCursor(); T val; BitType b; net.imglib2.Point position = new net.imglib2.Point( v.numDimensions() ); while(cursorInput.hasNext()) { val = cursorInput.next(); b = c.next(); b.setZero(); if(val.getRealDouble() > 0) { position.setPosition(cursorInput); image.randomAccess().setPosition(cursorInput); b.setOne(); } } Iterator<Integer> names = AllConnectedComponents.getIntegerNames( 0 ); long[][] structuringElement = new long[][] { {-1, -1}, {-1, 0}, {-1, 1}, {1, 0}, {1, -1}, {0, -1}, {0, 1}, {1, 1}}; AllConnectedComponents.labelAllConnectedComponents( labeling, image, names, structuringElement ); Cursor<LabelingType< Integer >> lc = labeling.localizingCursor(); HashMap< Integer, HashSet<Point> > map = new HashMap< Integer, HashSet<Point> >(); int[] pos = new int[ 2 ]; while ( lc.hasNext() ) { LabelingType<Integer> lt = lc.next(); lc.localize( pos ); List< Integer > labels = lt.getLabeling(); if(labels.size() > 0) { final Integer value = labels.get(0); if(!map.containsKey(value)) { HashSet<Point> hashMap = new HashSet<Point>(); map.put(value, hashMap); ObjectSetInfo info = new ObjectSetInfo( hashMap, "Junction-" + value, ""); objLists.add(info); junctionMap.put(value, info); } Point pt = new Point(pos[0], pos[1]); map.get(value).add(pt); junctionPoint.put(pt, value); } } Iterator<Integer> iter = map.keySet().iterator(); while(iter.hasNext()) { Integer i = iter.next(); //System.out.println("" + i + ":" + map.get(i).size()); } return objLists; } public < T extends RealType< T > & NativeType< T >> ArrayList<ObjectInfo> detectEndpoints(IntervalView<T> v) { objectMap.clear(); ArrayList<ObjectInfo> objLists = new ArrayList<ObjectInfo>(); IterableInterval< T > input = Views.iterable(v); net.imglib2.Cursor< T > cursorInput = input.localizingCursor(); T val; int i = 0; while(cursorInput.hasNext()) { val = cursorInput.next(); if(val.getRealDouble() > 0) { net.imglib2.Point position = new net.imglib2.Point( v.numDimensions() ); position.setPosition(cursorInput); ObjectInfo info = new ObjectInfo( position.getIntPosition(0), position.getIntPosition(1), "Endpoint-" + i, ""); // System.out.print("" + position.getDoublePosition(0) + "," + position.getDoublePosition(1)); // System.out.println(val.getRealDouble()); objLists.add(info); objectMap.put(new Point(position.getIntPosition(0), position.getIntPosition(1)), info); i++; } } return objLists; } @Override public void mouseDragged(MouseEvent mouseEvent) { } @Override public void mouseMoved(MouseEvent mouseEvent) { Point2D.Double p = display.viewToDrawing(mouseEvent.getPoint()); int x = (int)Math.round(p.getX()); int y = (int)Math.round(p.getY()); objectLabel.updateXY(x, y); Point pt = new Point(x, y); if(objectMap.containsKey(pt)) { ObjectInfo info = objectMap.get(pt); objectInfo.updateInfo(info.Label, "" + x + ", " + y); } else if(junctionPoint.containsKey(pt)) { ObjectSetInfo info = junctionMap.get(junctionPoint.get(pt)); objectInfo.updateInfo(info.Label, "" + x + ", " + y); } else objectInfo.updateInfo("Mouse ", "" + x + ", " + y); display.repaint(); } public void setJunctionVisible(boolean b) { if(b) objectLabel.setObjectSetList(objSetLists); else objectLabel.setObjectSetList(null); display.repaint(); } public void setEndpointVisible(boolean b) { if(b) objectLabel.setObjectList(objLists); else objectLabel.setObjectList(null); display.repaint(); } public void updateIntervalView(IntervalView v) { this.intervalView = v; detect(); } @Override public void stateChanged(ChangeEvent changeEvent) { if(changeEvent.getSource() instanceof JCheckBox) { JCheckBox cb = (JCheckBox) changeEvent.getSource(); if (cb.getName().equals("Endpoints")) { setEndpointVisible(cb.isSelected()); } else if (cb.getName().equals("Junctions")) { setJunctionVisible(cb.isSelected()); } } } }