Extracting object names from masks within the pipeline

First, let me thank for all the great work that you guys are doing on CP. I absolutely love it and I became a self-appointed CP evangelist in my group :smiley:

Here’s my question. I’ve got two masks from MetaMorph (I use it to identify neurite outgrowth per cell, a functionality that CP lacks at the moment, I believe):

  1. neurite mask with shades of gray that correspond to object numbers in MetaMorph xls file,
  2. nuclear mask, which is just binary.

In CP, I measure fluorescence intensity in nuclei from other tifs with appropriate staining. In order to measure nuclear fluorescence, I need the nuclear mask with annotated objects. Needless to say, I need to keep the same object annotations. I simply multiply the neurite mask (which already contains object numbering) with the binary nuclear mask. The problem is, that when I do it in CP, I obtain a new image. How can I extract object information within the pipeline from that image? It’s possible to do that at the beginning in NamesAndTypes when I load an already saved image and load it as Objects. But I couldn’t achieve that without saving the multiplied image and re-loading it.

Another similar issue concerns retaining image annotations after applying a filter. In CP, I use the annotated neurite mask, apply a median filter to get rid of neurites and just have an annotated mask with cell bodies. Now I’d like to run shape&size module on that new mask. But again, since the result of filtering is a new image, how can I extract image numbers from there, within the pipeline?


Hi M.,

I’m mostly clear on what you want to do, but I would be more clear if you would post an example set of masks and image to measure, and possibly a CP pipeline attempt (even failed). Can you?

Just some guesses on my part – see the attached pipeline:
(1) Yes, load your “Label matrix”, i.e. your objects which are hopefully object pixels labeled as monotonically increasing grayscale levels (again, post, and we can confirm what MetaMorph gives you), as ‘Objects’ in the Images module. This will preserve the object numbers. I have done this in the attached pipeline assuming an input label matrix.
(2) You could then simply DisplayDataOnImage and select the ObjectNumber to at least see the object number displayed. I think this will preserve the object number as oded in your input label matrix, but I am not totally sure.
(3) ExportToSpreadsheet also saves object info – look in the exported CSV labeled with the object’s name, and the location of the object centroid and the ObjectNumber, etc are listed. At the very least you could match these to your previously obtained object locations.

Hope that helps to get you started, but posting examples would help.
testLabelMatrix.cppipe (4.76 KB)

Hi David,
many thanks for your quick reply. I’m attaching a super simple pipeline with one mask (cropped, because it’s a huge montage) where levels of gray encode object numbers. What I’m trying to achieve is to run a median filter on that mask, to get rid of small foci, and to run MeasureObjectSizeShape module on that filtered image. The point is that I would need something like ConvertImageToObjects module which CP doesn’t seem to have :wink:


testObjectNames.cpproj (88.5 KB)

Ah, I see now – indeed that is an annoying conundrum! But I may have a workaround. See my attached pipeline.

The idea is to convert the input objects into CP’s native object format, by shrinking them a minimal amount to separate touching objects, convert to an image, and then use CP’s best analog to a “ConvertImageToObject”, which are the identify*Objects modules.

Pipeline notes:
(1) ExpandOrShrinkObjects - Basically, I shrink all the objects (i.e. MetaMorph’s label matrix) by a single pixel. This is a hedge which I hope you can live with, but it is necessary to separate touching objects.
(2) ConvertObjectsToImage - make grayscale image from the newly shrunk objects
(3) IdentifyPrimaryObjects - uses the most simple methods possible, and note that I put in a manual threshold of 0.001 – note that this should be lower than your lowest grayscale value, likely a value < 1/(# objects). Check that all objects are getting segmented here
(4) Measure* - measure whatever you want

I would say, though, that I would every attempt at using an entirely-CP method. I have made quite a few neurite measuring pipelines and even though we don’t have a Neuron Toolbox yet (though there is of course MeasureNeurons to measure branching), using Identify Primary and IdentifySecondary with appropriate settings, as well as good pre-processing, works quite well in many cases. But we’re not going to force that method on anybody and hopefully the above works for you.

testObjectNames_DL.cppipe (6.85 KB)

Hi David,
many thanks for your assistance so far. Yes, the pipeline you provided does the job, although I’d still run it through median filter to make sure that shape properties are calculated from cell bodies and not cells with protrusions. Ultimately, I’d like to compare neurite length (from MetaMorph) with cell diameter or Feret diameter. There’s one catch, though. The ID’s from IdentifyPrimaryObjects are different from the ID’s encoded as grey shades from MetaMorph. And I need them to stay the same in order to have neurites per cell (from MetaMorph) and other properties such as shape, size, fluorescence intensity from other channels (calculated in CP), for the exact same cells.

I’d definitely want to do everything within CellProfiler. However, based on what I’ve learnt about CP so far, it’s not possible to obtain the number of neurites per cell and the stats of those neurites, such as max, min, total neurite length. Or is it?


MeasureNeurons does not yet output the length, unfortunately, though it does measure the number of neurites and branches (“NumberTrunks”, etc). Note, you can get the length measure indirectly via other modules (Morph>Skeletonize, then measure intensity of the binary which is the same as length).

A for the ID mismatch, I think you’d have to output the MM ID’s as a CSV somehow, and then use CP’s Metadata to import those ID’s and associate them by their X/Y locations. Maybe an even more unlikely hack, but you might even to be able to use the grayscale value of the MM label matrix as the Object ID (is it meaningful?) and use the intensity measure in CP to relate them! A pain, but it might work :confused: