All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.actelion.research.orbit.imageAnalysis.components.RecognitionFrame Maven / Gradle / Ivy

Go to download

Orbit, a versatile image analysis software for biological image-based quantification

There is a newer version: 3.15
Show newest version
/*
 *     Orbit, a versatile image analysis software for biological image-based quantification.
 *     Copyright (C) 2009 - 2018 Idorsia Pharmaceuticals Ltd., Hegenheimermattweg 91, CH-4123 Allschwil, Switzerland.
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see .
 *
 */

package com.actelion.research.orbit.imageAnalysis.components;

import com.actelion.research.orbit.beans.RawAnnotation;
import com.actelion.research.orbit.beans.RawDataFile;
import com.actelion.research.orbit.dal.IOrbitImage;
import com.actelion.research.orbit.exceptions.OrbitImageServletException;
import com.actelion.research.orbit.imageAnalysis.dal.DALConfig;
import com.actelion.research.orbit.imageAnalysis.models.*;
import com.actelion.research.orbit.imageAnalysis.tasks.ClassificationTaskTiled;
import com.actelion.research.orbit.imageAnalysis.utils.*;
import com.actelion.research.orbit.utils.RawUtilsCommon;
import com.sun.media.jai.codec.JPEGEncodeParam;
import com.sun.media.jai.codec.TIFFEncodeParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.media.jai.JAI;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.MouseListener;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.*;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Represents an image plus results (e.g. classification map, segmented shapes).
 * Component which holds a planarImage (bimg), a classification image (classImage) and additional shapes (e.g. segmentation objects).
 * The paint() method renders the image with all markup.
 * 

* Attention: This class still holds a ClassShape list, even if the classShapes are stored in the model. So far this * is necessary because the drawn class regions (connected to a shapePaintListener) are stored here. This causes problems * e.g. in the NucleiSegmentationWorker which needs the classShapes of the (nested) segmentation model, so it first sets the * classShapes of the recognitionFrame to the segmentation model classShapes and later sets it back. * This should be refactored!!! *

