Identifying white regions in tissue slides


#1

Hi,

I’ve created a pipeline for identifying any white colored regions and apply them as masks so as to be able to reduce the area of non-tissue that is being analysed.

I’ve tried using Unmix Colours and had pretty good results, but have since opted for ColorToGray with the subsequent step being ImageMath in order to increase the image contrast, followed by an additional ImageMath to rescale the intensity levels.

I then use IdentifyPrimaryObject in order to locate all white regions, and output this image a mask that is used for downstream analysis. It works very well overall; however, for some reasons it counts some non-white regions as white. I’ve attached an example image where a couple of cells that are strongly non-white, are included in the masked region.

Any thoughts on how to improve the pipeline? I’ve tried using both .jpeg, .tif, but to no avail.

I’ve marked two cells with red squares in the attached image. These are cells that are are incorrectly included in the white region (there may of course be more like this).

WhiteArea.cppipe (9.3 KB)


#2

Hi,

In IdentifyPrimaryObjects, at the “filling the holes” box, you should not let it do anything hole filling operation:

The result then becomes:

Is that what you’re looking for?


#3

Thank you very much, that definitely improved the results. However, I’m getting issues with the number of nuclei not being counted correctly when I apply these steps as a pre-processing set of moduels when I compare it to the same pipeline without pre-processing (white-masking). Some nuclei are being differently declumped, while others are being excluded, and there is no masking in these regions as far as I can tell.

Any thoughts?


#4

I actually don’t think making white mask is a good move, since it involved many image alteration and the removed area is not that much.

Have you tried using the UmixColors with 2 colors ?

Now the nuclei are very bright for you to identify them:


#5

I actually use UnmixColors downstream after producing the mask, which is why I’m confused. I produce the masked image and use it as input for UnmixColors. As far as I can tell, there aren’t any nuclei blocked out after masking, which you helped set up correctly.

Didn’t include the rest of the pipeline as the initial problem was that masking caused some nuclei to be masked as well, which I assumed would no longer be the problem after I corrected it as you instructed.

Also, in some images I have as much as up to 50% white regions, which I really want to be able to exclude from analysis.


#6

Ah I see.

So back to address the “excluded” and “clumped” nuclei, the 3 parameters you may consider to tune are:

  • Size of the objects.
  • “Automatically calculate size of smoothing filter for declumping” (uncheck & enter number manually)
  • “Automatically calculate minimum allowed distance between local maxima” (uncheck & enter number manually)

