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); }
public static StainVector makeDefaultStainVector(DEFAULT_STAINS stain) { switch(stain) { case HEMATOXYLIN: return new StainVector(stain.toString(), STAIN_HEMATOXYLIN_DEFAULT); case EOSIN: return new StainVector(stain.toString(), STAIN_EOSIN_DEFAULT); case DAB: return new StainVector(stain.toString(), STAIN_DAB_DEFAULT); } return null; }
/** * Check if we have H&E staining, by checking the names of the first two stains and confirming that the third stain is a residual. * Note the order of the stains must be 1-Hematoxylin, 2-Eosin, 3-residual (missing) * @return */ public boolean isH_E() { return stain3.isResidual() && isHematoxylin(stain1) && isEosin(stain2); }
/** * 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); }
/** * 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 StainVector generateStainVectorFromRGB(String name, int rgb, double redMax, double greenMax, double blueMax) { double rOD = makeOD(ColorTools.red(rgb), redMax); double gOD = makeOD(ColorTools.green(rgb), greenMax); //J double bOD = makeOD(ColorTools.blue(rgb), blueMax); //J return new StainVector(name, rOD, gOD, bOD); }
/** * Convert to optical densities in which a second image is used to provide the 'maximum' (i.e. white) pixel values. * @param px * @param pxMax */ public static void convertPixelsToOpticalDensities(float[] px, float[] pxMax) { for (int i = 0; i < px.length; i++) px[i] = (float)makeOD(px[i], pxMax[i]); }
public double[][] inverse() { double invDet3 = 1/determinant(); return new double[][]{ {invDet3*det2(m22,m23,m32,m33), invDet3*det2(m13,m12,m33,m32), invDet3*det2(m12,m13,m22,m23)}, {invDet3*det2(m23,m21,m33,m31), invDet3*det2(m11,m13,m31,m33), invDet3*det2(m13,m11,m23,m21)}, {invDet3*det2(m21,m22,m31,m32), invDet3*det2(m12,m11,m32,m31), invDet3*det2(m11,m12,m21,m22)}}; }
/** * This method is *only* compatible with color transforms that do not require a ColorDeconvolutionStains object - * other transforms will throw an illegal argument exception. * * @param buf * @param method * @param pixels * @return */ public static float[] getSimpleTransformedPixels(final int[] buf, final ColorTransformMethod method, float[] pixels) { return getTransformedPixels(buf, method, pixels, null); }
/** * Check if we have H-DAB staining, by checking the names of the first two stains and confirming that the third stain is a residual. * Note the order of the stains must be 1-Hematoxylin, 2-DAB, 3-residual (missing) * @return */ public boolean isH_DAB() { return isHematoxylin(stain1) && isDAB(stain2); // && stain3.isResidual(); }
/** * Convert to a unit vector * @param vec */ public static void normalizeVector(double[] vec) { double len = vectorLength(vec); for (int i = 0; i < vec.length; i++) vec[i] /= len; }
/** * Create a new stains object, identical to this one but for one StainVector having been changed. * * @param stainNew * @param stainNumber * @return */ public ColorDeconvolutionStains changeStain(StainVector stainNew, int stainNumber) { return makeModifiedStains(this, stainNew, stainNumber); }
public ColorDeconvolutionStains(String name, StainVector stain1, StainVector stain2, StainVector stain3, double maxRed, double maxGreen, double maxBlue) { this.name = name; this.stain1 = stain1; this.stain2 = stain2; if (stain3 == null && stain1 != null && stain2 != null) this.stain3 = StainVector.makeResidualStainVector(stain1, stain2); else this.stain3 = stain3; this.maxRed = maxRed; this.maxGreen = maxGreen; this.maxBlue = maxBlue; }
/** * Make a 'residual' stain vector, i.e. a third stain vector orthogonal to two specified vectors. * * @param s1 * @param s2 * @return */ public static StainVector makeResidualStainVector(StainVector s1, StainVector s2) { return makeOrthogonalStainVector("Residual", s1, s2, true); }
@Override public String getName() { return method.toString(); }
public static double[] makeODLUT(double maxValue, int nValues) { double[] OD_LUT = new double[nValues]; for (int i = 0; i < nValues; i++) //J OD_LUT[i] = makeOD(i, maxValue); return OD_LUT; }