你已经派生过 gpr3dattribute
镜像自地址
https://gitee.com/sduem/gpr3dattribute.git
已同步 2025-09-19 01:13:49 +08:00
130 行
4.8 KiB
Python
130 行
4.8 KiB
Python
import segyio
|
|
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
from scipy.signal import tukey, hilbert
|
|
import mig_fk # Custom FK migration module
|
|
|
|
|
|
def write_to_dat_append(data, x, y, file):
|
|
"""
|
|
Append 3D point cloud data to a .dat file in the format (x, y, z, value)
|
|
|
|
Parameters:
|
|
data (2D array): Processed data to export
|
|
x (float): X offset for the current profile
|
|
y (float): Y offset for the current profile
|
|
file (file object): Output file opened in write/append mode
|
|
"""
|
|
nz, nx = data.shape
|
|
x_coords = np.linspace(x + 8, 213, nx)
|
|
z_coords = np.linspace(0, 85, nz)
|
|
|
|
for i in range(nz):
|
|
for j in range(nx):
|
|
file.write(f"{x_coords[j]} {y + 3} {z_coords[i]} {data[i, j]}\n")
|
|
|
|
|
|
def sliding_window_mean(data, window_size):
|
|
"""
|
|
Compute local background mean using a sliding window
|
|
|
|
Parameters:
|
|
data (2D array): Input data of shape (n_traces, n_samples)
|
|
window_size (int): Size of the sliding window (must be odd)
|
|
|
|
Returns:
|
|
2D array: Local mean values with the same shape as input
|
|
"""
|
|
if window_size % 2 == 0:
|
|
raise ValueError("Window size must be an odd number.")
|
|
|
|
half_window = window_size // 2
|
|
padded_data = np.pad(data, ((0, 0), (half_window, half_window)), mode='reflect')
|
|
local_means = np.empty_like(data)
|
|
|
|
for i in range(data.shape[1]):
|
|
local_means[:, i] = np.mean(padded_data[:, i:i + window_size], axis=1)
|
|
|
|
return local_means
|
|
|
|
|
|
def taper_field(in_array):
|
|
"""
|
|
Apply a Tukey window-based taper to suppress edge noise
|
|
|
|
Parameters:
|
|
in_array (1D array): Input radar trace
|
|
|
|
Returns:
|
|
1D array: Tapered trace
|
|
"""
|
|
window = tukey(500, 0.3)
|
|
window[65:] = 1 # Force central part to remain unchanged
|
|
window = window ** 2
|
|
return in_array * window
|
|
|
|
|
|
def load(filename, static, trace_remove, x, y, sub_aver, amplify):
|
|
"""
|
|
Load and process GPR data from a SEG-Y file
|
|
|
|
Parameters:
|
|
filename (str): Path to SEG-Y file
|
|
static (int): Number of top samples to remove (static correction)
|
|
trace_remove (int): Number of traces to remove from the end
|
|
x (float): X-coordinate offset
|
|
y (float): Y-coordinate offset
|
|
sub_aver (int): Window size for background subtraction
|
|
amplify (float): Amplitude scale factor for visualization
|
|
"""
|
|
with segyio.open(filename, 'r', ignore_geometry=True) as segyfile:
|
|
raw_traces = segyfile.trace.raw[:]
|
|
data_meta = raw_traces.T[static:, :-trace_remove]
|
|
data=data_meta[0:500]
|
|
|
|
# Subtract local mean background (clutter removal)
|
|
reference_mean = sliding_window_mean(data, sub_aver)
|
|
data = data - reference_mean
|
|
|
|
# Apply tapering to suppress edge effects
|
|
data = np.apply_along_axis(taper_field, 0, data)
|
|
|
|
# Perform FK migration (custom)
|
|
data, twtt, mig_pos = mig_fk.fkmig(data, dt=0.02425e-9, dx=0.005, v=1.10e8)
|
|
|
|
# Compute envelope using Hilbert transform
|
|
data_envelop = np.abs(hilbert(data, axis=0))
|
|
|
|
# Plot migrated image
|
|
plt.title(filename[7:-4])
|
|
plt.imshow(data * amplify, cmap='gray_r', aspect='auto',
|
|
vmin=-np.max(np.abs(data)), vmax=np.max(np.abs(data)))
|
|
plt.colorbar()
|
|
plt.show()
|
|
|
|
# Plot envelope
|
|
plt.title(filename[7:-4] + " Envelope")
|
|
plt.imshow(data_envelop * amplify, cmap='gray_r', aspect='auto',
|
|
vmin=0, vmax=0.0040)
|
|
plt.colorbar()
|
|
plt.show()
|
|
|
|
# Save envelope to .dat file
|
|
write_to_dat_append(data_envelop, x, y, file)
|
|
|
|
|
|
# Main process for batch loading and writing
|
|
with open('3D.dat', 'w') as file:
|
|
load('./data/x0y0.sgy', static=35, trace_remove=1, x=0, y=0, sub_aver=51, amplify=3)
|
|
load('./data/x0y5.sgy', static=35, trace_remove=1, x=0, y=5, sub_aver=51, amplify=5)
|
|
load('./data/x0y10.sgy', static=35, trace_remove=1, x=0, y=10, sub_aver=51, amplify=10)
|
|
load('./data/x0y15.sgy', static=35, trace_remove=1, x=0, y=15, sub_aver=51, amplify=10)
|
|
load('./data/x0y20.sgy', static=35, trace_remove=1, x=0, y=20, sub_aver=51, amplify=10)
|
|
load('./data/x10y25.sgy', static=35, trace_remove=1, x=10, y=25, sub_aver=51, amplify=10)
|
|
load('./data/x20y30.sgy', static=35, trace_remove=1, x=20, y=30, sub_aver=51, amplify=10)
|
|
load('./data/x30y35.sgy', static=35, trace_remove=15, x=30, y=35, sub_aver=51, amplify=10)
|
|
load('./data/x30y40.sgy', static=35, trace_remove=1, x=30, y=40, sub_aver=51, amplify=10)
|
|
load('./data/x40y45.sgy', static=35, trace_remove=1, x=40, y=45, sub_aver=51, amplify=10)
|
|
load('./data/x45y50.sgy', static=35, trace_remove=14, x=45, y=50, sub_aver=51, amplify=10)
|
|
|