I would like to seperate the fringes (the red curved lines) that I have calculated with scipy findpeaks how can I achive it. I would like to seperate them and store in the text file.
import numpy as np
from scipy.signal import find_peaks
import matplotlib.pyplot as plt
X = np.load('X.npy')
Y = np.load('Y.npy')
P_new = np.load('P_new.npy')
# Example data: Replace with your actual data
T = np.real(P_new) # Simulating a 2D matrix
# Plot the original image
plt.figure()
plt.imshow(T, cmap='jet', aspect='auto')
plt.colorbar()
plt.title('Original Image')
plt.show()
# Peak detection parameters
min_peak_dist = 3 # Minimum distance between peaks
min_peak_h = 3e-5 # Minimum peak height
x_coords = []
y_coords = []
# Process all rows from top to bottom
for k in range(T.shape[0]):
tex = T[k, :]
peaks, _ = find_peaks(tex, distance=min_peak_dist, height=min_peak_h)
if peaks.size > 0:
x_coords.extend(X[k, peaks])
y_coords.extend(Y[k, peaks])
# Plot detected peaks
plt.figure()
plt.scatter(x_coords, y_coords, color='r', s=2) # 's' controls marker size
plt.xlabel('X Coordinate')
plt.ylabel('Y Coordinate')
plt.title('Detected Fringes in Real-World Coordinates')
plt.colorbar()
plt.show()
Want I want see is just seperate fringes like here:
previously I could do it with cv2 method contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) but this is from finding the edges which is not very rigorous for my case as with finding peaks of the actual data.
Can someone help with this? Thanks
I had reasonable success using HDBSCAN
.
I first ran find_peaks
to find peaks along y (rather than along x) - these are the black lines. I then clipped the image to within the blue square, and clustered the points using HDBSCAN. The final clusterings are coloured.
To plot a particular cluster, you could use:
view_cluster = 20
plt.figure(figsize=(3, 5))
plt.scatter(*clustered[view_cluster].T, marker='.', s=1)
plt.xlabel('x')
plt.ylabel('y')
plt.title(f'Fringe {view_cluster}')
plt.grid(linestyle=':')
Load data and preprocess:
import numpy as np
from scipy.signal import find_peaks
import matplotlib.pyplot as plt
from matplotlib.patheffects import withTickedStroke
#
# Example data: Replace with your actual data
#
X_orig = np.load('X.npy')
Y_orig = np.load('Y.npy')
P_new = np.load('P_new.npy')
n_rows, n_cols = P_new.shape
T = np.real(P_new) # Simulating a 2D matrix
#Resample X and Y to match resolution of P_new
# NB. I use the min/max values for simplicity
x_axis = np.linspace(X_orig.min(), X_orig.max(), num=n_cols)
y_axis = np.linspace(Y_orig.min(), Y_orig.max(), num=n_rows)
X_grid, Y_grid = np.meshgrid(x_axis, y_axis)
# Peak detection parameters
min_peak_dist = 3 # Minimum distance between peaks
min_peak_h = 3e-5 # Minimum peak height
coords = []
# Process all cols (x axis)
for col_ix in range(n_cols):
peaks, _ = find_peaks(T[:, col_ix], distance=min_peak_dist, height=min_peak_h)
if not len(peaks):
continue
x_coord = x_axis[col_ix]
peaks_y = y_axis[peaks]
coords.extend([(x_coord, peak_y) for peak_y in peaks_y])
coords = np.array(coords)
x_coords, y_coords = coords.T
#
#Clip unwanted regions
#
ignore_left_of = 5
ignore_below = 25
# ignore_shorter_than = 10
coords_clipped = coords[(x_coords > ignore_left_of) & (y_coords > ignore_below)]
Cluster and visualise:
#
# HDBSCAN
#
from sklearn.cluster import HDBSCAN
coord_labels = HDBSCAN().fit_predict(coords_clipped)
clustered = [
coords_clipped[coord_labels==cluster_id]
for cluster_id in np.unique(coord_labels)
]
#
# Visualise
#
plt.figure()
#Original image
plt.matshow(
T, extent=[x_axis.min(), x_axis.max(), y_axis.min(), y_axis.max()],
cmap='Greys_r', origin='lower', vmax=5e-4, aspect='auto'
)
plt.gcf().set_size_inches(12, 6)
plt.colorbar(extend='both')
#Detected peaks
plt.scatter(x_coords, y_coords, color='black', marker='.', s=0.2, alpha=0.4)
# #Clip regions
plt.axvline(ignore_left_of, path_effects=[withTickedStroke(angle=135)])
plt.axhline(ignore_below, path_effects=[withTickedStroke(angle=-135)])
#Clusters
clustered = sorted(clustered, key=lambda members: members[:, 1].min())
for cluster_members in clustered:
plt.plot(*cluster_members[::30].T, alpha=0.2, zorder=0, lw=8)
#Formatting
plt.xlabel('x')
plt.ylabel('y')
plt.show()