/** * Create a new stains object with the same StainVectors but a new name. * * @param name * @return */ public ColorDeconvolutionStains changeName(String name) { return new ColorDeconvolutionStains(name, getStain(1), getStain(2), getStain(3), getMaxRed(), getMaxGreen(), getMaxBlue()); }
/** * Create a new stains object with the same StainVectors but new max (background) values. * * @param maxRed * @param maxGreen * @param maxBlue * @return */ public ColorDeconvolutionStains changeMaxValues(double maxRed, double maxGreen, double maxBlue) { return new ColorDeconvolutionStains(getName(), getStain(1), getStain(2), getStain(3), maxRed, maxGreen, maxBlue); }
private void initializeStainMap() { stainMap.put(ImageType.BRIGHTFIELD_H_DAB, ColorDeconvolutionStains.makeDefaultColorDeconvolutionStains(DEFAULT_CD_STAINS.H_DAB)); stainMap.put(ImageType.BRIGHTFIELD_H_E, ColorDeconvolutionStains.makeDefaultColorDeconvolutionStains(DEFAULT_CD_STAINS.H_E)); stainMap.put(ImageType.BRIGHTFIELD_OTHER, ColorDeconvolutionStains.makeDefaultColorDeconvolutionStains(DEFAULT_CD_STAINS.H_DAB)); }
public static ColorDeconvolutionStains parseColorDeconvolutionStainsArg(final String s) { Map<String, String> map = GeneralTools.parseArgStringValues(s); if (map.isEmpty()) return null; StainVector stain1 = parseStainVector(Locale.US, map.get("Stain 1"), map.get("Values 1")); StainVector stain2 = parseStainVector(Locale.US, map.get("Stain 2"), map.get("Values 2")); StainVector stain3 = null; if (map.containsKey("Stain 3")) stain3 = parseStainVector(Locale.US, map.get("Stain 3"), map.get("Values 3")); double[] background = parseStainValues(Locale.US, map.get("Background")); return new ColorDeconvolutionStains(map.get("Name"), stain1, stain2, stain3, background[0], background[1], background[2]); }
boolean doColorTestForHE = checkColors && stainsOriginal.isH_E(); boolean doGrayTest = checkColors && (stainsOriginal.isH_E() || stainsOriginal.isH_DAB()); double sqrt3 = 1/Math.sqrt(3); double grayThreshold = Math.cos(0.15); StainVector s1 = new StainVector(stainsOriginal.getStain(1).getName(), red[ind1], green[ind1], blue[ind1]); StainVector s2 = new StainVector(stainsOriginal.getStain(2).getName(), red[ind2], green[ind2], blue[ind2]); if (stainsOriginal.isH_E()) { s1 = new StainVector(stainsOriginal.getStain(1).getName(), red[ind2], green[ind2], blue[ind2]); s2 = new StainVector(stainsOriginal.getStain(2).getName(), red[ind1], green[ind1], blue[ind1]); double angle11 = StainVector.computeAngle(s1, stainsOriginal.getStain(1)); double angle12 = StainVector.computeAngle(s1, stainsOriginal.getStain(2)); double angle21 = StainVector.computeAngle(s2, stainsOriginal.getStain(1)); double angle22 = StainVector.computeAngle(s2, stainsOriginal.getStain(2)); if (Math.min(angle12, angle21) < Math.min(angle11, angle22)) { s1 = new StainVector(stainsOriginal.getStain(1).getName(), red[ind2], green[ind2], blue[ind2]); s2 = new StainVector(stainsOriginal.getStain(2).getName(), red[ind1], green[ind1], blue[ind1]); ColorDeconvolutionStains stains = new ColorDeconvolutionStains(stainsOriginal.getName(), s1, s2, stainsOriginal.getMaxRed(), stainsOriginal.getMaxGreen(), stainsOriginal.getMaxBlue());
public static float colorDeconvolveRGBPixel(int rgb, ColorDeconvolutionStains stains, int channel) { double[][] matInv = stains.getMatrixInverse(); double scaleRed = matInv[0][channel]; double scaleGreen = matInv[1][channel]; double scaleBlue = matInv[2][channel]; // Apply color deconvolution double r = ColorDeconvolutionHelper.makeOD((rgb & 0xff0000) >> 16, stains.getMaxRed()); double g = ColorDeconvolutionHelper.makeOD((rgb & 0xff00) >> 8, stains.getMaxGreen()); double b = ColorDeconvolutionHelper.makeOD((rgb & 0xff), stains.getMaxBlue()); return (float)(r * scaleRed + g * scaleGreen + b * scaleBlue); }
od_lut = ColorDeconvolutionHelper.makeODLUT(stains.getMaxRed()); for (int i = 0; i < buf.length; i++) { pixels[i] = (float)od_lut[ColorTools.red(buf[i])]; od_lut = ColorDeconvolutionHelper.makeODLUT(stains.getMaxGreen()); for (int i = 0; i < buf.length; i++) { pixels[i] = (float)od_lut[ColorTools.green(buf[i])]; od_lut = ColorDeconvolutionHelper.makeODLUT(stains.getMaxBlue()); for (int i = 0; i < buf.length; i++) { pixels[i] = (float)od_lut[ColorTools.blue(buf[i])]; if (stains == null || !stains.isH_E()) { throw new IllegalArgumentException("No valid H&E stains supplied!"); od_lut_red = ColorDeconvolutionHelper.makeODLUT(stains.getMaxRed()); od_lut_green = ColorDeconvolutionHelper.makeODLUT(stains.getMaxGreen()); od_lut_blue = ColorDeconvolutionHelper.makeODLUT(stains.getMaxBlue()); inverse = stains.getMatrixInverse(); for (int i = 0; i < buf.length; i++) { pixels[i] = ColorTransformer.deconvolve(buf[i], inverse, od_lut_red, od_lut_green, od_lut_blue, 1); if (stains == null || !stains.isH_E()) { throw new IllegalArgumentException("No valid H&E stains supplied!"); od_lut_red = ColorDeconvolutionHelper.makeODLUT(stains.getMaxRed()); od_lut_green = ColorDeconvolutionHelper.makeODLUT(stains.getMaxGreen()); od_lut_blue = ColorDeconvolutionHelper.makeODLUT(stains.getMaxBlue()); inverse = stains.getMatrixInverse();
boolean[] mask = createStainMask(redOD, greenOD, blueOD, minStain, stains.isH_DAB() || stains.isH_E(), true, null); double[] stain1 = stains.getStain(1).getArray(); double[] stain2 = stains.getStain(2).getArray(); float[] stain1Proj = new float[nnz]; float[] stain2Proj = new float[nnz]; StainVector stain2Refined = new StainVector(stains.getStain(2).getName(), base1[0]*cos + base2[0]*sin, base1[1]*cos + base2[1]*sin, base1[2]*cos + base2[2]*sin); cos = Math.cos(maxAngle); sin = Math.sin(maxAngle); StainVector stain1Refined = new StainVector(stains.getStain(1).getName(), base1[0]*cos + base2[0]*sin, base1[1]*cos + base2[1]*sin, base1[2]*cos + base2[2]*sin); return new ColorDeconvolutionStains(stains.getName(), stain1Refined, stain2Refined, whiteValues[0], whiteValues[1], whiteValues[2]);
public static ColorDeconvolutionStains estimateStains(final BufferedImage img, final ColorDeconvolutionStains stainsOriginal, final double minStain, final double maxStain, final double ignorePercentage, final boolean checkColors) { int[] buf = img.getRGB(0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth()); int[] rgb = buf; float[] red = ColorDeconvolutionHelper.getRedOpticalDensities(rgb, stainsOriginal.getMaxRed(), null); float[] green = ColorDeconvolutionHelper.getGreenOpticalDensities(rgb, stainsOriginal.getMaxGreen(), null); float[] blue = ColorDeconvolutionHelper.getBlueOpticalDensities(rgb, stainsOriginal.getMaxBlue(), null); return estimateStains(buf, red, green, blue, stainsOriginal, minStain, maxStain, ignorePercentage, checkColors); }
public String getPrompt(final ImageData<?> imageData) { ColorDeconvolutionStains stains = imageData == null ? null : imageData.getColorDeconvolutionStains(); if (stains != null) { switch (this) { case STAIN_1: return stains.getStain(1).getName() + " (color deconvolved)"; case STAIN_2: return stains.getStain(2).getName() + " (color deconvolved)"; case STAIN_3: return stains.getStain(3).getName() + " (color deconvolved)"; default: break; } } return prompt; }
public void setColorDeconvolutionStains(final String stainsString) { setColorDeconvolutionStains(ColorDeconvolutionStains.parseColorDeconvolutionStainsArg(stainsString)); }
/** * Create a ColorDeconvolutionStains for a default stain combination, and default max values (255 for all channels). * * @param stains * @return */ public static ColorDeconvolutionStains makeDefaultColorDeconvolutionStains(DEFAULT_CD_STAINS stains) { switch(stains) { case H_E: return new ColorDeconvolutionStains("H&E default", StainVector.makeDefaultStainVector(StainVector.DEFAULT_STAINS.HEMATOXYLIN), StainVector.makeDefaultStainVector(StainVector.DEFAULT_STAINS.EOSIN)); case H_DAB: return new ColorDeconvolutionStains("H-DAB default", StainVector.makeDefaultStainVector(StainVector.DEFAULT_STAINS.HEMATOXYLIN), StainVector.makeDefaultStainVector(StainVector.DEFAULT_STAINS.DAB)); } return null; }
output = new float[buf.length]; double[][] matInv = stains.getMatrixInverse(); double scaleBlue = matInv[2][channel]; double maxRed = stains.getMaxRed(); //J double maxGreen = stains.getMaxGreen(); //J double maxBlue = stains.getMaxBlue(); //J
@Override public float getValue(BufferedImage img, int x, int y) { ensureStainsUpdated(); if (stains == null) return 0f; int rgb = img.getRGB(x, y); if (method == null) return ColorDeconvolution.colorDeconvolveRGBPixel(rgb, stains, stainNumber-1); else if (method == ColorTransformMethod.Optical_density_sum) { int r = ColorTools.red(rgb); int g = ColorTools.green(rgb); int b = ColorTools.blue(rgb); return (float)(ColorDeconvolutionHelper.makeOD(r, stains.getMaxRed()) + ColorDeconvolutionHelper.makeOD(g, stains.getMaxGreen()) + ColorDeconvolutionHelper.makeOD(b, stains.getMaxBlue())); } else return ColorTransformer.getPixelValue(rgb, method); }
public String getName(final ColorDeconvolutionStains stains) { switch (this) { case STAIN_1: return stains == null ? "Stain 1" : stains.getStain(1).getName(); case STAIN_2: return stains == null ? "Stain 2" : stains.getStain(2).getName(); case STAIN_3: return stains == null ? "Stain 3" : stains.getStain(3).getName(); case HUE: return "Hue"; case OD: return "OD Sum"; default: return getPrompt(null); } }
@Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { int version = in.readInt(); if (version != 1) logger.error("{} unsupported version number: {}", getClass().getSimpleName(), version); Object o = in.readObject(); if (o instanceof String) { ColorDeconvolutionStains stains = parseColorDeconvolutionStainsArg((String)o); name = stains.name; stain1 = stains.stain1; stain2 = stains.stain2; stain3 = stains.stain3; maxRed = stains.maxRed; maxGreen = stains.maxGreen; maxBlue = stains.maxBlue; } // name = in.readUTF(); // stain1 = (StainVector)in.readObject(); // stain2 = (StainVector)in.readObject(); // stain3 = (StainVector)in.readObject(); // maxRed = in.readDouble(); // maxGreen = in.readDouble(); // maxBlue = in.readDouble(); }
/** * Create a new ColorDeconvolutionStains object, with all settings the same except one of the stains has been changed. * If the third stain was a residual, it will also be regenerated (i.e. it won't remain the same residual... which would be wrong, * as it would be orthogonal to the old stain rather than the new one). * * @param stains * @param stain * @param stainNumber * @return */ public static ColorDeconvolutionStains makeModifiedStains(ColorDeconvolutionStains stains, StainVector stainNew, int stainNumber) { StainVector[] stainVectors = new StainVector[3]; stainVectors[0] = stains.getStain(1); stainVectors[1] = stains.getStain(2); stainVectors[2] = stains.getStain(3); stainVectors[stainNumber - 1] = stainNew; if (stainVectors[2].isResidual()) stainVectors[2] = null; return new ColorDeconvolutionStains(stains.getName(), stainVectors[0], stainVectors[1], stainVectors[2], stains.getMaxRed(), stains.getMaxGreen(), stains.getMaxBlue()); }
bufOutput = new int[buf.length]; double[][] matInv = stainsInput.getMatrixInverse(); double s22 = matInv[2][2]; discardResidual = discardResidual && stainsInput.getStain(3).isResidual(); double d00 = stainsOutput.getStain(1).getRed(); double d01 = stainsOutput.getStain(1).getGreen(); double d02 = stainsOutput.getStain(1).getBlue(); double d10 = stainsOutput.getStain(2).getRed(); double d11 = stainsOutput.getStain(2).getGreen(); double d12 = stainsOutput.getStain(2).getBlue(); double d20 = stainsOutput.getStain(3).getRed(); double d21 = stainsOutput.getStain(3).getGreen(); double d22 = stainsOutput.getStain(3).getBlue(); double maxRed = stainsOutput.getMaxRed(); double maxGreen = stainsOutput.getMaxGreen(); double maxBlue = stainsOutput.getMaxBlue(); double[] od_lut_red = ColorDeconvolutionHelper.makeODLUT(stainsInput.getMaxRed()); double[] od_lut_green = ColorDeconvolutionHelper.makeODLUT(stainsInput.getMaxGreen()); double[] od_lut_blue = ColorDeconvolutionHelper.makeODLUT(stainsInput.getMaxBlue());
/** * Get matrix inverse, as useful for color deconvolution. * See static ColorDeconvolution classes for usage. * * @return */ public double[][] getMatrixInverse() { // Create if we don't have one already if (matInverse == null) { double[][] stainMat = new double[][]{ getStain(1).getArray(), getStain(2).getArray(), getStain(3).getArray()}; ColorDeconvMatrix3x3 mat3x3 = new ColorDeconvMatrix3x3(stainMat); matInverse = mat3x3.inverse(); } return matInverse; }
public static boolean setColorDeconvolutionStains(final String arg) { ImageData<?> imageData = getCurrentImageData(); if (imageData == null) return false; ColorDeconvolutionStains stains = ColorDeconvolutionStains.parseColorDeconvolutionStainsArg(arg); imageData.setColorDeconvolutionStains(stains); return true; }