*/ public class RecognitionFrame extends JComponent implements PropertyChangeListener { private static final long serialVersionUID = 1L; public static int maxClassShapesToPaint = 10000; private static final Logger logger = LoggerFactory.getLogger(RecognitionFrame.class); private int windowSize = 4; private double targetRadius = 3.0d; // just for drawing private double segmentationClassSize = 12.0d; private int boundaryClass = -1; private boolean contextClassificationEnabled = false; private TiledImageWriter classImage = null; @Deprecated private RecognitionFrame negativeChannel = null; private String picName = ""; private String originalName = ""; private final List classShapes = Collections.synchronizedList(new ArrayList()); private final List annotations = Collections.synchronizedList(new ArrayList()); private IScaleableShape ROI = null; private final HashMap colorClassLookup = new HashMap(); private float opacity = 0f; private boolean drawMarkup = true; private double[] ratio = null; // has to be initialized to classShapeList.size private final List classList = new ArrayList(); private final ReentrantReadWriteLock classListLock = new ReentrantReadWriteLock(); private List objectSegmentationList = null; private List secondaryObjectSegmentationList = null; private List objectSegmentationColors = null; // used for heatmap private int[] objectClassificationList = null; private List centerList = null; private List centroidList = null; @Deprecated private Arc2D.Double classBounds = null; private static final Color[] colors = new Color[]{Color.red, Color.blue, Color.green, Color.yellow, Color.cyan, Color.orange, Color.magenta, Color.pink, Color.lightGray}; private static Random rand = new Random(); private static Font toolTipFont = new Font("Arial", Font.PLAIN, 12); //private boolean fromResource = false; private double scale = 100d; private double oldScale = 100d; private double muMeterPerPixel = 0d; private Color gaugeColor = Color.black; private Point2D viewPortOffset = new Point2D.Double(0, 0); private Dimension2D viewPortSize = new Dimension2D_Double(0d, 0d); public enum Tools {magneticLasso, brush, rectangle, cell, circle, delete, finger, roi, moveAnnotation, rotateAnnotation} ; private Tools selectedTool = Tools.finger; private ShapePainterListener myListener = null; @Deprecated public List pathList = new ArrayList(); private String toolTip = null; private Point toolTipPosition = null; private double toolTipCurrentScale = 100d; private boolean showObjectToolTip = false; private MixtureStatistics mixStats = null; public TiledImagePainter bimg = new TiledImagePainter(); private List> taskList = null; private Hashtable threadProgress = null; private long startTime = 0L; private FeatureDescription featureDescription = new FeatureDescription(); // with default values private float classImageScale = 1.0f; // additional scaleFactor, e.g. if classification has been done on MIP image. private transient RenderThread _renderThread = null; private static final Color annotationBackgroundColor = new Color(1f, 1f, 1f, 0.6f); private boolean displayAnnotationLabels = true; // private ExclusionMapGen exMapGen = null; private double mipScale = 1d; private static final boolean ignoreRepaint = true; private static final boolean opaque = false; private static final boolean doubleBuffered = false; private static final AtomicInteger activeAnnotationGroup = new AtomicInteger(0); // annotation group -> see annotationPanel private BufferedImage screenImage = null; private BufferedImage lastImage = null; // private Image smallImage = null; private ScreenProps screenProps = null; private AtomicBoolean forceRepaint = new AtomicBoolean(true); private AtomicBoolean drawing = new AtomicBoolean(false); /** * @param picObj can ob url or orbitId * @throws OrbitImageServletException */ public RecognitionFrame(Object picObj) throws OrbitImageServletException { this(picObj, false); } public RecognitionFrame(Object picName, boolean fromResource) throws OrbitImageServletException { this.setOpaque(opaque); this.setIgnoreRepaint(ignoreRepaint); this.setDoubleBuffered(doubleBuffered); //this.fromResource = fromResource; classShapes.clear(); classShapes.addAll(OrbitUtils.buildDefaultClassShapes()); ratio = new double[classShapes.size()]; if (picName != null) loadImage(picName, fromResource); setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); myListener = new ShapePainterListener(this.getClassShapes().get(0).getShapeList(), this.getClassShapes().get(0).getName(), this); // at least one class has to exist! this.addMouseListener(myListener); this.addMouseMotionListener(myListener); this.addMouseWheelListener(myListener); } public RecognitionFrame(Object picName, boolean fromResource, List classShapes, FeatureDescription featureDescription) { this.setOpaque(opaque); this.setIgnoreRepaint(ignoreRepaint); this.setDoubleBuffered(doubleBuffered); //this.fromResource = fromResource; this.classShapes.clear(); this.classShapes.addAll(classShapes); this.featureDescription = featureDescription; this.windowSize = featureDescription.getWindowSize(); ratio = new double[classShapes.size()]; if (picName != null) try { loadImage(picName, fromResource); } catch (OrbitImageServletException e) { e.printStackTrace(); } setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); myListener = new ShapePainterListener(this.getClassShapes().get(0).getShapeList(), this.getClassShapes().get(0).getName(), this); // at least one class has to exist! addMouseListeners(); } /** * Creates a recognitionframe based on a MIP image of a parent recognition frame.
* Sets classShapes (copy), featureDescription, ratio and picName according to the parent.
* MouseListeners (ShapePainterListener) will be set if addMouseListeners is true.
* No check if requested MIP exists will be performed! * * @param parent * @param mipNum */ public RecognitionFrame(RecognitionFrame parent, int mipNum, boolean addMouseListeners) { this.setOpaque(opaque); this.setIgnoreRepaint(ignoreRepaint); this.setDoubleBuffered(doubleBuffered); this.classShapes.clear(); this.classShapes.addAll(OrbitUtils.cloneClassShapes(parent.getClassShapes())); this.featureDescription = parent.getFeatureDescription(); this.windowSize = parent.getWindowSize(); this.ratio = parent.getRatio(); this.picName = parent.getPicName(); this.bimg = parent.bimg.getMipMaps()[mipNum]; this.muMeterPerPixel = parent.getMuMeterPerPixel() * (parent.bimg.getWidth() / (double) this.bimg.getWidth()); this.setGaugeColor(parent.getGaugeColor()); if (parent != null) { this.mipScale = (double) this.bimg.getWidth() / (double) parent.bimg.getWidth(); // copy scaled roi if (parent.getROI() != null) { IScaleableShape roiScaled = (IScaleableShape) parent.getROI().getScaledInstance(((mipScale) * 100d), new Point(0, 0)); roiScaled = roiScaled.clone(); roiScaled.setScale(100d); this.setROI(roiScaled); } } setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); if (addMouseListeners) { myListener = new ShapePainterListener(this.getClassShapes().get(0).getShapeList(), this.getClassShapes().get(0).getName(), this); // at least one class has to exist! this.addMouseListener(myListener); this.addMouseMotionListener(myListener); try { this.addMouseWheelListener(myListener); } catch (Exception e) { } } } public RecognitionFrame(TiledImagePainter tip) { this.setOpaque(opaque); this.setIgnoreRepaint(ignoreRepaint); this.setDoubleBuffered(doubleBuffered); this.classShapes.clear(); this.classShapes.addAll(OrbitUtils.buildDefaultClassShapes()); ratio = new double[classShapes.size()]; setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); if (tip != null) { bimg = tip; } } public RecognitionFrame(IOrbitImage orbitImage, String imageName) throws Exception { this.setOpaque(opaque); this.setIgnoreRepaint(ignoreRepaint); this.setDoubleBuffered(doubleBuffered); this.classShapes.clear(); this.classShapes.addAll(OrbitUtils.buildDefaultClassShapes()); ratio = new double[classShapes.size()]; setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); OrbitTiledImageIOrbitImage img = new OrbitTiledImageIOrbitImage(orbitImage); TiledImagePainter tip = new TiledImagePainter(img,imageName); if (tip != null) { bimg = tip; } } public RecognitionFrame(RecognitionFrame parent, RawDataFile rdf, int level) { this.setOpaque(opaque); this.setIgnoreRepaint(ignoreRepaint); this.setDoubleBuffered(doubleBuffered); this.classShapes.clear(); if (parent != null) { this.classShapes.addAll(OrbitUtils.cloneClassShapes(parent.getClassShapes())); this.featureDescription = parent.getFeatureDescription(); this.windowSize = parent.getWindowSize(); this.ratio = parent.getRatio(); } else { classShapes.clear(); classShapes.addAll(OrbitUtils.buildDefaultClassShapes()); ratio = new double[classShapes.size()]; } this.picName = rdf.getFileName() + " [" + level + "]"; try { TiledImagePainter tip = new TiledImagePainter(); tip.loadImageSpecial(rdf, level); if (tip == null) { logger.error("Special image not available"); } if (true) { myListener = new ShapePainterListener(this.getClassShapes().get(0).getShapeList(), this.getClassShapes().get(0).getName(), this); // at least one class has to exist! this.addMouseListener(myListener); this.addMouseMotionListener(myListener); try { this.addMouseWheelListener(myListener); } catch (Exception e) { } } this.bimg = tip; if (parent != null) this.mipScale = (double) this.bimg.getWidth() / (double) parent.bimg.getWidth(); logger.trace("loading level {} image with width {}", level, this.bimg.getWidth()); if (parent != null) { this.muMeterPerPixel = parent.getMuMeterPerPixel() * (parent.bimg.getWidth() / (double) this.bimg.getWidth()); this.setGaugeColor(parent.getGaugeColor()); // copy scaled roi if (parent.getROI() != null) { IScaleableShape roiScaled = (IScaleableShape) parent.getROI().getScaledInstance(((mipScale) * 100d), new Point(0, 0)); roiScaled = roiScaled.clone(); roiScaled.setScale(100d); this.setROI(roiScaled); } this.bimg.getImage().setAnalysisHues(parent.bimg.getImage().getAnalysisHues()); this.bimg.getImage().setChannelContributionsClassification(parent.bimg.getImage().getChannelContributionsClassification()); if (parent.getObjectSegmentationList() != null) { // copy parent segmentations (important for object classification) double originalCurrentFrameRatioInverse = parent.bimg.getImage().getWidth() / (double) this.bimg.getImage().getWidth(); if (this.getObjectSegmentationList() == null) this.setObjectSegmentationList(new ArrayList(parent.getObjectSegmentationList().size())); this.getObjectSegmentationList().clear(); for (Shape shape : parent.getObjectSegmentationList()) { this.getObjectSegmentationList().add(((IScaleableShape) shape).getScaledInstance(originalCurrentFrameRatioInverse * 100d, new Point(0, 0))); } } } } catch (Exception e) { logger.error("error loading special image", e); } } public RecognitionFrame(RecognitionFrame parent, RawDataFile rdf, double scaleFactor) { this.setOpaque(opaque); this.setIgnoreRepaint(ignoreRepaint); this.setDoubleBuffered(doubleBuffered); this.classShapes.clear(); if (parent != null) { this.classShapes.addAll(OrbitUtils.cloneClassShapes(parent.getClassShapes())); this.featureDescription = parent.getFeatureDescription(); this.windowSize = parent.getWindowSize(); this.ratio = parent.getRatio(); } else { classShapes.clear(); classShapes.addAll(OrbitUtils.buildDefaultClassShapes()); ratio = new double[classShapes.size()]; } this.picName = rdf.getFileName() + " [" + scaleFactor + "]"; try { TiledImagePainter tip = new TiledImagePainter(); tip.loadImageScaleFactor(rdf, scaleFactor, parent.bimg.getImage().getWidth()); if (tip == null) { logger.error("Special image not available"); } if (true) { myListener = new ShapePainterListener(this.getClassShapes().get(0).getShapeList(), this.getClassShapes().get(0).getName(), this); // at least one class has to exist! this.addMouseListener(myListener); this.addMouseMotionListener(myListener); try { this.addMouseWheelListener(myListener); } catch (Exception e) { } } this.bimg = tip; if (parent != null) this.mipScale = (double) this.bimg.getWidth() / (double) parent.bimg.getWidth(); logger.trace("loading targetWidth {} image by scaleFactor {}", scaleFactor, this.bimg.getWidth()); if (parent != null) { this.muMeterPerPixel = parent.getMuMeterPerPixel() * (parent.bimg.getWidth() / (double) this.bimg.getWidth()); this.setGaugeColor(parent.getGaugeColor()); // copy scaled roi if (parent.getROI() != null) { IScaleableShape roiScaled = (IScaleableShape) parent.getROI().getScaledInstance(((mipScale) * 100d), new Point(0, 0)); roiScaled = roiScaled.clone(); roiScaled.setScale(100d); this.setROI(roiScaled); } this.bimg.getImage().setAnalysisHues(parent.bimg.getImage().getAnalysisHues()); this.bimg.getImage().setChannelContributionsClassification(parent.bimg.getImage().getChannelContributionsClassification()); // System.out.println("channelContribs: "+Arrays.toString(this.bimg.getImage().getChannelContributionsClassification())); if (parent.getObjectSegmentationList() != null) { // copy parent segmentations (important for object classification) double originalCurrentFrameRatioInverse = parent.bimg.getImage().getWidth() / (double) this.bimg.getImage().getWidth(); if (this.getObjectSegmentationList() == null) this.setObjectSegmentationList(new ArrayList(parent.getObjectSegmentationList().size())); this.getObjectSegmentationList().clear(); for (Shape shape : parent.getObjectSegmentationList()) { this.getObjectSegmentationList().add(((IScaleableShape) shape).getScaledInstance(originalCurrentFrameRatioInverse * 100d, new Point(0, 0))); } } } } catch (Exception e) { logger.error("error loading special image", e); } } /** * clones the parent RecognitionFrame. The TiledImagePainter (bimg) will be referenced (not really cloned)!!! * * @param parent * @param addMouseListeners */ public RecognitionFrame(RecognitionFrame parent, boolean addMouseListeners) { this.setOpaque(opaque); this.setIgnoreRepaint(ignoreRepaint); this.setDoubleBuffered(doubleBuffered); this.classShapes.clear(); this.classShapes.addAll(OrbitUtils.cloneClassShapes(parent.getClassShapes())); this.featureDescription = parent.getFeatureDescription(); this.windowSize = parent.getWindowSize(); this.ratio = parent.getRatio(); this.picName = parent.getPicName(); this.bimg = parent.bimg; this.muMeterPerPixel = parent.muMeterPerPixel; this.gaugeColor = parent.getGaugeColor(); // copy scaled roi if (parent.getROI() != null) { IScaleableShape roiScaled = (IScaleableShape) parent.getROI().getScaledInstance((((double) this.bimg.getWidth() / parent.bimg.getWidth()) * 100d), new Point(0, 0)); roiScaled = roiScaled.clone(); roiScaled.setScale(100d); this.setROI(roiScaled); } setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); if (addMouseListeners) { myListener = new ShapePainterListener(this.getClassShapes().get(0).getShapeList(), this.getClassShapes().get(0).getName(), this); // at least one class has to exist! this.addMouseListener(myListener); this.addMouseMotionListener(myListener); try { this.addMouseWheelListener(myListener); } catch (Exception e) { } } } /** * Constructs and sets a TiledImageWriter-based new classification image. */ public void constructClassificationImage() { setClassImage(new TiledImageWriter(bimg.getWidth(), bimg.getHeight(), bimg.getTileWidth(), bimg.getTileHeight())); } public Point[] getTiles() { return bimg.getImage().getTileIndices(null); } public Point[] getTiles(Rectangle rectangle) { return bimg.getImage().getTileIndices(rectangle); } public WritableRaster getWritableClassificationTile(int tileX, int tileY) { return classImage.getImage().getWritableTile(tileX, tileY); } public void releaseWritableClassificationTile(int tileX, int tileY) { classImage.getImage().releaseWritableTile(tileX, tileY); } public Raster getTile(int tileX, int tileY) { return bimg.getImage().getTile(tileX, tileY); } /** * singleton factory for renderThread * * @return */ private synchronized RenderThread getRenderThread() { if (_renderThread == null) { _renderThread = new RenderThread(this); _renderThread.setName("renderThread"); _renderThread.addPropertyChangeListener(this); _renderThread.start(); } return _renderThread; } /** * returns the renderthread without instantiation.
* This might return null if the private getRenderThread (singleton) has never been called (for small images). * * @return */ public RenderThread getRenderThreadOriginal() { return _renderThread; } public void addMouseListeners() { try { addMouseListener(myListener); addMouseMotionListener(myListener); addMouseWheelListener(myListener); // >= Java 1.6 } catch (Exception ex) { } } public void removeMouseListeners() { try { removeMouseListener(myListener); removeMouseMotionListener(myListener); removeMouseWheelListener(myListener); // >= Java 1.6 } catch (Exception ex) { } } /** * Obsolete since version 1.90i (no setPreferredSize done anymore) */ @Deprecated public void scaleImage(double percentage) { scale = percentage; double scaleFactor = scale / 100d; double sizeX = bimg.getWidth() * scaleFactor; double sizeY = bimg.getHeight() * scaleFactor; this.setPreferredSize(new Dimension((int) sizeX, (int) sizeY)); } public void loadImage(Object picNameOrUrl, boolean fromResource) throws OrbitImageServletException { loadImage(picNameOrUrl, fromResource, 0, 0, true); } public void loadImage(Object picNameOrUrl, boolean fromResource, int width, int height, boolean scaleIs100) throws OrbitImageServletException { if (picNameOrUrl == null) return; //this.fromResource= fromResource; if (picNameOrUrl instanceof RawDataFile) { this.picName = ((RawDataFile) picNameOrUrl).getFileName(); this.originalName = ((RawDataFile) picNameOrUrl).getRawDataFileId() + ""; } else { this.picName = picNameOrUrl.toString(); this.originalName = picNameOrUrl.toString(); if (picNameOrUrl instanceof String) { String[] splitStr = picNameOrUrl.toString().split("\\\\"); if (splitStr != null && splitStr.length > 0) this.picName = splitStr[splitStr.length - 1]; // just the filename without the path before } } try { if (fromResource) picNameOrUrl = this.getClass().getResource(picName); if (picNameOrUrl == null) picNameOrUrl = picName; // first load might be also a string bimg.loadImage(picNameOrUrl); //System.out.println("image: "+bimg.image); //System.gc(); } catch (Exception e) { logger.error("Error loading image. Probably the Orbit image server down or not accessible.\nError Details: ", e); if (e instanceof OrbitImageServletException) { throw new OrbitImageServletException(e.getMessage()); } } this.setPreferredSize(new Dimension(bimg.getWidth(), bimg.getHeight())); } public void paintComponent(Graphics g) { if (bimg == null) return; ScreenProps currentScreenprops = new ScreenProps(viewPortOffset.getX(),viewPortOffset.getY(),viewPortSize.getWidth(),viewPortSize.getHeight(),scale,opacity); if (screenImage==null || g.getClipBounds().width!=screenImage.getWidth() || g.getClipBounds().height!=screenImage.getHeight()) { GraphicsConfiguration gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); screenImage = gconf.createCompatibleImage(g.getClipBounds().width, g.getClipBounds().height); forceRepaint.set(true); } //Graphics2D g2d = (Graphics2D) g; Graphics2D g2d = screenImage.createGraphics(); try { // "viewPort" //System.out.println("vpSize: "+viewPortSize+" vpOffs: "+viewPortOffset+" image: "+bimg.image); // GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(height, width, Transparency.OPAQUE); if (viewPortSize.getWidth() <= 0 || viewPortSize.getHeight() <= 0) return; if (forceRepaint.get() || screenProps==null || !currentScreenprops.equals(screenProps)) { g2d.setColor(this.getBackground()); g2d.fillRect(0, 0, screenImage.getWidth(), screenImage.getHeight()); } g2d.translate(-viewPortOffset.getX(), -viewPortOffset.getY()); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED); //g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); AffineTransform oldTransform = g2d.getTransform(); double sc = getScale() / 100d; double cx = getParent().getBounds().getCenterX(); double cy = getParent().getBounds().getCenterY(); double vpWidth = viewPortSize.getWidth(); double vpHeight = viewPortSize.getHeight(); if (!drawing.get()) { drawing.set(true); if (forceRepaint.get() || screenProps == null || !currentScreenprops.equals(screenProps)) { // forceRepaint.set(false); // too many problems => disabled if (bimg.hasMipMaps()) { // for TiledImagePainter rendering scale before drawing the image, for rendering from buffer scale after drawing the image // if (smallImage==null) { // smallImage = bimg.getMipMaps()[bimg.getMipMaps().length-1].getImage().getAsBufferedImage(); // VolatileImage vi = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleVolatileImage(smallImage.getWidth(this), smallImage.getHeight(this)); // smallImage = vi; // //System.out.println("small image: "+smallImage); // } if (!getRenderThread().isBufferReady()) { g2d.scale(sc, sc); if (scale >= 100) bimg.drawImage(g2d, viewPortOffset.getX(), viewPortOffset.getY(), vpWidth, vpHeight, getScale(), 0); // bimg.getMipMaps().length - 1 was: 0 //else if (scale>30) bimg.drawImage(g2d, viewPortOffset.getX(),viewPortOffset.getY(),vpWidth,vpHeight,getScale(),bimg.getMipMaps().length-2); else bimg.drawImage(g2d, viewPortOffset.getX(), viewPortOffset.getY(), vpWidth, vpHeight, getScale(), bimg.getMipMaps().length - 1); } else { Image image = getRenderThread().getImageBuffer(); int vpX = (int) viewPortOffset.getX(); int vpY = (int) viewPortOffset.getY(); g2d.drawImage(image, vpX, vpY, this); g2d.scale(sc, sc); } } else // no mipMaps, so normal rendering { g2d.scale(sc, sc); bimg.drawImage(g2d, viewPortOffset.getX(), viewPortOffset.getY(), vpWidth, vpHeight, getScale(), -1); } } drawing.set(false); } screenProps = currentScreenprops; // g2d.scale(sc, sc); // bimg.drawImage(g2d, viewPortOffset.x,viewPortOffset.y,vpWidth,vpHeight,getScale(),-1); // pathList if (pathList != null) { g2d.setColor(Color.red); //pathList.drawPolygon(g2d); for (Point p : pathList) { g2d.fillRect(p.x, p.y, 1, 1); } } if ((toolTip != null) && (toolTipPosition != null)) { Color oldFront = g2d.getColor(); g2d.setColor(Color.yellow); g2d.setFont(toolTipFont); g2d.drawString(toolTip, toolTipPosition.x, toolTipPosition.y); g2d.setColor(oldFront); } if (classBounds != null) { g2d.setColor(Color.black); g2d.drawArc((int) classBounds.x, (int) classBounds.y, (int) classBounds.width, (int) classBounds.height, 0, 360); } // TODO /* if ((exMapGen!=null && exMapGen.getRecognitionFrame()!=null && exMapGen.getRecognitionFrame().getClassImage()!=null) && (opacity>0)) { AffineTransform af = g2d.getTransform(); g2d.scale(classImageScale, classImageScale); Rectangle rbb = new Rectangle(viewPortOffset.x, viewPortOffset.y, vpWidth, vpHeight); if (ROI!=null) { Rectangle roiBB = ROI.getScaledInstance(getScale(), new Point((int)cx,(int)cy)).getBounds(); if (rbb.intersects(roiBB)) rbb = rbb.intersection(roiBB); } exMapGen.getRecognitionFrame().getClassImage().drawImage(g2d, rbb.x,rbb.y,rbb.width,rbb.height,getScale()*classImageScale,opacity); //classImage.drawImage(g2d, viewPortOffset.x,viewPortOffset.y,viewPortSize.width,viewPortSize.height,getScale()*classImageScale,opacity); g2d.setTransform(af); } */ TiledImageWriter.timeOut.set(System.currentTimeMillis()); if ((classImage != null) && (opacity > 0) && classImage.getPainting().get() == false) { AffineTransform af = g2d.getTransform(); g2d.scale(classImageScale, classImageScale); Rectangle rbb = new Rectangle((int) viewPortOffset.getX(), (int) viewPortOffset.getY(), (int) vpWidth, (int) vpHeight); if (ROI != null) { Rectangle roiBB = ROI.getScaledInstance(getScale(), new Point((int) cx, (int) cy)).getBounds(); if (roiBB != null /*&& rbb.intersects(roiBB)*/) { rbb = rbb.intersection(roiBB); } } Composite composite = g2d.getComposite(); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity)); classImage.drawImage(g2d, rbb.x, rbb.y, rbb.width, rbb.height, getScale() * classImageScale); // opacity //classImage.drawImage(g2d, viewPortOffset.x,viewPortOffset.y,viewPortSize.width,viewPortSize.height,getScale()*classImageScale,opacity); g2d.setComposite(composite); g2d.setTransform(af); } if (classImage != null) { if (drawMarkup) // draw found regions/objects { if (classList != null && classList.size() > 0) { g2d.setColor(Color.white); if (classListLock.readLock().tryLock()) { try { for (Polygon poly : classList) { Rectangle rec = poly.getBounds(); g2d.drawArc((int) rec.getCenterX() - (int) segmentationClassSize / 2, (int) rec.getCenterY() - (int) segmentationClassSize / 2, (int) segmentationClassSize, (int) segmentationClassSize, 0, 360); } } finally { classListLock.readLock().unlock(); } } } if (objectSegmentationList != null) { try { double scaleFactor = (getScale() / 100d); int segSize = objectSegmentationList.size(); for (int i = 0; i < segSize; i++) { Shape shape = objectSegmentationList.get(i); if (shape == null) continue; Point pos = null; // try { pos = new Point((int) (myListener.getMousePosition().x / scaleFactor), (int) (myListener.getMousePosition().y / scaleFactor)); // } catch (NullPointerException ex) { // } if ((objectClassificationList != null) && (objectClassificationList.length == objectSegmentationList.size()) && (objectClassificationList[i] >= 0)) { // draw classification of objects (e.g. cells) g2d.setColor(classShapes.get(objectClassificationList[i]).getColor()); if (shape instanceof Polygon) g2d.fillPolygon((Polygon) shape); } if (pos != null && shape.contains(pos)) g2d.setColor(Color.red); else { g2d.setColor(Color.yellow); if (objectSegmentationColors != null && objectSegmentationColors.size() == segSize) { g2d.setColor(objectSegmentationColors.get(i)); } } if (shape instanceof Polygon) { if (objectSegmentationColors != null && objectSegmentationColors.size() == segSize) g2d.fillPolygon((Polygon) shape); else drawPolygonLine((Polygon) shape, g2d); } } } catch (Exception e) { // might fail because objectSegmentationList is null -> better use a final synchronized list } } if (secondaryObjectSegmentationList != null) { try { double scaleFactor = (getScale() / 100d); int segSize = secondaryObjectSegmentationList.size(); for (int i = 0; i < segSize; i++) { Shape shape = secondaryObjectSegmentationList.get(i); if (shape == null) continue; Point pos = null; pos = new Point((int) (myListener.getMousePosition().x / scaleFactor), (int) (myListener.getMousePosition().y / scaleFactor)); if (pos != null && shape.contains(pos)) g2d.setColor(Color.red); else g2d.setColor(Color.green); if (shape instanceof Polygon) { drawPolygonLine((Polygon) shape, g2d); } } } catch (Exception e) { // might fail because objectSegmentationList is null -> better use a final synchronized list } } if (centerList != null) { for (Point center : centerList) { g2d.setColor(Color.red); g2d.drawRect(center.x - 1, center.y - 1, 3, 3); } } /* if (centroidList!=null) { for (Point centroid: centroidList) { g2d.setColor(Color.green); g2d.drawRect(centroid.x-1,centroid.y-1,3,3); } } */ } } g2d.setTransform(oldTransform); g2d.setColor(Color.white); // draw arc or fixed rectangle if in arc mode at mouse position MouseListener listener = myListener; if (listener instanceof ShapePainterListener) { // arc if (((ShapePainterListener) listener).getShapeMode() == ClassShape.SHAPETYPE_ARC && (!((ShapePainterListener) listener).isDeleteMode())) { Point mp = ((ShapePainterListener) listener).getMousePosition(); if (mp != null) { int r = (int) getTargetRadius(); Arc2D p = new Arc2D.Double(Arc2D.CHORD); p.setArcByCenter(mp.getX(), mp.getY(), r, 0d, 360d, Arc2D.CHORD); g2d.drawArc((int) p.getX(), (int) p.getY(), (int) p.getWidth(), (int) p.getHeight(), 0, 360); } } // fixed rectangle if (((ShapePainterListener) listener).getShapeMode() == ClassShape.SHAPETYPE_RECTANGLE && ((ShapePainterListener) listener).isFixedRectangle() == true && (!((ShapePainterListener) listener).isDeleteMode())) { Point mp = ((ShapePainterListener) listener).getMousePosition(); if (mp != null) { int r = (int) getTargetRadius(); double fixedRectangleRatio = ((ShapePainterListener) listener).getFixedRectangleRatio(); //int w = r/2; int w = (int) ((r / 2) * (getScale() / 100d)); int h = (int) ((double) w * fixedRectangleRatio); g2d.drawRect(mp.x - w, mp.y - h, w * 2, h * 2); } } } else logger.error("error: MouseListener is not a ShapePainterListener"); // toolTip if ((showObjectToolTip == true) && (toolTipPosition != null) && (mixStats != null) && (objectSegmentationList != null)) { String tip = null; double scaleFactor = (getScale() / 100d); Point pos = new Point((int) (toolTipPosition.x / scaleFactor), (int) (toolTipPosition.y / scaleFactor)); for (int i = 0; i < objectSegmentationList.size(); i++) { if (objectSegmentationList.get(i).contains(pos)) { tip = mixStats.getObjDescription(i); break; } } if (tip != null) { //Color oldFront = g2d.getColor(); g2d.setFont(toolTipFont); Rectangle2D r = toolTipFont.getStringBounds(tip, g2d.getFontRenderContext()); g2d.setColor(Color.white); g2d.fillRoundRect((int) r.getX() + toolTipPosition.x - 3, (int) r.getY() + toolTipPosition.y - 3, (int) r.getWidth() + 6, (int) r.getHeight() + 6, 12, 12); g2d.setColor(Color.black); g2d.drawString(tip, toolTipPosition.x, toolTipPosition.y); //g2d.setColor(oldFront); } } // draw ploygons Point currentOffs = new Point((int) cx, (int) cy); if (drawMarkup) { int csCnt = 0; synchronized (classShapes) { for (ClassShape classShape : classShapes) { csCnt++; if (csCnt > maxClassShapesToPaint) break; if (classShape.getShapeList() != null) { g2d.setColor(classShape.getColor()); for (Shape p : classShape.getShapeList()) { //AffineTransform af = AffineTransform.getScaleInstance(0.9d, 0.9d); //Path2D p2 = (Path2D)af.createTransformedShape(p); if (p instanceof PolygonExt) { drawPolygonLine(((PolygonExt) p).getScaledInstance(getScale(), currentOffs), g2d); } else if (p instanceof Arc2DExt) { if (p instanceof Arc2DExt) p = ((Arc2DExt) p).getScaledInstance(getScale(), currentOffs); g2d.drawArc((int) ((Arc2DExt) p).getX(), (int) ((Arc2DExt) p).getY(), (int) ((Arc2DExt) p).getWidth(), (int) ((Arc2DExt) p).getHeight(), 0, 360); } else if (p instanceof RectangleExt) { RectangleExt re = ((RectangleExt) p).getScaledInstance(getScale(), currentOffs); g2d.drawRect((int) re.getX(), (int) re.getY(), (int) re.getWidth(), (int) re.getHeight()); } } } } } // synchronized(classShapes) // draw Annotations Stroke oldStroke = g2d.getStroke(); g2d.setStroke(new BasicStroke(2)); synchronized (annotations) { OrbitModel model = null; if (annotations != null && annotations.size() > 0) { model = OrbitImageAnalysis.getInstance().getModel(); } for (ImageAnnotation annotation : annotations) { if (getActiveAnnotationGroup().get() > 0) { // filter annotations by group if (getActiveAnnotationGroup().get() != annotation.getGroup()) { continue; // skip displaying annotation (group not active) } } Point jitterOffs = (Point) currentOffs.clone(); ClassShape classShape = annotation.getShape(); if (classShape != null && classShape.getShapeList() != null) { double addscale = 1d; g2d.setColor(classShape.getColor()); if (annotation.isSelected()) { // highlight selected annotation g2d.setColor(Color.magenta); } if (annotation instanceof SpotAnnotation) { SpotAnnotation sa = (SpotAnnotation) annotation; if (sa.isSelected()) { g2d.setColor(Color.yellow); } else { // set class color if (sa.getClassNum() >= 0 && model != null && model.getClassShapes().size() > sa.getClassNum()) { g2d.setColor(model.getClassShapes().get(sa.getClassNum()).getColor()); } } } for (Shape p : classShape.getShapeList()) { if (p instanceof PolygonExt) { drawPolygonLine(((PolygonExt) p).getScaledInstance(getScale(), currentOffs), g2d); } else if (p instanceof Arc2DExt) { if (p instanceof Arc2DExt) p = ((Arc2DExt) p).getScaledInstance(getScale(), currentOffs); g2d.drawArc((int) ((Arc2DExt) p).getX(), (int) ((Arc2DExt) p).getY(), (int) ((Arc2DExt) p).getWidth(), (int) ((Arc2DExt) p).getHeight(), 0, 360); } else if (p instanceof RectangleExt) { RectangleExt re = ((RectangleExt) p).getScaledInstance(getScale(), currentOffs); g2d.drawRect((int) re.getX(), (int) re.getY(), (int) re.getWidth(), (int) re.getHeight()); } if (displayAnnotationLabels && (p instanceof PolygonExt) && (((PolygonExt) p).isClosed())) { Rectangle br = p.getBounds(); Point uppRight = getUppedRightPoint((PolygonExt) p); int ax = br.x + br.width; int ay = br.y; double scaleFactor = (getScale() / ((IScaleableShape) p).getScale()); ax = (int) (ax * scaleFactor); ay = (int) (ay * scaleFactor); int dx = (int) (uppRight.x * scaleFactor); int dy = (int) (uppRight.y * scaleFactor); g2d.setFont(toolTipFont); String text = annotation.getDescription(); if (text.length() > 40) text = text.subSequence(0, 40) + "..."; Rectangle2D r = toolTipFont.getStringBounds(text, g2d.getFontRenderContext()); g2d.setColor(annotationBackgroundColor); g2d.fillRoundRect((int) r.getX() + ax - 3, (int) r.getY() + ay - 3, (int) r.getWidth() + 6, (int) r.getHeight() + 6, 12, 12); g2d.drawLine(dx, dy, ax, ay); g2d.setColor(Color.black); g2d.drawString(text, ax, ay); } } } } // annotations } // synchronized annotations g2d.setStroke(oldStroke); // drow ROI if (ROI != null && (ROI instanceof PolygonExt)) { g2d.setColor(Color.yellow); //g2d.setXORMode(Color.white); drawPolygonLine(((PolygonExt) ROI).getScaledInstance(getScale(), currentOffs), g2d); } } // drawMarkup // without vieportOffset g2d.translate(viewPortOffset.getX(), viewPortOffset.getY()); if (muMeterPerPixel > 0 && OrbitImageAnalysis.getInstance().isShowGauge()) { final int gaugeLen = 100; // Component c = getParent().getParent().getParent().getParent().getParent(); // imageFrame // int gaugeY = c.getHeight()-100+viewPortOffset.y; // int gaugeX = 20+viewPortOffset.x; // int gaugeY = getHeight() - 40; // was -80 int gaugeX = 20; double gaugeVal = (double) gaugeLen * muMeterPerPixel * (1d / sc); //g.setColor(Color.white); //g.fillRect(gaugeX, gaugeY, gaugeLen, 15); g2d.setColor(gaugeColor); g2d.drawLine(gaugeX, gaugeY, gaugeX + gaugeLen, gaugeY); g2d.drawLine(gaugeX, gaugeY - 10, gaugeX, gaugeY + 10); g2d.drawLine(gaugeX + gaugeLen, gaugeY - 10, gaugeX + gaugeLen, gaugeY + 10); g2d.drawString(String.format("%1$.2f µm", gaugeVal), gaugeX + 5, gaugeY + 13); } } catch (Exception e) { e.printStackTrace(); } finally { g.drawImage(screenImage,0,0,null); g2d.dispose(); } } public void prepareBuffer() { if (bimg != null && bimg.hasMipMaps()) { getRenderThread().setValuesDirty(true); //if (renderThread.isScheduleUpdate()) return; //renderThread.stop(); //renderThread = new RenderThread(); //renderThread.addPropertyChangeListener(this); getRenderThread().setScale(getScale()); getRenderThread().setViewPortWidth(getViewPortSize().getWidth()); getRenderThread().setViewPortHeight(getViewPortSize().getHeight()); getRenderThread().setViewPortOffsetX(getViewPortOffset().getX()); getRenderThread().setViewPortOffsetY(getViewPortOffset().getY()); getRenderThread().setTiledImagePainter(bimg); getRenderThread().setScheduleUpdate(true); //renderThread.start(); } } @Override public void repaint() { TiledImageWriter.timeOut.set(System.currentTimeMillis()); super.repaint(); } @Override public void repaint(long tm, int x, int y, int width, int height) { TiledImageWriter.timeOut.set(System.currentTimeMillis()); super.repaint(tm, x, y, width, height); } @Override public void repaint(Rectangle r) { TiledImageWriter.timeOut.set(System.currentTimeMillis()); super.repaint(r); } @Override public void repaint(int x, int y, int width, int height) { TiledImageWriter.timeOut.set(System.currentTimeMillis()); super.repaint(x, y, width, height); } @Override public void repaint(long tm) { TiledImageWriter.timeOut.set(System.currentTimeMillis()); super.repaint(tm); } @Override public void update(Graphics g) { TiledImageWriter.timeOut.set(System.currentTimeMillis()); super.update(g); } /** * set all pixels in classImage with class label in oldClasses to the newClass label (for two class sets, e.g. set inclusion and exclusion at once) */ public void changeClassLabels(List oldClasses1, Byte newClass1, List oldClasses2, Byte newClass2) { if (classImage == null) throw new IllegalArgumentException("classImage is null, please perform a classification first."); initializeClassColors(); Color c1 = classShapes.get(newClass1).getColor(); Color c2 = classShapes.get(newClass2).getColor(); Byte classVal; Shape roi = null; if (getROI() != null) roi = getROI().getScaledInstance(100d, new Point(0, 0)); Point[] tileList = classImage.getImage().getTileIndices(null); for (Point tile : tileList) { WritableRaster writeRaster = classImage.getImage().getWritableTile(tile.x, tile.y); for (int x = classImage.getImage().tileXToX(tile.x); x < classImage.getImage().tileXToX(tile.x) + classImage.getImage().getTileWidth(); x++) for (int y = classImage.getImage().tileYToY(tile.y); y < classImage.getImage().tileYToY(tile.y) + classImage.getImage().getTileHeight(); y++) { if ((roi == null) || (roi.contains(x, y))) { classVal = getClass(x, y, writeRaster); if (classVal != null) { for (Byte cv : oldClasses1) { if (cv == classVal) { writeRaster.setPixel(x, y, new int[]{c1.getRed(), c1.getGreen(), c1.getBlue(), 255}); break; } } for (Byte cv : oldClasses2) { if (cv == classVal) { writeRaster.setPixel(x, y, new int[]{c2.getRed(), c2.getGreen(), c2.getBlue(), 255}); break; } } } } // ROI check } // x,y classImage.getImage().releaseWritableTile(tile.x, tile.y); //DiskMemImage.getCommonTileCache().flush(); // really needed? } // tile } public void makeImageSnapshot() { if (((long) bimg.getWidth() * bimg.getHeight()) > (8000L * 8000L)) { JOptionPane.showMessageDialog(this, "In the current version this feature can only be used for images where width*height <= 8000*8000.\nHowever, you can use the Orbit Agent to download the file.", "Image too large", JOptionPane.ERROR_MESSAGE); return; } JFileChooser fc = new JFileChooser(); FileNameExtensionFilter filter = new FileNameExtensionFilter("*.tif", "tif"); fc.setFileFilter(filter); String snapShotFileName = getPicName(); snapShotFileName = snapShotFileName.replaceAll(RawUtilsCommon.getExtension(snapShotFileName, false), "tif"); fc.setSelectedFile(new File(snapShotFileName)); int returnVal = fc.showSaveDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { logger.debug("begin making image snapshot"); String fn = fc.getSelectedFile().getAbsolutePath(); if (!fn.toLowerCase().endsWith(".tif")) fn += ".tif"; Dimension2D oldVPSize = viewPortSize; Point2D oldVPOffs = getViewPortOffset(); double sc = getScale(); setScale(100d); setViewPortOffset(new Point(0, 0)); viewPortSize = new Dimension(bimg.getWidth(), bimg.getHeight()); /* ColorModel colorModel = new ComponentColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[]{8,8,8}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); SampleModel sampleModel = colorModel.createCompatibleSampleModel(256, 256); DiskMemImage tiledImage = new DiskMemImage(0, 0, bimg.getWidth(), bimg.getHeight(), 0, 0, sampleModel, colorModel); Graphics2D g2d = (Graphics2D)tiledImage.createGraphics(); ((DiskMemImageGraphics)g2d).overwriteRenderingHint((((Graphics2D)getGraphics()).getRenderingHints())); */ // Update 1.7.2010: Fallback to normal bufferedImage (only up to 30kx30k pixel!) // due to rendering problems with class image (only first tile problem) BufferedImage buffImg = new BufferedImage(bimg.getWidth(), bimg.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D g2d = buffImg.createGraphics(); buffImg.flush(); paint(g2d); setScale(sc); setViewPortOffset(oldVPOffs); viewPortSize = oldVPSize; logger.info("finished painting"); TIFFEncodeParam param = new TIFFEncodeParam(); param.setTileSize(128, 128); param.setWriteTiled(true); param.setCompression(TIFFEncodeParam.COMPRESSION_JPEG_TTN2); JPEGEncodeParam jpgParam = new JPEGEncodeParam(); jpgParam.setQuality(0.85f); param.setJPEGEncodeParam(jpgParam); // TODO: extraImages (Iterator where .next() returns further (low-res) RenderedImages //param.setExtraImages(extraImages) JAI.create("filestore", /*tiledImage*/buffImg, fn, "TIFF", param); logger.info("finished writing"); JOptionPane.showMessageDialog(null, "Image successfully saved to " + fn, "Image saved", JOptionPane.INFORMATION_MESSAGE); //tiledImage = null; //DiskMemImage.getCommonTileCache().flush(); Runtime.getRuntime().gc(); Runtime.getRuntime().gc(); Runtime.getRuntime().gc(); logger.debug("cleaning up finished"); } } public BufferedImage getImageSnapshot() { if (((long) bimg.getWidth() * bimg.getHeight()) > (30000 * 30000)) { JOptionPane.showMessageDialog(this, "In the current version this feature can only be used for images where width*height <= 30000*30000.", "Image too large", JOptionPane.ERROR_MESSAGE); return null; } Dimension2D oldVPSize = viewPortSize; Point2D oldVPOffs = getViewPortOffset(); double sc = getScale(); setScale(100d); setViewPortOffset(new Point(0, 0)); viewPortSize = new Dimension(bimg.getWidth(), bimg.getHeight()); BufferedImage buffImg = new BufferedImage(bimg.getWidth(), bimg.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D g2d = buffImg.createGraphics(); buffImg.flush(); paint(g2d); setScale(sc); setViewPortOffset(oldVPOffs); viewPortSize = oldVPSize; logger.debug("finished painting"); return buffImg; } /** * (re)init of colorClassLookup */ public void initializeClassColors() { //colorClassLookup = new HashMap(classShapes.size()); colorClassLookup.clear(); synchronized (classShapes) { for (byte i = 0; i < classShapes.size(); i++) { ClassShape cs = classShapes.get(i); colorClassLookup.put(cs.getColor().getRGB(), i); //System.out.println("init color: "+cs.getColor().toString()+" -> "+i+" ("+cs.getColor().getRGB()+")"); } } // System.out.println("CS: "); // for (Integer i: colorClassLookup.keySet()) { // System.out.println(i+":"+colorClassLookup.get(i)); // } } /** * requires getObjectSegmentation to be called first * * @return */ public List getMixtures() { if (objectSegmentationList == null) throw new RuntimeException("Error: call getObjectSegmentations first!"); if (classImage == null) throw new RuntimeException("Error: call classifyImage first!"); List mixList = new ArrayList(objectSegmentationList.size()); for (Shape shape : objectSegmentationList) { int sum = 0; double[] mix = new double[classShapes.size()]; for (int i = 0; i < mix.length; i++) mix[i] = 0d; for (int x = (int) shape.getBounds().getMinX(); x < shape.getBounds().getMaxX(); x++) for (int y = (int) shape.getBounds().getMinY(); y < shape.getBounds().getMaxY(); y++) { if (shape.contains(x, y)) { mix[getClass(x, y)]++; sum++; } } for (int i = 0; i < mix.length; i++) mix[i] = mix[i] / (double) sum; mixList.add(mix); } return mixList; } private void drawPolygonLine(Polygon poly, Graphics g) { if (poly instanceof PolygonExt) { ((PolygonExt) poly).drawPolygon(g); } else { g.drawPolygon(poly); } } private Point getUppedRightPoint(Polygon poly) { int x = poly.getBounds().x; int y = poly.getBounds().y + poly.getBounds().height; for (int i = 0; i < poly.npoints; i++) { if (poly.xpoints[i] > x && poly.ypoints[i] < y) { x = poly.xpoints[i]; y = poly.ypoints[i]; } } return new Point(x, y); } public static Color getColorByNum(int num) { if (num < colors.length) return colors[num]; else return new Color((num * 10000) + rand.nextInt()); } /** * returns the class number (in byte) of a position (calls classImage.getPixel(x,y))
* * @param x * @param y * @return */ public byte getClass(int x, int y) { // TODO: performance! (but currently not so bad) Byte b = colorClassLookup.get(classImage.getPixel(x, y)); if (b == null) return 0; else return b; } /** * returns the class number (in byte) of a position (calls classImage.getPixel(x,y))
* here the classImage can be specified (used by cell segmentation). * * @param x * @param y * @return */ public byte getClass(int x, int y, TiledImageWriter classImage2) { Byte b = colorClassLookup.get(classImage2.getPixel(x, y)); if (b == null) { return 0; } else return b; } /** * returns the class number (in byte) of a position (calls classImage.getPixel(x,y,raster))
* here the classImage can be specified (used by cell segmentation). * * @param x * @param y * @return */ public byte getClass(int x, int y, TiledImageWriter classImage2, Raster raster) { Byte b = colorClassLookup.get(classImage2.getPixel(x, y, raster)); if (b == null) { return 0; } else return b; } /** * returns the class number (in byte) of a position (calls classImage.getPixel(x,y,r))
* This is the more performant method where the raster is already available. * Returns nullVal if x,y is outside ROI ! * * @param x * @param y * @return */ public byte getClass(int x, int y, final Raster r, final byte nullVal) { int i = classImage.getPixel(x, y, r); if (i == OrbitUtils.UNDEF_COLOR) return nullVal; // black / undef byte b = colorClassLookup.get(i); return b; } /** * returns the class number (in byte) of a position (calls classImage.getPixel(x,y,r))
* Can return null if x,y is outsite ROI ! * This is the more performant method where the raster is already available. * * @param x * @param y * @return */ public Byte getClass(int x, int y, final Raster r) { int i = classImage.getPixel(x, y, r); if (i == OrbitUtils.UNDEF_COLOR) return null; // black / undef Byte b = colorClassLookup.get(i); //if (b==null) System.out.println(i); return b; } public List getClassShapes() { return classShapes; } public void setClassShapes(List classShapes) { synchronized (this.classShapes) { this.classShapes.clear(); this.classShapes.addAll(classShapes); ratio = new double[classShapes.size()]; } } public void setClassShapes(final List classShapes, int segmentationSize) { synchronized (this.classShapes) { this.classShapes.clear(); this.classShapes.addAll(classShapes); this.segmentationClassSize = segmentationSize; ratio = new double[classShapes.size()]; } } public void setModel(OrbitModel model) { setClassShapes(model.getClassShapes()); setWindowSize(model.getFeatureDescription().getWindowSize()); setBoundaryClass(model.getBoundaryClass()); } /** * annotationGroup -1 means ignore, 0 means use all, otherwise the specific group * * @param rdfID * @param annotationGroup */ public void loadAnnotationROI(int rdfID, int annotationGroup) { loadAnnotationROI(rdfID, annotationGroup, false); } /** * annotationGroup -1 means ignore, 0 means use all, otherwise the specific group * * @param rdfID * @param annotationGroup */ public void loadAnnotationROI(int rdfID, int annotationGroup, boolean otherGroupROIAsExclusion) { loadAnnotationROI(rdfID, annotationGroup, otherGroupROIAsExclusion, false); } /** * annotationGroup -1 means ignore, 0 means use all, otherwise the specific group * * @param rdfID * @param annotationGroup */ public void loadAnnotationROI(int rdfID, int annotationGroup, boolean otherGroupROIAsExclusion, boolean exclusionsForAllGroups) { if (annotationGroup < 0) { setROI(null); return; // ignore } try { IScaleableShape roi = OrbitUtils.loadAnnotationROI(rdfID, annotationGroup, otherGroupROIAsExclusion, exclusionsForAllGroups); if ((roi != null) && Math.abs(mipScale - 1d) > OrbitUtils.EPSILON) { roi = (IScaleableShape) roi.getScaledInstance(((mipScale) * 100d), new Point(0, 0)); roi.setScale(100d); } setROI(roi); } catch (Exception e) { logger.error("cannot load raw annotations", e); } } /** * load image annotations according to rdfID. Annotation with name ROI are used as ROI, if useAnnotationsAsInverseROI is true, all other annotations * (description<>ROI are used as inverse ROI). ROI and inverse ROIs can be combined. */ @Deprecated public void loadAnnotationROIOld(int rdfID, boolean useAnnotationsAsInverseROI) { try { List annotations = DALConfig.getImageProvider().LoadRawAnnotationsByRawDataFile(rdfID, RawAnnotation.ANNOTATION_TYPE_IMAGE); List pList = new ArrayList(annotations.size()); Shape annotationROI = null; for (RawAnnotation anno : annotations) { if (anno.getRawAnnotationType() == RawAnnotation.ANNOTATION_TYPE_IMAGE) { ImageAnnotation ia = new ImageAnnotation(anno); if (ia.getShape().getShapeList().size() > 0) { IScaleableShape poly = (IScaleableShape) ia.getShape().getShapeList().get(0); IScaleableShape pScaled = (IScaleableShape) poly.getScaledInstance(100d, new Point(0, 0)); if (anno.getDescription().trim().equalsIgnoreCase("ROI")) { annotationROI = pScaled; } else { if (useAnnotationsAsInverseROI) pList.add(pScaled); } } } } ShapeExtListInvers roi = new ShapeExtListInvers(annotationROI, pList, new Rectangle(Integer.MAX_VALUE, Integer.MAX_VALUE)); setROI(roi); logger.trace("invers annotation ROI successfully set: " + pList.size()); } catch (Exception e) { logger.error("cannot load raw annotations", e); } } /** * Creates a BufferedImage of the raster with 0,0 as origin and ColorModel from the current image (bimg.getImage()). */ public BufferedImage createBufferedImage(final Raster r) { WritableRaster writableRaster = r.createCompatibleWritableRaster(r.getWidth(),r.getHeight()); writableRaster.setDataElements(0, 0, r.createTranslatedChild(0,0)); DataBuffer dataBuffer = writableRaster.getDataBuffer(); WritableRaster wr = Raster.createWritableRaster(bimg.getImage().getColorModel().createCompatibleSampleModel(writableRaster.getWidth(),writableRaster.getHeight()), dataBuffer, new Point(0, 0)); BufferedImage bi = new BufferedImage(bimg.getImage().getColorModel(), wr, bimg.getImage().getColorModel().isAlphaPremultiplied(), null); return bi; } public BufferedImage getViewportImage(Point2D center, int vpWidth, int vpHeight) throws Exception { if (bimg==null) throw new Exception("no image tiledImagePainter available (bimg=null)"); double vpX = -(vpWidth/2d); double vpY = -(vpHeight/2d); BufferedImage bi = new BufferedImage(vpWidth,vpHeight,BufferedImage.TYPE_INT_RGB); Graphics2D g2d = (Graphics2D) bi.getGraphics(); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); double sc = scale / 100d; double vpOffsX = center.getX()*sc +vpX; double vpOffsY = center.getY()*sc +vpY; g2d.translate(-vpOffsX,-vpOffsY); g2d.scale(sc, sc); bimg.drawImage(g2d,vpOffsX,vpOffsY,vpWidth,vpHeight,scale,0); bi.flush(); return bi; } /** * loads the mu meter per pixel meta data from raw meta database */ public void loadImageScale(int rdfId) { setMuMeterPerPixel(OrbitUtils.loadImageScale(rdfId)); } @Override public String toString() { return "RecognitionFrame [picName=" + picName + ", ROI=" + ROI + ", scale=" + scale + ", muMeterPerPixel=" + muMeterPerPixel + ", bimg=" + bimg + "]"; } public String getPicName() { return picName; } public void setPicName(String picName) { this.picName = picName; } public float getOpacity() { return opacity; } public void setOpacity(float opacity) { forceRepaint.set(true); this.opacity = opacity; } public double[] getRatio() { return ratio; } public void setRatio(double[] ratio) { this.ratio = ratio; } public TiledImageWriter getClassImage() { return classImage; } public void setClassImage(TiledImageWriter classImage) { this.classImage = classImage; } public boolean isDrawMarkup() { return drawMarkup; } public void setDrawMarkup(boolean drawMarkup) { this.drawMarkup = drawMarkup; } public double getTargetRadius() { return targetRadius; } public void setTargetRadius(double targetRadius) { this.targetRadius = targetRadius; } public int getWindowSize() { return windowSize; } public void setWindowSize(int windowSize) { this.windowSize = windowSize; } public double getSegmentationClassSize() { return segmentationClassSize; } public void setSegmentationClassSize(double segmentationClassSize) { this.segmentationClassSize = segmentationClassSize; } public List getClassList() { return classList; } public void clearClassList() { classListLock.writeLock().lock(); try { this.classList.clear(); } finally { classListLock.writeLock().unlock(); } } public List getObjectSegmentationList() { return objectSegmentationList; } public void setObjectSegmentationList(List objectSegmentationList) { this.objectSegmentationList = objectSegmentationList; } public List getObjectSegmentationColors() { return objectSegmentationColors; } public void setObjectSegmentationColors(List objectSegmentationColors) { this.objectSegmentationColors = objectSegmentationColors; } public List getCenterList() { return centerList; } public void setCenterList(List centerList) { this.centerList = centerList; } public List getCentroidList() { return centroidList; } public void setCentroidList(List centroidList) { this.centroidList = centroidList; } public void setScale(double scale) { this.scale = scale; prepareBuffer(); } /** * scale 0..100 * * @return */ public double getScale() { //return ((double)bimg.getWidth() / originalWidth)*(double)100; return scale; } public Point2D getViewPortOffset() { return viewPortOffset; } public void setViewPortOffset(Point2D viewPortOffset) { this.viewPortOffset = viewPortOffset; prepareBuffer(); } public void addViewPortOffset(Point2D addOffset) { this.viewPortOffset.setLocation(viewPortOffset.getX() + addOffset.getX(), viewPortOffset.getY() + addOffset.getY()); prepareBuffer(); } public Tools getSelectedTool() { return selectedTool; } public void setSelectedTool(Tools selectedTool) { this.selectedTool = selectedTool; } public ShapePainterListener getMyListener() { return myListener; } public void setMyListener(ShapePainterListener myListener) { this.myListener = myListener; } @Deprecated public boolean isContextClassificationEnabled() { return contextClassificationEnabled; } @Deprecated public void setContextClassificationEnabled(boolean contextClassificationEnabled) { this.contextClassificationEnabled = contextClassificationEnabled; } @Deprecated public int getBoundaryClass() { return boundaryClass; } @Deprecated public void setBoundaryClass(int boundaryClass) { this.boundaryClass = boundaryClass; if (boundaryClass == -1) classBounds = null; } public String getToolTip() { return toolTip; } public void setToolTip(String toolTip) { this.toolTip = toolTip; } public Point getToolTipPosition() { return toolTipPosition; } public void setToolTipPosition(Point toolTipPosition) { this.toolTipPosition = toolTipPosition; } public boolean isShowObjectToolTip() { return showObjectToolTip; } public void setShowObjectToolTip(boolean showObjectToolTip) { this.showObjectToolTip = showObjectToolTip; } public MixtureStatistics getMixStats() { return mixStats; } public void setMixStats(MixtureStatistics mixStats) { this.mixStats = mixStats; } public double getToolTipCurrentScale() { return toolTipCurrentScale; } public void setToolTipCurrentScale(double toolTipCurrentScale) { this.toolTipCurrentScale = toolTipCurrentScale; } public double getOldScale() { return oldScale; } public void setOldScale(double oldScale) { this.oldScale = oldScale; } public int[] getObjectClassificationList() { return objectClassificationList; } public synchronized void setObjectClassificationList(int[] objectClassificationList) { this.objectClassificationList = objectClassificationList; } public FeatureDescription getFeatureDescription() { return featureDescription; } public IScaleableShape getROI() { return ROI; } public void setROI(IScaleableShape rOI) { ROI = rOI; } public List getAnnotations() { return annotations; } public float getClassImageScale() { return classImageScale; } public void setClassImageScale(float classImageScale) { this.classImageScale = classImageScale; } public double getMuMeterPerPixel() { return muMeterPerPixel; } public void setMuMeterPerPixel(double muMeterPerPixel) { this.muMeterPerPixel = muMeterPerPixel; } public Color getGaugeColor() { return gaugeColor; } public void setGaugeColor(Color gaugeColor) { this.gaugeColor = gaugeColor; } public Dimension2D getViewPortSize() { return viewPortSize; } public void setViewPortSize(Dimension2D viewPortSize) { this.viewPortSize = viewPortSize; prepareBuffer(); } @Deprecated public RecognitionFrame getNegativeChannel() { return negativeChannel; } @Deprecated public void setNegativeChannel(RecognitionFrame negativeChannel) { this.negativeChannel = negativeChannel; } // public ExclusionMapGen getExMapGen() { // return exMapGen; // } // // public void setExMapGen(ExclusionMapGen exMapGen) { // this.exMapGen = exMapGen; // } /** * sets windowSize and contextClassification based on the featureDescription * * @param featureDescription */ public void setFeatureDescription(FeatureDescription featureDescription) { this.setWindowSize(featureDescription.getWindowSize()); this.setContextClassificationEnabled(featureDescription.isContextClassificationEnabled()); this.featureDescription = featureDescription; } public String getOriginalName() { return originalName; } public void setOriginalName(String originalName) { this.originalName = originalName; } public boolean isDisplayAnnotationLabels() { return displayAnnotationLabels; } public void setDisplayAnnotationLabels(boolean displayAnnotationLabels) { this.displayAnnotationLabels = displayAnnotationLabels; } public double getMipScale() { return mipScale; } public void setMipScale(double mipScale) { this.mipScale = mipScale; } public List getSecondaryObjectSegmentationList() { return secondaryObjectSegmentationList; } public void setSecondaryObjectSegmentationList(List secondaryObjectSegmentationList) { this.secondaryObjectSegmentationList = secondaryObjectSegmentationList; } public static AtomicInteger getActiveAnnotationGroup() { return activeAnnotationGroup; } public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals(ClassificationTaskTiled.CLASSIFICATION_PROGRESS)) { threadProgress.put(evt.getSource(), (Double) evt.getNewValue()); double progress = 0d; for (Object obj : threadProgress.keySet()) { progress += threadProgress.get(obj); } if ((taskList != null) && (taskList.size() > 0)) progress /= taskList.size(); long elapsed = (System.currentTimeMillis() - startTime) / 1000L; double et = (elapsed / (progress / 100d)) * (1d - (progress / 100d)); logger.debug("Classification progress: " + String.format("%1$.2f", progress) + "% est. time: " + OrbitUtils.formatTime(et)); } else { if (evt.getPropertyName().equals(RenderThread.RENDERBUFFER_READY)) { forceRepaint.set(true); repaint(); } } } public AtomicBoolean getForceRepaint() { return forceRepaint; } public void setForceRepaint(AtomicBoolean forceRepaint) { this.forceRepaint = forceRepaint; } class ScreenProps { double vpOffsX; double vpOffsY; double vpWidthM; double vpHeight; double scale; double opacity; public ScreenProps(double vpOffsX, double vpOffsY, double vpWidthM, double vpHeight, double scale, double opacity) { this.vpOffsX = vpOffsX; this.vpOffsY = vpOffsY; this.vpWidthM = vpWidthM; this.vpHeight = vpHeight; this.scale = scale; this.opacity = opacity; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ScreenProps that = (ScreenProps) o; return Double.compare(that.vpOffsX, vpOffsX) == 0 && Double.compare(that.vpOffsY, vpOffsY) == 0 && Double.compare(that.vpWidthM, vpWidthM) == 0 && Double.compare(that.vpHeight, vpHeight) == 0 && Double.compare(that.scale, scale) == 0 && Double.compare(that.opacity, opacity) == 0; } @Override public int hashCode() { return Objects.hash(vpOffsX, vpOffsY, vpWidthM, vpHeight, scale, opacity); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy