Incorrect label assignment after watershed segmentation (Python) - python

I am segmenting some particles using skimage.segmentation.watershed.
This works quite well, and I manage to separate them adecuately (see image).
Image after segmentation.
However, when I use ndi.label to label the different regions, not all the segments get separated, and some are assigned the same label (even if with watershed they were correctly segmented) (image 2, for instance top left particle) after labeling assignment. Notice how particles previously separated are assigned the same label.
I am relatively new in Python and do not know what else I can try to solve this. I would appreciate if you could give me any help. Thanks in advance :)
The code I am using is (I have it in a for loop since I want to automatize the process for the analysis of several images simultaneously):
#import hyperspy for reading directly ser or emd files
import hyperspy.api as hs
#The scikit image library will be used for segmenting the images
from skimage.exposure import histogram
from skimage.color import label2rgb
from skimage import data, io, filters
from skimage.filters import threshold_local, threshold _yen, threshold_li
from skimage.filters import try_all_threshold
from skimage.filters import gaussian
from skimage.feature import peak_local_max
from skimage.feature import canny
from skimage import measure
from skimage.morphology import label
from skimage.morphology import remove_small_objects
from skimage.draw import ellipse
from skimage.measure import label, regionprops, regionprops_table
from skimage.transform import rotate
from skimage.segmentation import watershed
#matplotlib for performing plots
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
#Basic packages (math and statistics)
import pandas as pd
import numpy as np
from scipy import ndimage as ndi
from scipy import stats
import math
import glob
import seaborn as sns
#load data
s=hs.load(folder+'*.emi',stack=True)
#threshold
thresh=threshold_li(s.data)
binary=s>thresh
#Cleaning
cleaned=remove_small_objects(binary.data, min_size=5)
Segmentation itself
#Define variables needed
dist=np.zeros([cleaned.shape[1],cleaned.shape[1]])
water=np.zeros([cleaned.shape[0],cleaned.shape[1],cleaned.shape[1]])
mask=np.zeros(dist.shape, dtype=bool)
markers,_=ndi.label(mask)
water_particles=np.zeros([cleaned.shape[0],cleaned.shape[1],cleaned.shape[1]])
eq_diam_total=np.array([])
#for loop for segmenting all the images using watershed.
#I will use the commented "for i in range (cleaned.shape[0])"
#once I manage to solve the segmentation issue:
#for i in range (cleaned.shape[0]):
for i in range(2,3):
dist = ndi.distance_transform_edt(cleaned[i,:,:]) #make distance map
maxima=peak_local_max(gaussian(dist, sigma=1.5),threshold_rel=None,
min_distance=5) # find local maxima
print('maxima',maxima.shape)
mask[tuple(maxima.T)]=True
markers,_=ndi.label(mask)
print('markers',markers.shape)
#segment
water[i,:,:]=watershed(-dist, markers,mask=cleaned[i,:,:])
print('water', water.shape)
#label each particle
water_particles[i,:,:], water_labels = ndi.label(water[i,:,:])
print('water_particles',water_particles.shape)
print('water_labels',water_labels)
Plot after segmentation
%matplotlib inline
from skimage import color
fig,axes=plt.subplots(1, 2, sharey=True)
axes[0].imshow(color.label2rgb(water[i,:,:]))
axes[0].axis('off')
axes[0].set_title('After watershed segmentation')
axes[1].imshow(color.label2rgb(water_particles[i,:,:]))
axes[1].axis('off')
axes[1].set_title('After label')

The output of skimage.segmentation.watershed is a labeled image, it can go directly into the measurement function (regionprops).
Also, that watershed function will take all local minima as markers, you don’t need to find these yourself. Simplified code:
from scipy import ndimage as ndi
from skimage.segmentation import watershed
# ...
dist = ndi.distance_transform_edt(cleaned[i,:,:]) #make distance map
water_particles[i,:,:] = watershed(-dist, markers,mask=cleaned[i,:,:])
If you want to receive an image you can label yourself (for whatever reason), then add the watershed_line=True argument. This will keep a separation between each region (basin) so that the labeling algorithm can identify them.

Related

Computing fft2 of an image in Python

