Computing fft2 of an image in Python - 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.

Related

Incorrect label assignment after watershed segmentation (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.

Transform some kind of exponential distribution into normal distribution

I have the following exponential distribution, generated with the following code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random
np.random.seed(1)
tags_ratio = np.random.exponential(1/25, 1000)
plt.hist(tags_ratio, range=(0, 1), bins=100)
plt.show()
I'm trying to transform my data, resides in tags_ratio into normal distribution, but with no success.
Tried with the log function and square functions. it given decent results. But I'm interesting in more ideas. Maybe more sophisticated.
You can try to see if this helps:
from scipy.stats import boxcox
tags_ratio = boxcox(tags_ratio, 0.3)
plt.hist(tags_ratio)
plt.show()
result:
for more explanations and theory about Box-Cox click here.

smoothing curves with no local extremums using numpy

I am trying to get a smooth curve for my data points. Say (lin_space,rms) are my ordered pairs that I need to plot. For the following code-
spl=UnivariateSpline(lin_space,rms)
x=np.arange(0,1001,0.5)
plt.plot(lin_space,rms,'k.')
plt.plot(lin_space,spl(lin_space),'b-')
plt.plot(x,np.sqrt(x),'r-')
After smoothing with UnivariateSpline I am getting the blue line whereas I need my plots like the red one like shown (with no local extremums)
You'll want a more limited class of models.
One option, for the data that you have shown, is to do least squares with a square-root function. That should produce good results.
A running average will be smooth(er), depending on how you weight the terms.
A Gaussian Process regression with an RBF + WhiteNoise kernel might be worth checking into, with appropriate a priori bounds on the length scale of the RBF kernel. OTOH, your residuals aren't normally distributed, so this model may not work as well for values toward the edges.
Note: If you specifically want a function with no local extrema, you need to select a class of models that has that property. e.g. fitting a square root function.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import sklearn.linear_model
mpl.rcParams['figure.figsize'] = (18,16)
WINDOW=30
def ma(signal, window=30):
return sum([signal[i:-window+i] for i in range(window)])/window
X=np.linspace(0,1000,1000)
Y=np.sqrt(X) + np.log(np.log(X+np.e))*np.random.normal(0,1,X.shape)
sqrt_model_X = np.sqrt(X)
model = sklearn.linear_model.LinearRegression()
model.fit(sqrt_model_X.reshape((-1,1)),Y.reshape((-1,1)))
plt.scatter(X,Y,c='b',marker='.',s=5)
plt.plot(X,np.sqrt(X),'r-')
plt.plot(X[WINDOW:],ma(Y,window=WINDOW),'g-.')
plt.plot(X,model.predict(sqrt_model_X.reshape((-1,1))),'k--')
plt.show()

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!

FFT in SimpleCV?

I'm exploring SimpleCV as an imaging library in Python, and it seems pretty good. However, I'm stumped at how to perform an FFT on an image within SimpleCV. It seems I'd have to convert to an numpy array first, and then use the numpy facilities:
import SimpleCV as SV
im = Image('image.png')
img = im.getGrayNumpy()
imf = np.fft.fftshift(np.fft.fft2(img))
plt.imshow(log(abs(imf)+1),cmap=cm.gray)
Or maybe this is the best way? And of course if I want to convert the log of the fft spectrum into a SimpleCV image for later use, that's another issue...
You can bring numpy matrices back to SimpleCV using the Image() constructor:
import scipy
import numpy as np
import SimpleCV as scv
cam = scv.Camera()
disp = scv.Display()
while disp.isNotDone():
current = cam.getImage().resize(w=768)
matrix = current.getGrayNumpy()
spectrum = np.abs(np.log(np.fft.fftshift(np.fft.fft2(matrix))))
spectrum *= 255 / spectrum.max()
scv.Image(spectrum).show()
if disp.mouseLeft:
break

Categories

Resources