All these three values often affect each others, so you may have to experiment a bit.
Other than that, sorry analyzing histology images is hard : (


#7

Yeah, unfortunately histology isn’t the easiest thing.

I just tried a different approach, where I use ConvertObjectsToImage --> ImageMath to invert --> use the raw image as input in UnMix Colors --> MaskImage (ConvertObjectsToImage used as Image Mask) on the raw input image --> IdentifyPrimaryObjects for nuclei, and I still get declumping issues, even though I have altered absolutely nothing on the raw input image beyond adding a mask on top of it (which visibly does not interfere with said nuclei).

Am I missing something? I also quantify the DAB-staining, but for some reason the DAB-quantity remains completely unaffected while the hematoxylin (nucleic) stain is affected. .


#8

Since the nuclei size in your image is small, can you try to decrease both:

  • Size of the objects.
  • “Automatically calculate size of smoothing filter for declumping” (uncheck & enter number manually)
  • “Automatically calculate minimum allowed distance between local maxima” (uncheck & enter number manually)

To something like 15 / 7/ 5 and declumping using “Intensity” instead of “Shape”

In second question, I don’t quite get it. But you can try to combine DAB+ Eosin/ or Hematoxylin+ Eosin, instead of DAB+Hematoxylin and see if it helps.


#9

Everything downstream of my masking procedure is a pipeline that was not created by me. I’m trying to integrate my pipeline into it without altering the pre-existing basis for identification of hematoxylin-stained nuclei and DAB-stained regions.

I’ve uploaded two pipelines where I tried a slightly different approach to show you what I mean:

1. In ConvertObjectsToImage.cppipe I mask the input for UnmixColors using ConvertObjectsToImage
2. MaskImage
3. Running the downstream pipeline as usual.

1. In MaskImage.cppipe I mask the input for UnmixColors using IdentifyPrimaryObjects (white regions)
2. MaskImage, before proceeding as normal.

I both cases I see a reduction of counted nuclei, when comparing to running the pipeline from UnmixColors without using a masked image, but instead using the normal (unaltered image) without any masking procedure. In this case, I always end up with 1194 nuclei.

Whitemasking_ConvertObjectsToImage.cppipe (18.6 KB)
Whitemasking_MaskImage.cppipe (18.2 KB)


#10

Hi there,

So I played with the two pipelines and don’t think the mask would really help you to get the segmentation of the nuclei right. It may give a lot of false positive nuclei that you need to filter out later.

The reason is probably that after masking, we’d introduce additional shade of gray (total white for background), confusing the segmentation algorithm.

A simple UnmixColors + immediate segmentation with MoG could be enough to get the bright nuclei
(relatively same region with the above)

pipeline: White.cpproj (669.0 KB)


Alternatively, you can consider using Ilastik coupling with CellProfiler, there’re quite a few discussions in the forum you can find easily if you’re interested.

Hope that helps


#11

Thanks a lot, that might explain it. However, I was under the impression that the program somehow would “take into consideration” the fact that it’s masking and thus completely exclude it from analysis. If masking impacts the end results, how would you ever use it in a “correct” way?

I’ll try out Ilastik, but I’ve read that there has been issue with CP not working well with Ilastik. Is this still the case?


#12

Ah, to clarify: you should download and use newest version of ilastik as separate program, don’t use the integrated ilastik inside CellProfiler, it’s an old version of ilastik.

Good luck, have fun.


#13

However, I was under the impression that the program somehow would “take into consideration” the fact that it’s masking and thus completely exclude it from analysis. If masking impacts the end results, how would you ever use it in a “correct” way?

If an image is masked those regions will be ignored, but that will almost certainly impact the end results; most threshold calculation methods are based on looking at the intensity histogram of the pixels in the image. If you’ve therefore masked out a bunch of the pixels and told CP to ignore them, you’ll have a different histogram, which will lead to a different threshold being calculated. Does that make sense conceptually?

I haven’t played with your pipeline or your images, so I can’t speak to the specific value of masking vs not in them, but if @Minh says he’s getting good isolation of the nuclei just with UnmixColors without needing to mask, it makes sense to me to just start with that very simple approach. The more complications and steps that you add, the more parameters you’ll have to keep tuned for each new batch of images and the more potential places for things to go wrong.


#14

Thank you for your fast reply. That definitely makes sense.

However, due to a number of factors, we have lots of non-tissue (basically nothing) being included in our analysis, leading to false negative when calculating the ratio of area stained. Therefore, the point of the masking is to simply function as a “pre-processing” step to reduce non-tissue area being analysed, and should not interfere in any way with the actual analysis as I still input the raw image into UnmixColors and then run my regular pipeline.
As a matter of fact, I’ve set up the pipeline in such a way that all masking is done separately upstream from the main pipeline as I was quite happy with the identification of nuclei & DAB. It was never my intention at all to alter the identification of nuclei or DAB, that was just an unexpected effect.

Of course, reducing the non-tissue from the very get-go would be be the ideal solution as we wouldn’t have problem at all then. Unfortunately, this can’t be done so I’m trying to mitigate the effects in the image analysis.

Do you think this could be considered for future development? To include it as an option that downstream modules will use the raw image to produce the histogram, regardless of Masking?


#15

Therefore, the point of the masking is to simply function as a “pre-processing” step to reduce non-tissue area being analysed, and should not interfere in any way with the actual analysis as I still input the raw image into UnmixColors and then run my regular pipeline.

No, actually, both pipelines you uploaded do UnmixColors on ‘Mask’/‘Masked’ (what you called your masked image), not on ‘raw’, so everything I said above applies. Set UnmixColors to process ‘raw’ again, and you’ll get your original analysis back.

If the only reason you’re trying to find the white parts is to measure their total area (and therefore figure out what the area of tissue is in the image), there’s no reason to apply them as a mask at all in the pipeline. Simply measure the total area of the “whitemask” objects (as you’re already doing in your MeasureImageAreaOccupied module), then you can use CalculateMath to subtract the AreaOccupied_whitemask from TotalImageArea_whitemask to get a measurement you could call ‘TotalTissueArea’.


#16

My bad, in that case I must admit I uploaded the wrong ones. I have of course tried by used UnmixColors with raw, and using MaskImage afterwards, but prior to, using IdentifyPrimaryObjects, without any change in the results. Of course, I may as well be doing it wrong, but I feel I’ve tried several different approaches (masking prior to identification, after, etc) without any change.

I’ve also already constructed a pipeline with CalculateMath, exactly as you describe. However, without going into the details of the actual research, it would be beneficial to get as easy numbers as possible in the spreadsheet (i.e. all white regions never to be analysed in the first place).


#17

Unless you’re saying the masking improves the segmentation (and since you seem to be explicitly saying it makes the segmentation worse I don’t think that’s the case), I still don’t understand why you’re doing it at all. Masking is typically done to improve the segmentation, there’s no point to it if it’s not doing that. If I’m missing something, please explain what.

I’ve also already constructed a pipeline with CalculateMath, exactly as you describe. However, without going into the details of the actual research, it would be beneficial to get as easy numbers as possible in the spreadsheet (i.e. all white regions never to be analysed in the first place).

You can set in ExportToSpreadsheet exactly which values to write out, so you could tell it just to write out your calculated ‘TotalTissueArea’ (or whatever you name it) but not the original things from MeasureImageAreaOccupied that were used to create the calculation.


#18

I greatly appreciate your help and I really love your program. But I am by no means an expert, I’m just leaning by doing, tinkering with the program the best I can, and if I’m using Masking (or anything else) in the completely wrong way then now I know. I’m a biologist, not a software engineer so you’ll have to bear with me…

My reasoning behind masking the white areas was that some of my tissues contain up to 50% non-tissue, which again, is completely out of my control. I would love to have intact tissues, but I don’t. We’re using the quantified DAB-area and expressing as the ratio of total area that has been analysed. The problem is when you have 50% of that area consisting of nothing, then that does not reflect the true situation. Again, it was never my intention to alter segmentation, I was unaware that masking would have such an impact on it.

If this can’t be achieved the way I imagined, then of course there’s nothing anyone can do anything about it. I’ll just use the CalculateMath method that I had planned as backup.


#19

It’s not a problem- I definitely remember what it was like to learn all this stuff (I’m also a biologist!) and there’s a lot to take in! :smile:

I understand what you’re saying about not having intact tissues and why you’d want to make sure you’re only calculating the % stained of how much tissue is in the image rather than % stained in every pixel, since not every pixel will have tissue. You’re right that a priori masking out the empty areas is a good idea in theory, but since you’re getting good identification of the objects without it (which is after all what you really care about) there’s no need to try to push it since it’s not working out in practice. As long as you can accurately identify the parts of the image that you care about (white areas, nuclei, dab spots, etc), you can use the measurement and calculation tools to come up with the ratios etc that you need.

Good luck!


#20

Ah, then you are sympathetic of my struggles :slight_smile:

You are right, having the complete raw data is course superior to all other methods.

Just one last question; let’s say your interest in just the area of DAB-staining without analysing the nuclei at all, would there be any effect to the amount of DAB quantify? Granted that you’ve found the appropriate threshold levels. I noticed that the number of DAB regions were not affected at all in my analysis, only the number of nuclei due to segmentation.