I am experimenting with Fourier transformations and the built-in NumPy.fft library. I was trying to see the difference between computing just fft2 of an image and fftshift on fft2 of an image. But for some reason, I am not getting the results that I was expecting. I have tried changing images as well but regardless of what I use, I get the same results as below. If someone could help me out here, it would be awesome. This is the code I used:
import numpy as np
import cv2
import matplotlib.pyplot as plt
from scipy import ndimage, fftpack
light = cv2.imread("go_light.jpeg")
dark = cv2.imread("go_dark.jpeg")
g_img = cv2.cvtColor(dark, cv2.COLOR_BGR2GRAY)
di = (np.abs((np.fft.fft2(g_img))))
dm = np.abs(np.fft.fftshift(np.fft.fft2(g_img)))
plt.figure(figsize=(6.4*5, 4.8*5), constrained_layout=False)
plt.subplot(151), plt.imshow(di, "gray"), plt.title("fft");
plt.subplot(152), plt.imshow(dm, "gray"), plt.title("fftshift");
plt.show()
di and dm are floating point values. Matplotlib can't do that. First, try di.astype(np.int8). However, many of the values are out of range. You may need to scale the array.

matplotlib does not show the image

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
i = Image.open('images/dot.png')
iar = np.asarray(i)
plt.imshow(iar)
plt.show()
I have the image called dot.png in the same directory but it is not working.
When I start the program no errors detected. It runs fine. But the matplotlib tool not working.
The window look like this:

Matplotlib plot with AGG backend not working

Is there something I am missing? I would like to run software without having to go install a monitor on a virtual machine and hit a key every time it processes another image. The concept of forcing the GUI dependence on the user seems rather odd... Why assume a physical monitor?
I have jumped through the hoops for the "AGG" backend to remove the X server dependence, but this changes nothing. How can I force it to not try and draw to a non-existent display?
import cv2
import numpy as np
import os
from decimal import Decimal
from PIL import Image
from PIL.ExifTags import TAGS
import time
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
chans = cv2.split(img)
colors = ("b", "g", "r")
plt.figure()
#plt.axis('off')
features = []
# loop over the image channels
for (chan, color) in zip(chans, colors):
chist = cv2.calcHist([chan], [0], None, [256], [0, 256])
features.extend(chist)
# plot the histogram
plt.plot(chist, color = color)
plt.xlim([0, 256])
plt.savefig('histchart.png', bbox_inches=0)
No matter what I do, it still forces that stupid GUI dependance. Is there any way to totally and completely remove the dependency?

module getting stuck on show() in ipython

Hello I created a module in the ipython text editor and then called it in the ipython notebook and it freezes when I call show() from matplotlib. I am running on a surface pro windows 10. I have checked for answers and I found that using import matplotlib as mpl
mpl.use('TkAgg')
in the beginning of my module worked the first time and then every time I tried to run after it has killed my kernel. Here is my module which is called Take_Home.py:
import numpy as np
import matplotlib as mpl
import pdb
#mpl.use('TkAgg')
import matplotlib.pyplot as plt
import matplotlib.mlab as ml
def statistics(array,bin_size):
#calculate mean and standard deviation of array
mean=np.mean(array)
std=np.std(array)
#get the gaussian fit of the data
gaussian=ml.normpdf(array,mean,std)
#plot the normalized histogram
plt.hist(array,bins=np.arange(np.min(array), np.max(array) + bin_size, bin_size),normed=True)
#plot the gaussian function over the histogram
plt.plot(array,gaussian,'.k')
#this attempts to show the plot but doesn't work
plt.show()
#saves the plot to a PDF
plt.savefig('Statistics.pdf')
and here is the ipython notebook that calls the module:
import Take_Home as th
import numpy as np
import matplotlib.pyplot as plt
#initialize an array of 1000 elements and set them all to 1
rd=np.arange(0,1000)
rd[:]=1
#change the array to have all random numbers with a std of 2 and a mean of 1
rd=rd*(2*np.random.randn(1,1000)+1)
#transpose it because the error message said so
rd=np.transpose(rd)
#declare bin size
binsize=0.2
#use method inside module
th.statistics(rd,binsize)
I just need to show the plot and I don't know why it's working any help would be much appreciated thank you!

Python hangs when I call imshow

from pylab import *
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import random
import time
from scipy.misc import imread
from scipy.misc import imresize
import matplotlib.image as mpimg
import os
# General setup
matplotlib
#gray()
# 2D Array
a = array([[4,5,6], [1,2,3]])
# shape of matrix in format n x m
a.shape
# Read in an image
i = imread('test.jpg')
if __name__ == "__main__":
imshow(i) # HANGS ON OSX
plt.show()
This code runs completely fine on my windows machine, but on MacOSX it hangs whenever I call imshow (even on a trivial array), the image window pops up but it hangs. I am using pycharm.
Anybody know why this is? Am i doing something wrong?

Categories

Resources