0

I have the following problem. In the image below, a so-called teardrop-like DNA is shown. In red, a trace yielded by skimage.morphology.skeletonize is shown. The bright yellow region is a molecular complex called "Streptavidin", which I need to identify. In essence, my problem revolves around two steps:

  1. I need to identify the brightest spot in the image. For that, I apply a Gaussian filter to the image and subsequently try a thresholding algorithm (for example, skimage.filters.threshold_yen). Then, I use skimage.measure.regionprops.centroid to identify the Streptavidin. However, this approach is prone to errors: Since I need not only identify this single image, but do the same for other images as well, I cannot use a global threshold. For some images, Yen Thresholding works fine, for some it doesn't yield a result at all. So my question here would be: Is there an alternative way to identify the centroid of the Streptavidin complex, given that the various image display different intenstity values, i.e. a global approach is difficult to implement?
  1. I then want to delete all trace points (in red) that lie within the Streptavidin complex. Here, I wanted to use a boolean mask representing the Streptavidin complex and then tell the program to delete all points that lie within the complex. But again, this is very dependent on the actual boolean mask I get from thresholding, so I would like to think of another way to do it.

Overall, here is my code for reference:

        img_gaussian = filters.gaussian(mol_filtered, sigma=1.)

        # Get threshold (use yen threshold)
        if self.anal_pars['strep_thresh'] is None:
            thresh = filters.threshold_yen(img_gaussian)
            
            # If Yen thresholding fails:
            if thresh < 0.8:
                thresh = filters.threshold_minimum(img_gaussian)
        else:
            thresh = self.anal_pars['strep_thresh']
        
        # Split the image according to threshold selected
        img_bw = copy.deepcopy(img_gaussian)
        img_bw[img_bw < thresh] = 0
        img_bw[img_bw != 0] = 1
         
        # Label the regions that lie above the threshold
        img_labelled = morphology.label(img_bw)
        
        # Check if the thresholding yielded more than one area:
        if img_labelled.max() != 1:
            
             # Remove possible artefacts (happens for Yen filter)
             img_bw = morphology.remove_small_objects(img_bw.astype(bool))
             img_labelled = morphology.label(img_bw) # relabel image
        
        for region in measure.regionprops(img_labelled):
            strep_index = region.centroid
            mol_pars['strep_index'] = strep_index
        
        # Add the streptavidin area to the mol_pars dictionary
        img_strep = copy.deepcopy(img_bw)
        mol_pars['img_strep'] = img_strep

So this seems quite messy and inefficient, there surely is a faster way to do it? Thanks for your helpThe image. The yellow bright region corresponds to a Streptavidin complex. The original, unfiltered image.

LionCereals
  • 171
  • 1
  • 10
  • Just run a simple gaussian filter and threshold. You have plenty of snr. Maybe just threshold directly from the histogram. – Mad Physicist Dec 12 '20 at 09:39
  • You have shared a *picture* of your image with axes, annotations and presumably a colourmap, which is fine and good, but can you additionally provide the pure, unannotated (presumably greyscale) image too please? – Mark Setchell Dec 12 '20 at 09:39
  • Hm, I already applied a gaussian filter and tried thresholding. However, at times this doesn't yield a result, especially for images where the intensities not as clearly aligned. – LionCereals Dec 12 '20 at 09:45
  • For example, when I do what @MadPhysicist suggested, the centroid is not exactly in the middle of the bright region, at least I would infer that from the image. – LionCereals Dec 12 '20 at 09:48
  • You want just the dot without the chain? In that case, median filter to remove shot noise, large median subtraction to remove unevenness in background, then gauss kernel to make the peak more prominent. Find the max of the image, and do a 2D gaussian fit on that region. Set anything around 3-sigma to zero. I'll post a numpy+scipy example if no one else has an answer by Monday. – Mad Physicist Dec 12 '20 at 09:50
  • What do you mean by gaussian fit? Up to "find the max of the image", I can follow. – LionCereals Dec 12 '20 at 09:54
  • Here's a good example: https://stackoverflow.com/q/21566379/2988730. There are some clever ways to linearize the problem, but you don't need to worry about optimization right now. Doing a fit will allow you to characterize the peak and block out everything else. – Mad Physicist Dec 12 '20 at 09:55
  • Okay, thanks so far. A few clarifications: By finding the max of the image, you mean just applying ```np.max```? And by "median subtraction", you mean what exactly? – LionCereals Dec 12 '20 at 09:58
  • Could you share your actual greyscale image please - without artificial colouring and without axes? https://scikit-image.org/docs/dev/api/skimage.io.html#skimage.io.imsave – Mark Setchell Dec 12 '20 at 10:00
  • @Mark Setchell. Well, this image is just done by ```plt.imshow(img_name)```. So there is no colormap used by me at this point. Additionally, this is just a zoomed in version, the whole image contains much more of those strands. – LionCereals Dec 12 '20 at 10:08
  • `plt.imshow()` uses the *"viridis"* colourmap. – Mark Setchell Dec 12 '20 at 10:17

0 Answers0