|
12 | 12 | compressed and the sparse nature of the Seislet transform can also be used to |
13 | 13 | precondition sparsity-promoting inverse problems. |
14 | 14 |
|
| 15 | +We will show examples of a variety of different settings, including a comparison |
| 16 | +with the original implementation in [1]. |
| 17 | +
|
| 18 | +.. [1] van Vliet, L. J., Verbeek, P. W., "Estimators for orientation and |
| 19 | + anisotropy in digitized images", Journal ASCI Imaging Workshop. 1995. |
| 20 | +
|
15 | 21 | """ |
16 | 22 |
|
17 | 23 | import matplotlib.pyplot as plt |
18 | 24 | import numpy as np |
| 25 | +from matplotlib.image import imread |
19 | 26 | from mpl_toolkits.axes_grid1 import make_axes_locatable |
20 | 27 |
|
21 | 28 | import pylops |
22 | 29 | from pylops.signalprocessing.Seislet import _predict_trace |
| 30 | +from pylops.utils.signalprocessing import slope_estimate |
23 | 31 |
|
24 | 32 | plt.close("all") |
25 | 33 | np.random.seed(10) |
26 | 34 |
|
27 | 35 | ############################################################################### |
| 36 | +# Python logo |
| 37 | +# ----------- |
28 | 38 | # To start we import a 2d image and estimate the local slopes of the image. |
29 | 39 | im = np.load("../testdata/python.npy")[..., 0] |
30 | 40 | im = im / 255.0 - 0.5 |
31 | 41 |
|
32 | | -slopes, anisotropy = pylops.utils.signalprocessing.slope_estimate(im, smooth=7) |
| 42 | +slopes, anisotropy = slope_estimate(im, smooth=7) |
33 | 43 | angles = -np.rad2deg(np.arctan(slopes)) |
34 | 44 |
|
35 | 45 | ############################################################################### |
|
51 | 61 | fig.tight_layout() |
52 | 62 |
|
53 | 63 | ############################################################################### |
| 64 | +# Seismic data |
| 65 | +# ------------ |
54 | 66 | # We can now repeat the same using some seismic data. We will first define |
55 | 67 | # a single trace and a slope field, apply such slope field to the trace |
56 | 68 | # recursively to create the other traces of the data and finally try to recover |
|
87 | 99 | d[:, ix] = tr |
88 | 100 |
|
89 | 101 | # Estimate slopes |
90 | | -slope_est, _ = pylops.utils.signalprocessing.slope_estimate(d, dt, dx, smooth=10) |
| 102 | +slope_est, _ = slope_estimate(d, dt, dx, smooth=10) |
91 | 103 | slope_est *= -1 |
92 | 104 |
|
93 | 105 | ############################################################################### |
|
123 | 135 | fig.tight_layout() |
124 | 136 |
|
125 | 137 | ############################################################################### |
| 138 | +# Concentric circles |
| 139 | +# ------------------ |
| 140 | +# The original paper by van Vliet and Verbeek [1] has an example with concentric |
| 141 | +# circles. We recover their original images and compare our implementation with |
| 142 | +# theirs. |
| 143 | +def rgb2gray(rgb): |
| 144 | + return np.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140]) |
| 145 | + |
| 146 | + |
| 147 | +circles_input = rgb2gray(imread("../testdata/slope_estimate/concentric.png")) |
| 148 | +circles_angles = rgb2gray(imread("../testdata/slope_estimate/concentric_angles.png")) |
| 149 | + |
| 150 | +slope, anisos_sm0 = slope_estimate(circles_input, smooth=0) |
| 151 | +angles_sm0 = np.rad2deg(np.arctan(slope)) |
| 152 | + |
| 153 | +slope, anisos_sm4 = slope_estimate(circles_input, smooth=4) |
| 154 | +angles_sm4 = np.rad2deg(np.arctan(slope)) |
| 155 | + |
| 156 | +############################################################################### |
| 157 | +fig, axs = plt.subplots(2, 3, figsize=(6, 4), sharex=True, sharey=True) |
| 158 | +axs[0, 0].imshow(circles_input, cmap="gray", aspect="equal") |
| 159 | +axs[0, 0].set(title="Original Image") |
| 160 | +cax = make_axes_locatable(axs[0, 0]).append_axes("right", size="5%", pad=0.05) |
| 161 | +cax.axis("off") |
| 162 | + |
| 163 | +axs[1, 0].imshow(-circles_angles, cmap="RdBu_r") |
| 164 | +axs[1, 0].set(title="Original Angles") |
| 165 | +cax = make_axes_locatable(axs[1, 0]).append_axes("right", size="5%", pad=0.05) |
| 166 | +cax.axis("off") |
| 167 | + |
| 168 | +im = axs[0, 1].imshow(angles_sm0, cmap="RdBu_r", vmin=-90, vmax=90) |
| 169 | +cax = make_axes_locatable(axs[0, 1]).append_axes("right", size="5%", pad=0.05) |
| 170 | +cb = fig.colorbar(im, cax=cax, orientation="vertical") |
| 171 | +axs[0, 1].set(title="Angles (smooth=0)") |
| 172 | + |
| 173 | +im = axs[1, 1].imshow(angles_sm4, cmap="RdBu_r", vmin=-90, vmax=90) |
| 174 | +cax = make_axes_locatable(axs[1, 1]).append_axes("right", size="5%", pad=0.05) |
| 175 | +cb = fig.colorbar(im, cax=cax, orientation="vertical") |
| 176 | +axs[1, 1].set(title="Angles (smooth=4)") |
| 177 | + |
| 178 | +im = axs[0, 2].imshow(anisos_sm0, cmap="Reds", vmin=0, vmax=1) |
| 179 | +cax = make_axes_locatable(axs[0, 2]).append_axes("right", size="5%", pad=0.05) |
| 180 | +cb = fig.colorbar(im, cax=cax, orientation="vertical") |
| 181 | +axs[0, 2].set(title="Anisotropy (smooth=0)") |
| 182 | + |
| 183 | +im = axs[1, 2].imshow(anisos_sm4, cmap="Reds", vmin=0, vmax=1) |
| 184 | +cax = make_axes_locatable(axs[1, 2]).append_axes("right", size="5%", pad=0.05) |
| 185 | +cb = fig.colorbar(im, cax=cax, orientation="vertical") |
| 186 | +axs[1, 2].set(title="Anisotropy (smooth=4)") |
| 187 | + |
| 188 | +for ax in axs.ravel(): |
| 189 | + ax.axis("off") |
| 190 | +fig.tight_layout() |
| 191 | + |
| 192 | + |
| 193 | +############################################################################### |
| 194 | +# Core samples |
| 195 | +# ------------------ |
| 196 | +# The original paper by van Vliet and Verbeek [1] also has an example with images |
| 197 | +# of core samples. Since the original paper does not have a scale with which to |
| 198 | +# plot the angles, we have chosen ours it to match their image as closely as |
| 199 | +# possible. |
| 200 | + |
| 201 | +core_input = rgb2gray(imread("../testdata/slope_estimate/core_sample.png")) |
| 202 | +core_angles = rgb2gray(imread("../testdata/slope_estimate/core_sample_orientation.png")) |
| 203 | +core_aniso = rgb2gray(imread("../testdata/slope_estimate/core_sample_anisotropy.png")) |
| 204 | + |
| 205 | + |
| 206 | +slope, anisos_sm4 = slope_estimate(core_input, smooth=4) |
| 207 | +angles_sm4 = np.rad2deg(np.arctan(slope)) |
| 208 | + |
| 209 | +slope, anisos_sm8 = slope_estimate(core_input, smooth=8) |
| 210 | +angles_sm8 = np.rad2deg(np.arctan(slope)) |
| 211 | + |
| 212 | +############################################################################### |
| 213 | +fig, axs = plt.subplots(1, 6, figsize=(10, 6)) |
| 214 | + |
| 215 | +axs[0].imshow(core_input, cmap="gray_r", aspect="equal") |
| 216 | +axs[0].set(title="Original\nImage") |
| 217 | +cax = make_axes_locatable(axs[0]).append_axes("right", size="20%", pad=0.05) |
| 218 | +cax.axis("off") |
| 219 | + |
| 220 | +axs[1].imshow(-core_angles, cmap="YlGnBu_r") |
| 221 | +axs[1].set(title="Original\nAngles") |
| 222 | +cax = make_axes_locatable(axs[1]).append_axes("right", size="20%", pad=0.05) |
| 223 | +cax.axis("off") |
| 224 | + |
| 225 | +im = axs[2].imshow(angles_sm8, cmap="YlGnBu_r", vmin=-49, vmax=-11) |
| 226 | +cax = make_axes_locatable(axs[2]).append_axes("right", size="20%", pad=0.05) |
| 227 | +cb = fig.colorbar(im, cax=cax, orientation="vertical") |
| 228 | +axs[2].set(title="Angles\n(smooth=8)") |
| 229 | + |
| 230 | +im = axs[3].imshow(angles_sm4, cmap="YlGnBu_r", vmin=-49, vmax=-11) |
| 231 | +cax = make_axes_locatable(axs[3]).append_axes("right", size="20%", pad=0.05) |
| 232 | +cb = fig.colorbar(im, cax=cax, orientation="vertical") |
| 233 | +axs[3].set(title="Angles\n(smooth=4)") |
| 234 | + |
| 235 | +im = axs[4].imshow(anisos_sm8, cmap="Reds", vmin=0, vmax=1) |
| 236 | +cax = make_axes_locatable(axs[4]).append_axes("right", size="20%", pad=0.05) |
| 237 | +cb = fig.colorbar(im, cax=cax, orientation="vertical") |
| 238 | +axs[4].set(title="Anisotropy\n(smooth=8)") |
| 239 | + |
| 240 | +im = axs[5].imshow(anisos_sm4, cmap="Reds", vmin=0, vmax=1) |
| 241 | +cax = make_axes_locatable(axs[5]).append_axes("right", size="20%", pad=0.05) |
| 242 | +cb = fig.colorbar(im, cax=cax, orientation="vertical") |
| 243 | +axs[5].set(title="Anisotropy\n(smooth=4)") |
| 244 | + |
| 245 | +for ax in axs.ravel(): |
| 246 | + ax.axis("off") |
| 247 | +fig.tight_layout() |
| 248 | + |
| 249 | +############################################################################### |
| 250 | +# Final considerations |
| 251 | +# -------------------- |
126 | 252 | # As you can see the Structure Tensor algorithm is a very fast, general purpose |
127 | 253 | # algorithm that can be used to estimate local slopes to input datasets of |
128 | | -# very different nature. |
| 254 | +# very different natures. |
0 commit comments