.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_gallery/plot_stereo_video.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_gallery_plot_stereo_video.py: Estimating directional spectra from stereo-imaging ================================================== Stereo-imaging has emerged as a unique measurement technique for obtaining precise directional information about wave fields. One of its key advantages lies in the direct estimation of directional wave spectra through three-dimensional Fourier analysis. The quality of the directional spectrum is intricately tied to the resolution of the images captured. Higher image resolution can provide insights into small-scale wave features, including the dynamics of growing waves and wave-breaking processes. However, large-scale wave features, such as long waves (e.g., swell), may fall beyond the camera's field of view. In such cases, alternative techniques may need to be considered. For example, one approach involves selecting several pixels from the image and extracting the time series of the surface elevation. This can then be used to construct the directional spectrum from the data. This example uses data from `Guimaraes et al (2020)`_ taken at the Black Sea. We explore different results changing the number and distribution of pixels in the image. .. _Guimaraes et al (2020): https://doi.org/10.1038/s41597-020-0492-9 .. GENERATED FROM PYTHON SOURCE LINES 30-54 .. code-block:: Python import numpy as np import xarray as xr import netCDF4 as nc import matplotlib.pyplot as plt import matplotlib.image as mpimg import urllib.request import subprocess import os from scipy.io import loadmat import ewdm from ewdm.plots import plot_directional_spectrum # define paths and filenames URL = "https://data-dataref.ifremer.fr/stereo/BS_2013/" VIDEO_URL = URL + "2013-09-22_13-00-01_10Hz/nc/Surfaces_20130922_130001_short.nc" IMAGE_RIGHT_URL = URL + "2013-09-22_13-00-01_10Hz/input/000111_01.tif" IMAGE_LEFT_URL = URL + "2013-09-22_13-00-01_10Hz/input/000111_02.tif" CACHE_DIR = "../../data/" LOCAL_VIDEO_FILE = os.path.join(CACHE_DIR, "stereo-video.nc") .. GENERATED FROM PYTHON SOURCE LINES 55-60 Exploring stereo-video dataset ------------------------------ First, let's see what a typical stereo-image looks like. Below, the first frame of the Black Sea data is shown. .. GENERATED FROM PYTHON SOURCE LINES 60-75 .. code-block:: Python # load images img_right = mpimg.imread(urllib.request.urlopen(IMAGE_RIGHT_URL), format='tif') img_left = mpimg.imread(urllib.request.urlopen(IMAGE_LEFT_URL), format='tif') # plot images fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8,4)) ax1.imshow(img_left) ax2.imshow(img_right) ax1.axis('off') ax2.axis('off') ax1.set_title("Left camera") ax2.set_title("Right camera") plt.show() .. image-sg:: /auto_gallery/images/sphx_glr_plot_stereo_video_001.png :alt: Left camera, Right camera :srcset: /auto_gallery/images/sphx_glr_plot_stereo_video_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 76-81 Computing directional wave spectra ---------------------------------- Now, we are going to download the netCDF4 containing the streo-images data and place it into the data folder. This might take a few minutes. .. GENERATED FROM PYTHON SOURCE LINES 81-94 .. code-block:: Python # check if the file is already cached if not os.path.exists(LOCAL_VIDEO_FILE): print("Downloading the stereo-video file. It might take a few minutes.") command = f"wget {VIDEO_URL} -O {LOCAL_VIDEO_FILE}" subprocess.call(command, shell=True) else: print("File already exists. Skipping download.") # laod the video data as netcdf nc_obj = nc.Dataset(LOCAL_VIDEO_FILE) .. rst-class:: sphx-glr-script-out .. code-block:: none Downloading the stereo-video file. It might take a few minutes. .. GENERATED FROM PYTHON SOURCE LINES 95-102 To pick the pixels, we define the corresponding indices. We are going to evaluate four different configurations. 1. The optimal array proposed by Young et al (1994). 2. A simple pentagon. 3. 10 random points. 4. 20 random points. .. GENERATED FROM PYTHON SOURCE LINES 103-156 .. code-block:: Python indices1 = [ (95,95), (95,175), (95,15), (175,15), (15,15), (115,95), (75,95), (95,75) ] indices2 = [ (95,95), (95, 5), (171, 62), (138, 161), (55, 161), (22, 62) ] indices3 = [tuple(np.random.randint(40, 150, size=2)) for _ in range(10)] indices4 = [tuple(np.random.randint(40, 150, size=2)) for _ in range(20)] titles = ["Young (1994)", "Pentagon", "10 random", "20 random"] # loop for each configuration for indices, title in zip((indices1, indices2, indices3, indices4), titles): # pick the elevation time series from the image x = np.array([nc_obj["X"][i,j] for i,j in indices]) y = np.array([nc_obj["Y"][i,j] for i,j in indices]) eta = np.array([nc_obj["Z"][:8192,i,j] for i,j in indices]) time = nc.num2date(nc_obj['time'][:8192], units=nc_obj["time"].units) elements = np.arange(len(x)) # create input dataset dataset = xr.Dataset( data_vars = { "surface_elevation": (["time", "element"], eta.T), "position_x": ("element", x), "position_y": ("element", y) }, coords = {"time": time, "element": elements}, attrs = {"sampling_rate": 10} ) # run the ewdm.Arrays code and obtain the directional spectrum spec = ewdm.Arrays(dataset) output = spec.compute( cross_wavelet=True, solver="least-squares", kappa=36 ) # plot the results fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8,3.5)) plot_directional_spectrum( output.directional_spectrum, ax=ax2, levels=None, colorbar=True, axes_kw={"rmin": 0.1, "rmax": 1.2, "rstep": 0.2, "angle": 135}, cbar_kw={"label": "$E(f,\\theta)$"} ) ax1.pcolormesh( nc_obj["X"][:,:], nc_obj["Y"][:,:], nc_obj["Z"][0,:,:], cmap="bwr", vmin=-0.5, vmax=0.5 ) ax1.plot(x, y, "o", mec="indigo", mfc="w") ax1.set_title(title) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_gallery/images/sphx_glr_plot_stereo_video_002.png :alt: Young (1994) :srcset: /auto_gallery/images/sphx_glr_plot_stereo_video_002.png :class: sphx-glr-multi-img * .. image-sg:: /auto_gallery/images/sphx_glr_plot_stereo_video_003.png :alt: Pentagon :srcset: /auto_gallery/images/sphx_glr_plot_stereo_video_003.png :class: sphx-glr-multi-img * .. image-sg:: /auto_gallery/images/sphx_glr_plot_stereo_video_004.png :alt: 10 random :srcset: /auto_gallery/images/sphx_glr_plot_stereo_video_004.png :class: sphx-glr-multi-img * .. image-sg:: /auto_gallery/images/sphx_glr_plot_stereo_video_005.png :alt: 20 random :srcset: /auto_gallery/images/sphx_glr_plot_stereo_video_005.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 157-161 There are clearly some differences between the chosen configurations. The overal quality of the directional spectrum depends on the array distribution. However, we confirm that the main wave direction obtained in all cases is consistent with the reported by Guimaraes et al (2020). .. rst-class:: sphx-glr-timing **Total running time of the script:** (5 minutes 30.826 seconds) .. _sphx_glr_download_auto_gallery_plot_stereo_video.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_stereo_video.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_stereo_video.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_stereo_video.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_