for key in test.labelDict.keys(): for value in test.labelDict[key]: listOfNames[value] = names[key] if imageOrTable == "Results table": rt = ResultsTable.getResultsTable(resultsName) else: measureImp = WM.getImage(imageName) src2 = clij2.push(measureImp) rt = ResultsTable() clij2.statisticsOfBackgroundAndLabelledPixels(src2, test.src, rt) src2.close() resultsName = "Results table" collumnNumber = rt.getLastColumn() + 1 for i in range(len(listOfNames)): try: j = rt.getValue("Identifier", i) except: try: j = rt.getValue("Label", i) except: j = i rt.setValue("Label name", i, listOfNames[int(j)]) rt.setValue("Label value", i, test.labelValues[int(j)]) rt.show(resultsName + " with labels") clij2.clear() labelColorBarImp.close()
def processImages(cfg, wellName, wellPath, images): stats = [[[dict() for t in range(cfg.getValue(ELMConfig.numT))] for z in range(cfg.getValue(ELMConfig.numZ))] for c in range(cfg.getValue(ELMConfig.numChannels))] times = {} for c in range(0, cfg.getValue(ELMConfig.numChannels)): chanStr = 'ch%(channel)02d' % {"channel" : c}; chanName = cfg.getValue(ELMConfig.chanLabel)[c] # Set some config based upon channel if (cfg.getValue(ELMConfig.chanLabel)[c] in cfg.getValue(ELMConfig.chansToSkip)): continue if (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.BRIGHTFIELD): minCircularity = 0.001 # We want to identify one big cell ball, so ignore small less circular objects if cfg.params[ELMConfig.imgType] == "png": minSize = 5; else: minSize = 500 elif (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.BLUE) \ or (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.RED) \ or (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.GREEN): # minCircularity = 0.001 minSize = 5 elif (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.YELLOW): minCircularity = 0.001 minSize = 5 # Process images in Z stack for z in range(0, cfg.getValue(ELMConfig.numZ)): zStr = cfg.getZStr(z); for t in range(0, cfg.getValue(ELMConfig.numT)): tStr = cfg.getTStr(t) if (cfg.getValue(ELMConfig.imgType) == "png"): # Brightfield uses the whole iamge if (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.BRIGHTFIELD): currIP = IJ.openImage(images[c][z][t][0]) else: # otherwise, we'll plit off channels chanIdx = 2 if (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.RED): chanIdx = 0 elif (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.GREEN): chanIdx = 1; img = IJ.openImage(images[c][z][t][0]) imgChanns = ChannelSplitter.split(img); img.close() currIP = imgChanns[chanIdx]; else: currIP = IJ.openImage(images[c][z][t][0]) resultsImage = currIP.duplicate() dbgOutDesc = wellName + "_" + zStr + "_" + chanStr + "_" + tStr if (cfg.getValue(ELMConfig.numT) > 1): outputPath = os.path.join(wellPath, "images") if not os.path.exists(outputPath): os.makedirs(outputPath) else: outputPath = wellPath if cfg.getValue(ELMConfig.debugOutput): WindowManager.setTempCurrentImage(currIP) IJ.saveAs('png', os.path.join(outputPath, "Orig_" + dbgOutDesc + ".png")) # We need to get to a grayscale image, which will be done differently for different channels startTime = time.time() currIP = ELMImageUtils.getThresholdedMask(currIP, c, z, t, chanName, cfg, outputPath, dbgOutDesc) endTime = time.time() if not 'grayscale' in times: times['grayscale'] = [] times['grayscale'].append(endTime-startTime) if (not currIP): resultsImage.close() stats[c][z][t][ELMConfig.UM_AREA] = [] continue startTime = time.time() # Create a table to store the results table = ResultsTable() # Create a hidden ROI manager, to store a ROI for each blob or cell #roim = RoiManager(True) # Create a ParticleAnalyzer measurements = Measurements.AREA + Measurements.MEAN + Measurements.STD_DEV + Measurements.MIN_MAX + Measurements.CENTROID + Measurements.RECT + Measurements.ELLIPSE paFlags = ParticleAnalyzer.IN_SITU_SHOW | ParticleAnalyzer.SHOW_MASKS | ParticleAnalyzer.CLEAR_WORKSHEET pa = ParticleAnalyzer(paFlags, measurements, table, minSize, Double.POSITIVE_INFINITY, minCircularity, 1.0) #pa.setHideOutputImage(True) # The Result image is copied when CurrIP can still have calibration from loading # We want the output to be in terms of pixels, for ease of use, so adjust calibration resultsImage.setCalibration(currIP.getCalibration()) Analyzer.setRedirectImage(resultsImage) if not pa.analyze(currIP): print "There was a problem in analyzing", currIP endTime = time.time() if not 'pa' in times: times['pa'] = [] times['pa'].append(endTime-startTime) #for i in range(0, roim.getCount()) : # r = roim.getRoi(i); # r.setColor(Color.red) # r.setStrokeWidth(2) # The measured areas are listed in the first column of the results table, as a float array: newAreas = [] maxArea = 0 if table.getColumn(ResultsTable.AREA): for pixArea in table.getColumn(ResultsTable.AREA): a = pixArea * cfg.getValue(ELMConfig.pixelHeight) * cfg.getValue(ELMConfig.pixelWidth) newAreas.append(a) if (a > maxArea): maxArea = a # Threshold areas idxToRemove = set() if cfg.hasValue(ELMConfig.areaMaxPercentThreshold): areaPercentThresh = cfg.getValue(ELMConfig.areaMaxPercentThreshold) for i in range(0,len(newAreas)): if newAreas[i] < (areaPercentThresh * maxArea): idxToRemove.add(i) if cfg.hasValue(ELMConfig.areaAbsoluteThreshold): areaAbsoluteThresh = cfg.getValue(ELMConfig.areaAbsoluteThreshold) for i in range(0,len(newAreas)): if newAreas[i] < areaAbsoluteThresh: idxToRemove.add(i) for i in sorted(idxToRemove, reverse=True): del newAreas[i] stats[c][z][t][ELMConfig.UM_AREA] = newAreas centroidX = [] centroidY = [] roiX = [] roiY = [] roiWidth = [] roiHeight = [] rArea = [] # Store all of the other data for col in range(0,table.getLastColumn()): newData = table.getColumn(col) if not newData is None: if col == ResultsTable.X_CENTROID: for idx in idxToRemove: centroidX.append(newData[idx]) if col == ResultsTable.Y_CENTROID: for idx in idxToRemove: centroidY.append(newData[idx]) if col == ResultsTable.ROI_X: for idx in idxToRemove: roiX.append(int(newData[idx])) if col == ResultsTable.ROI_Y: for idx in idxToRemove: roiY.append(int(newData[idx])) if col == ResultsTable.ROI_WIDTH: for idx in idxToRemove: roiWidth.append(int(newData[idx])) if col == ResultsTable.ROI_HEIGHT: for idx in idxToRemove: roiHeight.append(int(newData[idx])) if col == ResultsTable.AREA: for idx in idxToRemove: rArea.append(newData[idx]) for i in sorted(idxToRemove, reverse=True): del newData[i] stats[c][z][t][table.getColumnHeading(col)] = newData IJ.saveAs('png', os.path.join(outputPath, "PreFiltered_Segmentation_" + dbgOutDesc + "_particles.png")) # Remove the segmentation masks for the objects removed currProcessor = currIP.getProcessor() ff = FloodFiller(currProcessor) currIP.getProcessor().setValue(0) calib = resultsImage.getCalibration() sortedAreaIndices = [i[0] for i in sorted(enumerate(rArea), key=lambda x:x[1])] for idx in range(0, len(sortedAreaIndices)): i = sortedAreaIndices[idx] centX = int(calib.getRawX(centroidX[i])) centY = int(calib.getRawY(centroidY[i])) # Since the centroid isn't guaranteed to be part of the blob # search around until an active pixel is found found = False halfWidth = min([roiHeight[i], roiWidth[i]]) for offset in range(0,halfWidth): if found: break for x in range(centX-offset,centX+offset+1): if found: break for y in range(centY-offset,centY+offset+1): if not currProcessor.getPixel(x,y) == 0x0: found = True finalX = x finalY = y break if not found: print "\t\tZ = " + str(z) + ", T = " + str(t) + ", chan " + chanName + ": ERROR: Never found active pixel for filtered blob, centroid: " + str(centX) + ", " + str(centY) else: currProcessor.setRoi(roiX[i], roiY[i], roiWidth[i], roiHeight[i]) ff.fill8(finalX,finalY) #IJ.saveAs('png', os.path.join(outputPath, "Segmentation_" + dbgOutDesc + "_" + str(idx) + ".png")) #outImg = pa.getOutputImage() IJ.saveAs('png', os.path.join(outputPath, "Segmentation_" + dbgOutDesc + "_particles.png")) if cfg.hasValue(ELMConfig.createSegMask) and cfg.getValue(ELMConfig.createSegMask) == True: # Create segmentation mask segMask = currIP.duplicate() segMask.setTitle("SegMask_" + dbgOutDesc) # Iterate by smallest area first # We are more likely to correctly label small areas if len(newAreas) > 0: segProcessor = segMask.getProcessor() if (len(newAreas) > 255): segProcessor = segProcessor.convertToShort(True) segMask.setProcessor(segProcessor) ff = FloodFiller(segProcessor) sortedAreaIndices = [i[0] for i in sorted(enumerate(stats[c][z][t]['Area']), key=lambda x:x[1])] for idx in range(0, len(sortedAreaIndices)): row = sortedAreaIndices[idx] centX = int(stats[c][z][t]['X'][row]) centY = int(stats[c][z][t]['Y'][row]) roiX = int(stats[c][z][t]['BX'][row]) roiY = int(stats[c][z][t]['BY'][row]) roiWidth = int(stats[c][z][t]['Width'][row]) roiHeight = int(stats[c][z][t]['Height'][row]) area = stats[c][z][t]['Area'][row] halfRoiHeight = roiHeight/2 + 1 halfRoiWidth = roiWidth/2 + 1 # Since the centroid isn't guaranteed to be part of the blob # search around until an active pixel is found found = False for xOffset in range(0,halfRoiWidth): if found: break for yOffset in range(0, halfRoiHeight): if found: break for x in range(centX-xOffset,centX+xOffset+1): if found: break for y in range(centY-yOffset,centY+yOffset+1): # original image and this image for masked pixel # By checking original image, we avoid confusion with a label of 255 if segProcessor.getPixel(x,y) == 255 and currProcessor.getPixel(x,y) == 255: found = True finalX = x finalY = y break if not found: print "\t\tZ = " + str(z) + ", T = " + str(t) + ", chan " + chanName + ": ERROR: Never found active pixel for seg mask, centroid, roi, area (px): " \ + str(centX) + ", " + str(centY) + ", " + str(roiX) + ", " + str(roiY) + ", " + str(roiWidth) + ", " + str(roiHeight) + ", " + str(area) else: segProcessor.setRoi(roiX, roiY, roiWidth, roiHeight) segProcessor.setColor(row + 1) ff.fill8(finalX,finalY) lut = LutLoader.openLut(cfg.getValue(ELMConfig.lutPath)) segMask.setLut(lut) WindowManager.setTempCurrentImage(segMask); IJ.saveAs('png', os.path.join(outputPath, "SegMask_" + dbgOutDesc + "_particles.png")) startTime = time.time() width = currIP.getWidth(); height = currIP.getHeight(); overlayImage = resultsImage.duplicate() overlayImage.setTitle("Overlay_" + dbgOutDesc + "_particles") if not overlayImage.getType() == ImagePlus.COLOR_RGB: imgConvert = ImageConverter(overlayImage) imgConvert.convertToRGB() overlayProcessor = overlayImage.getProcessor() currProcessor = currIP.getProcessor() if (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.BRIGHTFIELD): maskColor = 0x0000ff00 elif (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.YELLOW): maskColor = 0x000000ff elif (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.RED): maskColor = 0x0000ff00 elif (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.GREEN): maskColor = 0x00ff0000 elif (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.BLUE): maskColor = 0x00ffff00 for x in range(0, width): for y in range(0,height): currPix = currProcessor.getPixel(x,y); if not currPix == 0x00000000: overlayProcessor.putPixel(x, y, maskColor) endTime = time.time() if not 'overlay' in times: times['overlay'] = [] times['overlay'].append(endTime-startTime) WindowManager.setTempCurrentImage(overlayImage); IJ.saveAs('png', os.path.join(outputPath, "Overlay_" + dbgOutDesc + "_particles.png")) #currIP.hide() currIP.close() resultsImage.close() timesAvg = {} for key in times: timeList = times[key] timesAvg[key] = sum(timeList) / len(timeList); print("processImage times " + str(timesAvg)) return stats