diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 0027159c..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-language: python
-python:
- - "3.8"
-
-notifications:
- email: false
-
-install:
- - pip install -q numpy pytest
- - pip install -e .
-
-script:
- - pytest openpiv
diff --git a/CHANGES.txt b/CHANGES.txt
deleted file mode 100644
index 9f0aa78b..00000000
--- a/CHANGES.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-v0.11, June 18, 2014 -- Initial release.op
-v0.12, June 26, 2014 -- Update with masking, completely black interrogation window is masked
-v0.13, June 30, 2014 -- Dynamic masking is included, image and velocity set to zero, sig2noise to infinity
-v0.17, July 1, 2014 -- Fixed the bug in lib.pyx of different casting of np.int32 on 64-bit machines
-v0.18 Aug. 8, 2014 -- small updates to the tutorial-part1, MANIFEST.IN, readme and install files
-...
-v0.22.3 Sep. 22, 2020 -- @erfan-mtr added two-phase extension, see phase_separation.ipynb for the demo
-v0.22.4 Nov, 2020 -- windef refactoring : no more process.pyx, everything in pyprocess.py, numpy vectorized correlation version from windef moved to pyprocess, get_field_shape has less arguments (it's a backward compatability problem, it breaks stuff), new tests, new documentation settings with Jupyter notebook and markdown inserts, tools.save requires also sig2noise column, as in windef, frame_interpolation is now deform_windows with optionaly kx,ky,
-v0.23.0 - refactored windef.py, with the main functions moved to pyprocess.py
-v0.23.1 - fixed bugs in 0.23.0, new normalized_correlation, normalize_intensity, find_subpixel_position, new tests, new jupyter notebooks, see also
- test_robustness
-v0.23.2 - added mask_coordinats to preprocess, allows to use dynamic_masking to create
- image mask as well as a polygon that propagates into multi-process and validation
- created new Jupyter notebook to test von Karman vortex street case and compare with PIVLab
- breakes backward compatibility of windef with removing validation and filtering steps, to be compatible
- with the first_pass. Both first_pass and multi_pass now apply filtering externally
-
-v0.23.6 - removed widim.pyx, no Cython modules anymore
-v0.23.7 - @ErichZimmer provided rectangular windows and we moved the test cases to another repo openpiv-python-examples
-
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index 692fcab1..00000000
--- a/INSTALL
+++ /dev/null
@@ -1,57 +0,0 @@
-=========================
-Installation instructions
-=========================
-
-Dependencies
-============
-
-OpenPIV would not have been possible if other great open source projects did not
-exist. We make extensive use of code and tools that other people have created, so
-you should install them before you can use OpenPIV.
-
-The main dependencies are:
-
-* `python `_
-* `scipy `_
-* `numpy `_
-* `scikit-image `_
-
-On all the platforms, the binary Anaconda installation is recommended.
-Visit https://www.continuum.io/downloads
-
-
-Get OpenPIV source code!
-========================
-
-At this moment the only way to get OpenPIV's source code is using git.
-`Git `_ Git is a distributed revision control system and
-our code is hosted at `GitHub `_.
-
-
-Use PyPI and pip
-================
-
- pip install -U openpiv
-
-
-Downloads the code from PyPI and runs the setup for you with installation and Cython (if preinstalled)
-
-Bleeding edge development version
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-If you are interested in the source code you are welcome to browse out git repository
-stored at https://github.com/gasagna/OpenPIV. If you want to download the source code
-on your machine, for testing, you need to set up git on your computer. Please look at
-http://help.github.com/ which provide extensive help for how to set up git.
-
-To follow the development of OpenPIV, clone our repository with the command::
-
- git clone http://github.com/alexlib/openpiv-python.git
-
-and update from time to time. You can also download a tarball containing everything.
-
-Then add the path where the OpenPIV source are to the PYTHONPATH environment variable, so
-that OpenPIV module can be imported and used in your programs. Remeber to build the extension
-with ::
-
- python setup.py build
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index fdf3dd8d..00000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,24 +0,0 @@
-include *.md
-include *.txt
-include INSTALL
-include LICENSE.txt
-include MILESTONES
-include TODO
-
-recursive-include openpiv/docs *
-recursive-include openpiv/examples *
-recursive-include openpiv/test *
-recursive-exclude openpiv/test/__pycache__ *
-recursive-exclude openpiv/examples/notebooks/.ipynb_checkpoints *
-
-
-recursive-include openpiv *.bmp
-recursive-include openpiv *.c
-recursive-include openpiv *.ipynb
-recursive-include openpiv *.pdf
-recursive-include openpiv *.png
-recursive-include openpiv *.py
-recursive-include openpiv *.pyx
-recursive-include openpiv *.rst
-recursive-include openpiv *.tif
-include cysetuptools.py
diff --git a/MILESTONES b/MILESTONES
deleted file mode 100644
index a6f3e19b..00000000
--- a/MILESTONES
+++ /dev/null
@@ -1,22 +0,0 @@
-Milestones and targets for future OpenPiv versions.
-
-v 0.1
-+ all functions should be unit tested
-+ all functions should be correctly documented
-+ the basic api structure should be clear and defined
-
-v 0.2
-+ Lavision file format reader
-+ Hdf5 output
-+ at least one advanced processing algorithm, ( 1st order, 2nd order )
-
-v 0.3
-+ data display submodule using matplotlib
-+ post-processing facilities
-
-v 0.4
-+ basic gui for image processing. The gui will allow to select image directory
-processing parameters, algorithm, etc, but not display result at the moment.
-
-v 0.5
-+ Gui post-processing and data visualization
diff --git a/README.md b/README.md
index af321ea2..4c1cda2d 100644
--- a/README.md
+++ b/README.md
@@ -1,100 +1,27 @@
-# OpenPIV
-[](https://travis-ci.org/OpenPIV/openpiv-python)
-
-[](https://doi.org/10.5281/zenodo.4409178)
-
-
-
-
-[](https://anaconda.org/alexlib/openpiv)
-
-
-OpenPIV consists in a Python and Cython modules for scripting and executing the analysis of
-a set of PIV image pairs. In addition, a Qt and Tk graphical user interfaces are in
-development, to ease the use for those users who don't have python skills.
-
-## Warning
-
-The OpenPIV python version is still in its *beta* state. This means that
-it still might have some bugs and the API may change. However, testing and contributing
-is very welcome, especially if you can contribute with new algorithms and features.
-
-
-## Test it without installation
-Click the link - thanks to BinderHub, Jupyter and Conda you can now get it in your browser with zero installation:
-[](https://mybinder.org/v2/gh/openpiv/openpiv-python/master?filepath=openpiv%2Fexamples%2Fnotebooks%2Ftutorial1.ipynb)
+# OpenPIV XL
+The authors aknowledge the authors of [OpenPIV](https://github.com/OpenPIV/openpiv-python), from which this package is derived. OpenPIV should be cited with this [DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4409178).
+This package is designed to perform DIC on large images (> 10,000 x 10,000 px) using chunking and GPU acceleration.
+Using the GPU, DIC correlation from a sub-window of 2048x2048 to 16x16 with no overlap on a (16000x16000) px image takes around a minute.
## Installing
-Use PyPI: :
-
- pip install openpiv
-
-
-## Or `conda`
-
- conda install -c alexlib openpiv
-
-
-### To build from source
-
-Download the package from the Github: https://github.com/OpenPIV/openpiv-python/archive/master.zip
-or clone using git
+Download the package and run
- git clone https://github.com/OpenPIV/openpiv-python.git
+`pip install -e .`
-Using distutils create a local (in the same directory) compilation of the Cython files:
+OR
- python setup.py build_ext --inplace
+`pip install git+https://github.com/MechMicroMan/openpiv-python.git`
-Or for the global installation, use:
+Note: you will need a Nvidia GPU which supports CUDA 12x
- python setup.py install
+## License and copyright
-## Documentation
-
-The OpenPIV documentation is available on the project web page at
-
-## Demo notebooks
-
-1. [Tutorial Notebook 1](https://nbviewer.jupyter.org/github/OpenPIV/openpiv-python-examples/blob/main/notebooks/tutorial1.ipynb)
-2. [Tutorial notebook 2](https://nbviewer.jupyter.org/github/OpenPIV/openpiv-python-examples/blob/main/notebooks/tutorial2.ipynb)
-3. [Dynamic masking tutorial](https://nbviewer.jupyter.org/github/OpenPIV/openpiv-python-examples/blob/main/notebooks/masking_tutorial.ipynb)
-4. [Multipass with Windows Deformation](https://nbviewer.jupyter.org/github/OpenPIV/openpiv-python-examples/blob/main/notebooks/window_deformation_comparison.ipynb)
-5. [Multiple sets in one notebook](https://nbviewer.jupyter.org/github/OpenPIV/openpiv-python-examples/blob/main/notebooks/all_test_cases_sample.ipynb)
-6. [3D PIV](https://nbviewer.org/github/OpenPIV/openpiv-python-examples/blob/main/notebooks/PIV_3D_example.ipynb)
-
-
-These and many additional examples are in another repository: [OpenPIV-Python-Examples](https://github.com/OpenPIV/openpiv-python-examples)
-
-
-## Contributors
-
-1. [Alex Liberzon](http://github.com/alexlib)
-2. [Roi Gurka](http://github.com/roigurka)
-3. [Zachary J. Taylor](http://github.com/zjtaylor)
-4. [David Lasagna](http://github.com/gasagna)
-5. [Mathias Aubert](http://github.com/MathiasAubert)
-6. [Pete Bachant](http://github.com/petebachant)
-7. [Cameron Dallas](http://github.com/CameronDallas5000)
-8. [Cecyl Curry](http://github.com/leycec)
-9. [Theo Käufer](http://github.com/TKaeufer)
-10. [Andreas Bauer](https://github.com/AndreasBauerGit)
-11. [David Bohringer](https://github.com/davidbhr)
-12. [Erich Zimmer](https://github.com/ErichZimmer)
-13. [Peter Vennemann](https://github.com/eguvep)
-14. [Lento Manickathan](https://github.com/lento234)
-
+This package is licenses under the GNU General Public License v3.0
Copyright statement: `smoothn.py` is a Python version of `smoothn.m` originally created by D. Garcia [https://de.mathworks.com/matlabcentral/fileexchange/25634-smoothn], written by Prof. Lewis and available on Github [https://github.com/profLewis/geogg122/blob/master/Chapter5_Interpolation/python/smoothn.py]. We include a version of it in the `openpiv` folder for convenience and preservation. We are thankful to the original authors for releasing their work as an open source. OpenPIV license does not relate to this code. Please communicate with the authors regarding their license.
-## How to cite this work
-[](https://doi.org/10.5281/zenodo.4409178)
-
-
-
-
diff --git a/openpiv/PIV_3D_plotting.py b/openpiv/PIV_3D_plotting.py
deleted file mode 100644
index a04dc2f0..00000000
--- a/openpiv/PIV_3D_plotting.py
+++ /dev/null
@@ -1,355 +0,0 @@
-"""
-functions to plot 3D-deformation fields and simple 3D-structures
-"""
-
-
-import matplotlib
-import matplotlib.pyplot as plt
-import numpy as np
-from itertools import chain
-from mpl_toolkits.mplot3d import Axes3D
-
-
-def set_axes_equal(ax):
-
- """
- Following https://stackoverflow.com/questions/13685386/matplotlib-equal-unit-length-with-equal-aspect-ratio-z-axis-is-not-equal-to
- Make axes of 3D plot have equal scale so that spheres appear as spheres,
- cubes as cubes, etc.. This is one possible solution to Matplotlib's
- ax.set_aspect('equal') and ax.axis('equal') not working for 3D.
-
- Parameters
- ----------
- ax: matplotlib.axes object
-
-
- """
-
- x_limits = ax.get_xlim3d()
- y_limits = ax.get_ylim3d()
- z_limits = ax.get_zlim3d()
-
- x_range = abs(x_limits[1] - x_limits[0])
- x_middle = np.mean(x_limits)
- y_range = abs(y_limits[1] - y_limits[0])
- y_middle = np.mean(y_limits)
- z_range = abs(z_limits[1] - z_limits[0])
- z_middle = np.mean(z_limits)
-
- # The plot bounding box is a sphere in the sense of the infinity
- # norm, hence I call half the max range the plot radius.
- plot_radius = 0.5 * max([x_range, y_range, z_range])
-
- ax.set_xlim3d([x_middle - plot_radius, x_middle + plot_radius])
- ax.set_ylim3d([y_middle - plot_radius, y_middle + plot_radius])
- ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius])
-
-
-def scatter_3D(a, cmap="jet", sca_args=None, control="color", size=60):
-
- # default arguments for the quiver plot. can be overwritten by quiv_args
- if not isinstance(sca_args, dict):
- sca_args = {}
- scatter_args = {"alpha": 1}
- scatter_args.update(sca_args)
-
- x, y, z = np.indices(a.shape)
- x = x.flatten()
- y = y.flatten()
- z = z.flatten()
-
- fig = plt.figure()
- ax = fig.add_subplot(projection='3d', rasterized=True)
-
- if control == "color":
- # make cmap
- cbound = [np.nanmin(a), np.nanmax(a)]
- # create normalized color map for arrows
- norm = matplotlib.colors.Normalize(
- vmin=cbound[0], vmax=cbound[1]
- ) # 10 ) #cbound[1] ) #)
- sm = matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm)
- sm.set_array([])
- # different option
- cm = matplotlib.cm.get_cmap(cmap)
- colors = cm(norm(a)).reshape(a.shape[0] * a.shape[1] * a.shape[2], 4) #
- # plotting
- nan_filter = ~np.isnan(a.flatten())
- ax.scatter(
- x[nan_filter],
- y[nan_filter],
- z[nan_filter],
- c=colors[nan_filter],
- s=size,
- **scatter_args
- )
- plt.colorbar(sm)
-
- if control == "alpha":
- # untested #
- colors = [(0, 0, 1, x / np.max(z)) for x in np.ravel(z)]
- ax.scatter(x, y, z, c=colors, s=size, **scatter_args)
- plt.show()
-
- if control == "size":
- sizes = (a - a.min()) * size / a.ptp()
- ax.scatter(x, y, z, a, s=sizes, **scatter_args)
- ax_scale = plt.axes([0.88, 0.1, 0.05, 0.7])
- # ax_scale.set_ylim((0.1,1.2))
- nm = 5
- ax_scale.scatter(
- [0] * nm,
- np.linspace(a.min(), a.max(), nm),
- s=sizes.max() * np.linspace(0, 1, nm),
- )
- ax_scale.spines["left"].set_visible(False)
- ax_scale.spines["right"].set_visible(True)
- ax_scale.spines["bottom"].set_visible(False)
- ax_scale.spines["top"].set_visible(False)
- ax_scale.tick_params(
- axis="both",
- which="both",
- labelbottom=False,
- labelleft=False,
- labelright=True,
- bottom=False,
- left=False,
- right=True,
- )
-
- ax.set_xlim(0, a.shape[0])
- ax.set_ylim(0, a.shape[1])
- ax.set_zlim(0, a.shape[2])
- ax.set_xlabel("x")
- ax.set_ylabel("y")
- ax.set_zlabel("z")
-
- return fig
-
-
-def explode(data):
- # following "https://matplotlib.org/3.1.1/gallery/mplot3d/voxels_numpy_logo.html"
-
- if len(data.shape) == 3:
- size = np.array(data.shape) * 2
- data_e = np.zeros(size - 1, dtype=data.dtype)
- data_e[::2, ::2, ::2] = data
- if len(data.shape) == 4: ## color data
- size = np.array(data.shape)[:3] * 2
- data_e = np.zeros(np.concatenate([size - 1, np.array([4])]), dtype=data.dtype)
- data_e[::2, ::2, ::2, :] = data
-
- return data_e
-
-
-def plot_3D_alpha(data):
- # plotting each voxel as a slightly smaller block with transparency depending
- # on the data value
- # following "https://matplotlib.org/3.1.1/gallery/mplot3d/voxels_numpy_logo.html"
-
- col = np.zeros((data.shape[0], data.shape[1], data.shape[2], 4))
-
- data_fil = data.copy()
- data_fil[(data == np.inf)] = np.nanmax(data[~(data == np.inf)])
- data_fil = (data_fil - np.nanmin(data_fil)) / (
- np.nanmax(data_fil) - np.nanmin(data_fil)
- )
- data_fil[np.isnan(data_fil)] = 0
-
- col[:, :, :, 2] = 1
- col[:, :, :, 3] = data_fil
-
- col_exp = explode(col)
- fill = explode(np.ones(data.shape))
-
- x, y, z = np.indices(np.array(fill.shape) + 1).astype(float) // 2
-
- x[0::2, :, :] += 0.05
- y[:, 0::2, :] += 0.05
- z[:, :, 0::2] += 0.05
- x[1::2, :, :] += 0.95
- y[:, 1::2, :] += 0.95
- z[:, :, 1::2] += 0.95
-
- fig = plt.figure()
- ax = fig.gca(projection="3d")
- ax.voxels(x, y, z, fill, facecolors=col_exp, edgecolors=col_exp)
- ax.set_xlabel("x")
- ax.set_ylabel("y")
- ax.set_zlabel("z")
- plt.show()
-
-
-def quiver_3D(
- u,
- v,
- w,
- x=None,
- y=None,
- z=None,
- mask_filtered=None,
- filter_def=0,
- filter_reg=(1, 1, 1),
- cmap="jet",
- quiv_args=None,
- vmin=None,
- vmax=None,
- arrow_scale=0.15,
- equal_ax=True,
-):
- """
- Displaying 3D deformation fields vector arrows
-
- Parameters
- ----------
- u,v,w: 3d ndarray or lists
- arrays or list with deformation in x,y and z direction
-
- x,y,z: 3d ndarray or lists
- Arrays or list with deformation the coordinates of the deformations.
- Must match the dimensions of the u,v qnd w. If not provided x,y and z are created
- with np.indices(u.shape)
-
- mask_filtered, boolean 3d ndarray or 1d ndarray
- Array, or list with same dimensions as the deformations. Defines the area where deformations are drawn
-
- filter_def: float
- Filter that prevents the display of deformations arrows with length < filter_def
-
- filter_reg: tuple,list or int
- Filter that prevents the display of every i-th deformations arrows separatly alon each axis.
- filter_reg=(2,2,2) means that only every second arrow along x,y z axis is displayed leading to
- a total reduction of displayed arrows by a factor of 8. filter_reg=3 is interpreted
- as (3,3,3).
-
- cmap: string
- matplotlib colorbar that defines the coloring of the arrow
-
- quiv_args: dict
- Dictionary with kwargs passed on to the matplotlib quiver function.
-
- vmin,vmax: float
- Upper and lower bounds for the colormap. Works like vmin and vmax in plt.imshow().
-
- arrow_scale: float
- Automatic scaling of the quiver arrows so that the longest arrow has the
- length axis length * arrow_scale. Arrow length can alternatively be set by
- passing a "lenght" argument in quiv_args.
-
- equal_axes: bool
- resize the figure axis so that they are have equal scaling.
-
-
- Returns
- -------
- fig: matploltib figure object
-
- ax: mattplotlib axes object
- the holding the main 3D quiver plot
-
- """
-
- # default arguments for the quiver plot. can be overwritten by quiv_args
- quiver_args = {
- "normalize": False,
- "alpha": 0.8,
- "pivot": "tail",
- "linewidth": 1,
- "length": 1,
- }
- if isinstance(quiv_args, dict):
- quiver_args.update(quiv_args)
- # overwriting length if an arrow scale and a "length" argument in quiv_args
- # is provided at the same
- if arrow_scale is not None:
- quiver_args["length"] = 1
-
- # convert filter ot list if proveided as int
- if not isinstance(filter_reg, (tuple, list)):
- filter_reg = [filter_reg] * 3
-
- # generating coordinates if not provided
- if x is None:
- # if you provide deformations as a list
- if len(u.shape) == 1:
- x, y, z = [np.indices(u.shape)[0] for i in range(3)]
- # if you provide deformations as an array
- elif len(u.shape) == 3:
- x, y, z = np.indices(u.shape)
- else:
- raise ValueError(
- "displacement data has wrong number of dimensions (%s). Use 1d array, list, or 3d array."
- % str(len(u.shape))
- )
-
- # conversion to array
- x, y, z = np.array([x, y, z])
-
- deformation = np.sqrt(u ** 2 + v ** 2 + w ** 2)
- if not isinstance(mask_filtered, np.ndarray):
- mask_filtered = deformation > filter_def
- if isinstance(filter_reg, list):
- show_only = np.zeros(u.shape).astype(bool)
- # filtering out every x-th
- show_only[:: filter_reg[0], :: filter_reg[1], :: filter_reg[2]] = True
- mask_filtered = np.logical_and(mask_filtered, show_only)
-
- xf = x[mask_filtered]
- yf = y[mask_filtered]
- zf = z[mask_filtered]
- uf = u[mask_filtered]
- vf = v[mask_filtered]
- wf = w[mask_filtered]
- df = deformation[mask_filtered]
-
- # make cmap
- # create normalized color map for arrows
- norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax) # 10 ) #cbound[1] ) #)
- sm = matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm)
- sm.set_array([])
- # different option
- colors = matplotlib.cm.jet(norm(df)) #
-
- colors = [c for c, d in zip(colors, df) if d > 0] + list(
- chain(*[[c, c] for c, d in zip(colors, df) if d > 0])
- )
- # colors in ax.quiver 3d is really fucked up/ will probably change with updates:
- # requires list with: first len(u) entries define the colors of the shaft, then the next len(u)*2 entries define
- # the color ofleft and right arrow head side in alternating order. Try for example:
- # colors = ["red" for i in range(len(cf))] + list(chain(*[["blue", "yellow"] for i in range(len(cf))]))
- # to see this effect.
- # BUT WAIT THERS MORE: zeor length arrows are apparently filtered out in the matplolib with out filtering
- # the color list appropriately so we have to do this our selfs as well
-
- # scale arrows to axis dimensions:
- ax_dims = [(x.min(), x.max()), (y.min(), y.max()), (z.min(), z.max())]
- if arrow_scale is not None:
- max_length = df.max()
- max_dim_length = np.max([(d[1] - d[0] + 1) for d in ax_dims])
- scale = max_dim_length * arrow_scale / max_length
- else:
- scale = 1
-
- # plotting
- fig = plt.figure()
- ax = fig.gca(projection="3d", rasterized=True)
- ax.quiver(
- xf, yf, zf, vf * scale, uf * scale, wf * scale, colors=colors, **quiver_args
- )
- plt.colorbar(sm)
-
- ax.set_xlim(ax_dims[0])
- ax.set_ylim(ax_dims[1])
- ax.set_zlim(ax_dims[2])
-
- if equal_ax:
- set_axes_equal(ax)
-
- ax.set_xlabel("x")
- ax.set_ylabel("y")
- ax.set_zlabel("z")
- ax.w_xaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
- ax.w_yaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
- ax.w_zaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
-
- return fig
diff --git a/openpiv/piv.py b/openpiv/piv.py
deleted file mode 100644
index ba32298d..00000000
--- a/openpiv/piv.py
+++ /dev/null
@@ -1,117 +0,0 @@
-import numpy as np
-import matplotlib.pyplot as plt
-
-from openpiv import pyprocess, tools
-import pkg_resources as pkg
-
-# import numpy as np
-
-import matplotlib.animation as animation
-
-"""This module contains image processing routines that improve
-images prior to PIV processing."""
-
-__licence_ = """
-Copyright (C) 2011 www.openpiv.net
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-
-def simple_piv(im1, im2, plot=True):
- """
- Simplest PIV run on the pair of images using default settings
-
- piv(im1,im2) will create a tmp.vec file with the vector filed in pix/dt
- (dt=1) from two images, im1,im2 provided as full path filenames
- (TIF is preferable, whatever imageio can read)
-
- """
- if isinstance(im1, str):
- im1 = tools.imread(im1)
- im2 = tools.imread(im2)
-
- u, v, s2n = pyprocess.extended_search_area_piv(
- im1.astype(np.int32), im2.astype(np.int32), window_size=32,
- overlap=16, search_area_size=32
- )
- x, y = pyprocess.get_coordinates(image_size=im1.shape,
- search_area_size=32, overlap=16)
-
- valid = s2n > np.percentile(s2n, 5)
-
- if plot:
- _, ax = plt.subplots(figsize=(6, 6))
- ax.imshow(im1, cmap=plt.get_cmap("gray"), alpha=0.5, origin="upper")
- ax.quiver(x[valid], y[valid], u[valid], -v[valid], scale=70,
- color='r', width=.005)
- plt.show()
-
- # conform with the windef and tools.display_vector_field
- x,y,u,v = tools.transform_coordinates(x,y,u,v)
-
- return x, y, u, v, s2n
-
-
-def piv_example():
- """
- PIV example uses examples/test5 vortex PIV data to show the main principles
-
- piv(im1,im2) will create a tmp.vec file with the vector filed in pix/dt
- (dt=1) from two images, im1,im2 provided as full path filenames
- (TIF is preferable)
-
- """
- # if im1 is None and im2 is None:
- im1 = pkg.resource_filename("openpiv", "data/test1/exp1_001_a.bmp")
- im2 = pkg.resource_filename("openpiv", "data/test1/exp1_001_b.bmp")
-
- frame_a = tools.imread(im1)
- frame_b = tools.imread(im2)
-
- # frame_a[0:32, 512 - 32:] = 255
-
- images = []
- images.extend([frame_a, frame_b])
-
- fig, ax = plt.subplots()
-
- # ims is a list of lists, each row is a list of artists to draw in the
- # current frame; here we are just animating one artist, the image, in
- # each frame
- ims = []
- for i in range(2):
- im = ax.imshow(images[i % 2], animated=True, cmap="gray")
- ims.append([im])
-
- _ = animation.ArtistAnimation(fig, ims, interval=500, blit=False,
- repeat_delay=0)
- plt.show()
-
- # import os
-
- vel = pyprocess.extended_search_area_piv(
- frame_a.astype(np.int32), frame_b.astype(np.int32), window_size=32,
- search_area_size=64,
- overlap=8
- )
- x, y = pyprocess.get_coordinates(image_size=frame_a.shape,
- search_area_size=64, overlap=8)
-
- fig, ax = plt.subplots(1, 2, figsize=(11, 8))
- ax[0].imshow(frame_a, cmap=plt.get_cmap("gray"), alpha=0.8)
- ax[0].quiver(x, y, vel[0], -vel[1], scale=50, color="r")
- ax[1].quiver(x, y[::-1, :], vel[0], -1*vel[1], scale=50, color="b")
- ax[1].set_aspect(1)
- # ax[1].invert_yaxis()
- plt.show()
-
- return x, y, vel[0], vel[1]
diff --git a/openpiv/pyprocess.py b/openpiv/pyprocess.py
index c24e8cc6..9146ac65 100644
--- a/openpiv/pyprocess.py
+++ b/openpiv/pyprocess.py
@@ -684,7 +684,8 @@ def fft_correlate_images(
fftshift = fftshift_,
f2a_builder=None,
f2b_builder=None,
- corr_builder=None
+ corr_builder=None,
+ settings=None
)->np.ndarray:
""" FFT based cross correlation
of two images with multiple views of np.stride_tricks()
@@ -740,14 +741,14 @@ def fft_correlate_images(
slice((fsize[0]-s1[0])//2, (fsize[0]+s1[0])//2),
slice((fsize[1]-s1[1])//2, (fsize[1]+s1[1])//2))
- f2a = conj(rfft2(image_a, fsize, axes=(-2, -1), threads=20)) # type: ignore
- f2b = rfft2(image_b, fsize, axes=(-2, -1), threads=20) # type: ignore
- corr = fftshift(irfft2(f2a * f2b, threads=20).real, axes=(-2, -1))[fslice]
+ f2a = conj(rfft2(image_a, fsize, axes=(-2, -1), threads = settings.num_cpus)) # type: ignore
+ f2b = rfft2(image_b, fsize, axes=(-2, -1), threads = settings.num_cpus) # type: ignore
+ corr = fftshift(irfft2(f2a * f2b, threads = settings.num_cpus).real, axes=(-2, -1))[fslice]
elif correlation_method == "circular":
- #f2a = conj(rfft2(image_a, threads=20))
- #f2b = rfft2(image_b, threads=20)
- #corr = fftshift(irfft2(f2a * f2b, threads=20).real, axes=(-2, -1))
+ #f2a = conj(rfft2(image_a, threads = settings.num_cpus))
+ #f2b = rfft2(image_b, threads = settings.num_cpus)
+ #corr = fftshift(irfft2(f2a * f2b, threads = settings.num_cpus).real, axes=(-2, -1))
if (f2a_builder != None):
@@ -761,15 +762,15 @@ def fft_correlate_images(
else:
- f2a = conj(rfft2(image_a, threads=20))
- f2b = rfft2(image_b, threads=20)
- corr = fftshift(irfft2(f2a * f2b, threads=20).real, axes=(-2, -1))
+ f2a = conj(rfft2(image_a, threads = settings.num_cpus))
+ f2b = rfft2(image_b, threads = settings.num_cpus)
+ corr = fftshift(irfft2(f2a * f2b, threads = settings.num_cpus).real, axes=(-2, -1))
else:
- f2a = conj(rfft2(image_a, threads=20))
- f2b = rfft2(image_b, threads=20)
- corr = fftshift(irfft2(f2a * f2b, threads=20).real, axes=(-2, -1))
+ f2a = conj(rfft2(image_a, threads = settings.num_cpus))
+ f2b = rfft2(image_b, threads = settings.num_cpus)
+ corr = fftshift(irfft2(f2a * f2b, threads = settings.num_cpus).real, axes=(-2, -1))
@@ -879,7 +880,8 @@ def correlate_windows(window_a, window_b, correlation_method="fft",
def fft_correlate_windows(window_a, window_b,
rfft2 = rfft2_,
- irfft2 = irfft2_):
+ irfft2 = irfft2_,
+ settings=None):
""" FFT based cross correlation
it is a so-called linear convolution based,
since we increase the size of the FFT to
@@ -930,9 +932,9 @@ def fft_correlate_windows(window_a, window_b,
f2b = rfft2(window_b[::-1, ::-1], fsize)
corr = irfft2(f2a * f2b).real[fslice]
- #fft_a = b_rfft2(window_a, s=fsize, threads=20)
- #fft_b = b_rfft2(window_b, s=fsize, threads=20)
- #ifft_corr = b_irfft2(f2a * f2b, s=fsize, threads=20)
+ #fft_a = b_rfft2(window_a, s=fsize, threads = settings.num_cpus)
+ #fft_b = b_rfft2(window_b, s=fsize, threads = settings.num_cpus)
+ #ifft_corr = b_irfft2(f2a * f2b, s=fsize, threads = settings.num_cpus)
#f2a = fft_a()
#f2b = fft_b()
#corr = ifft_corr().real[fslice]
@@ -953,6 +955,7 @@ def extended_search_area_piv(
normalized_correlation: bool=False,
use_vectorized: bool=False,
max_array_size: int = None,
+ settings = None
):
"""Standard PIV cross-correlation algorithm, with an option for
extended area search that increased dynamic range. The search region
@@ -1114,9 +1117,9 @@ def extended_search_area_piv(
aa_aligned = empty_aligned((areas_per_block, search_area_size[0], search_area_size[1]), dtype=aa.dtype)
bb_aligned = empty_aligned((areas_per_block, search_area_size[0], search_area_size[1]), dtype=aa.dtype)
corr_aligned = empty_aligned((areas_per_block, search_area_size[0], int((search_area_size[1]/2)+1)), dtype=aa.dtype)
- f2a_builder = b_rfft2(aa_aligned, axes=(-2, -1), threads=20)
- f2b_builder = b_rfft2(bb_aligned, axes=(-2, -1), threads=20)
- corr_builder = b_irfft2(corr_aligned, axes=(-2, -1), threads=20)
+ f2a_builder = b_rfft2(aa_aligned, axes=(-2, -1), threads = settings.num_cpus)
+ f2b_builder = b_rfft2(bb_aligned, axes=(-2, -1), threads = settings.num_cpus)
+ corr_builder = b_irfft2(corr_aligned, axes=(-2, -1), threads = settings.num_cpus)
for i in range(num_blocks):
@@ -1129,7 +1132,8 @@ def extended_search_area_piv(
normalized_correlation=normalized_correlation,
f2a_builder =f2a_builder,
f2b_builder = f2b_builder,
- corr_builder = corr_builder
+ corr_builder = corr_builder,
+ settings=settings
)
u[block_start:block_end], v[block_start:block_end], invalid = vectorized_correlation_to_displacements(
@@ -1148,7 +1152,8 @@ def extended_search_area_piv(
normalized_correlation=normalized_correlation,
f2a_builder = None,
f2b_builder = None,
- corr_builder = None)
+ corr_builder = None,
+ settings=settings)
if use_vectorized:
u, v, invalid = vectorized_correlation_to_displacements(
diff --git a/openpiv/pyprocess3D.py b/openpiv/pyprocess3D.py
deleted file mode 100644
index 1b12a828..00000000
--- a/openpiv/pyprocess3D.py
+++ /dev/null
@@ -1,676 +0,0 @@
-import numpy.lib.stride_tricks
-import numpy as np
-from scipy.fft import rfftn, irfftn
-from numpy import ma
-from tqdm import tqdm
-from openpiv.pyprocess import get_field_shape, find_first_peak
-
-"""This module contains a pure python implementation of the basic
-cross-correlation algorithm for PIV image processing."""
-
-__licence_ = """
-Copyright (C) 2011 www.openpiv.net
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-
-def get_coordinates(image_size, search_area_size, window_size, overlap):
- """Compute the x, y coordinates of the centers of the interrogation windows.
-
- Parameters
- ----------
- image_size: two elements tuple
- a three dimensional tuple for the pixel size of the image
-
- window_size: tuple
- the size of the interrogation window.
-
- search_area_size: tuple
- the size of the search area window.
-
- overlap: tuple
- the number of pixel by which two adjacent interrogation
- windows overlap.
-
-
- Returns
- -------
- x : 23 np.ndarray
- a three dimensional array containing the x coordinates of the
- interrogation window centers, in pixels.
-
- y : 23 np.ndarray
- a three dimensional array containing the y coordinates of the
- interrogation window centers, in pixels.
-
- z : 23 np.ndarray
- a three dimensional array containing the y coordinates of the
- interrogation window centers, in pixels.
-
- """
-
- # get shape of the resulting flow field
- field_shape = get_field_shape(image_size, search_area_size, overlap)
-
- # compute grid coordinates of the search area centers
- x = (
- np.arange(field_shape[1]) * (window_size[1] - overlap[1])
- + (search_area_size[1] - 1) / 2.0
- )
- y = (
- np.arange(field_shape[0]) * (window_size[0] - overlap[0])
- + (search_area_size[0] - 1) / 2.0
- )
- z = (
- np.arange(field_shape[2]) * (window_size[2] - overlap[2])
- + (search_area_size[2] - 1) / 2.0
- )
-
- # moving coordinates further to the center, so that the points at the extreme left/right or top/bottom
- # have the same distance to the window edges. For simplicity only integer movements are allowed.
- x += (
- image_size[1]
- - 1
- - (
- (field_shape[1] - 1) * (window_size[1] - overlap[1])
- + (search_area_size[1] - 1)
- )
- ) // 2
- y += (
- image_size[0]
- - 1
- - (
- (field_shape[0] - 1) * (window_size[0] - overlap[0])
- + (search_area_size[0] - 1)
- )
- ) // 2
- z += (
- image_size[2]
- - 1
- - (
- (field_shape[2] - 1) * (window_size[2] - overlap[2])
- + (search_area_size[2] - 1)
- )
- ) // 2
-
- return np.meshgrid(x, y, z)
-
-
-def find_second_peak_3D(corr, i=None, j=None, z=None, width=2):
- """
- Find the value of the second largest peak.
-
- The second largest peak is the height of the peak in
- the region outside a 3x3 submatrix around the first
- correlation peak.
-
- Parameters
- ----------
- corr: np.ndarray
- the correlation map.
-
- i,j,z : ints
- row, column and layer location of the first peak.
-
- width : int
- the half size of the region around the first correlation
- peak to ignore for finding the second peak.
-
- Returns
- -------
- i : int
- the row index of the second correlation peak.
-
- j : int
- the column index of the second correlation peak.
-
- z : int
- the 3rd index of the second correlation peak.
-
-
- corr_max2 : int
- the value of the second correlation peak.
-
- """
-
- if i is None or j is None or z is None:
- (i, j, z), tmp = find_first_peak(corr) # TODO: why tmp?
-
- # create a masked view of the corr
- tmp = corr.view(ma.MaskedArray)
-
- # set width x width square submatrix around the first correlation peak as masked.
- # Before check if we are not too close to the boundaries, otherwise we
- # have negative indices
- iini = max(0, i - width)
- ifin = min(i + width + 1, corr.shape[0])
- jini = max(0, j - width)
- jfin = min(j + width + 1, corr.shape[1])
- zini = max(0, z - width)
- zfin = min(z + width + 1, corr.shape[1])
-
- tmp[iini:ifin, jini:jfin, zini:zfin] = ma.masked
- (i, j, z), corr_max2 = find_first_peak(tmp)
-
- return (i, j, z), corr_max2
-
-
-def find_subpixel_peak_position(corr, subpixel_method="gaussian"):
- """
- Find subpixel approximation of the correlation peak.
-
- This function returns a subpixels approximation of the correlation
- peak by using one of the several methods available. If requested,
- the function also returns the signal to noise ratio level evaluated
- from the correlation map.
-
- Parameters
- ----------
- corr : np.ndarray
- the correlation map.
-
- subpixel_method : string
- one of the following methods to estimate subpixel location of the peak:
- 'centroid' [replaces default if correlation map is negative],
- 'gaussian' [default if correlation map is positive],
- 'parabolic'.
-
- Returns
- -------
- subp_peak_position : two elements tuple
- the fractional row and column indices for the sub-pixel
- approximation of the correlation peak.
- """
-
- # initialization
- # default_peak_position = (np.floor(corr.shape[0] / 2.), np.floor(corr.shape[1] / 2.))
- default_peak_position = (0, 0, 0)
-
- # the peak locations
- (peak1_i, peak1_j, peak1_z), dummy = find_first_peak(corr)
-
- try:
- # the peak and its neighbours: left, right, down, up
- c = corr[peak1_i, peak1_j, peak1_z]
- cl = corr[peak1_i - 1, peak1_j, peak1_z]
- cr = corr[peak1_i + 1, peak1_j, peak1_z]
- cd = corr[peak1_i, peak1_j - 1, peak1_z]
- cu = corr[peak1_i, peak1_j + 1, peak1_z]
- cf = corr[peak1_i, peak1_j, peak1_z - 1]
- cb = corr[peak1_i, peak1_j, peak1_z + 1]
-
- # gaussian fit
- if (
- np.any(np.array([c, cl, cr, cd, cu, cf, cb]) < 0)
- and subpixel_method == "gaussian"
- ):
- subpixel_method = "centroid"
-
- try:
- if subpixel_method == "centroid":
- subp_peak_position = (
- ((peak1_i - 1) * cl + peak1_i * c + (peak1_i + 1) * cr)
- / (cl + c + cr),
- ((peak1_j - 1) * cd + peak1_j * c + (peak1_j + 1) * cu)
- / (cd + c + cu),
- ((peak1_z - 1) * cf + peak1_z * c + (peak1_z + 1) * cb)
- / (cf + c + cb),
- )
-
- elif subpixel_method == "gaussian":
- with numpy.errstate(divide="ignore"):
- subp_peak_position = (
- peak1_i
- + (
- (np.log(cl) - np.log(cr))
- / (2 * np.log(cl) - 4 * np.log(c) + 2 * np.log(cr))
- ),
- peak1_j
- + (
- (np.log(cd) - np.log(cu))
- / (2 * np.log(cd) - 4 * np.log(c) + 2 * np.log(cu))
- ),
- peak1_z
- + (
- (np.log(cf) - np.log(cb))
- / (2 * np.log(cf) - 4 * np.log(c) + 2 * np.log(cb))
- ),
- )
-
- elif subpixel_method == "parabolic":
- subp_peak_position = (
- peak1_i + (cl - cr) / (2 * cl - 4 * c + 2 * cr),
- peak1_j + (cd - cu) / (2 * cd - 4 * c + 2 * cu),
- peak1_z + (cf - cb) / (2 * cf - 4 * c + 2 * cb),
- )
- except:
- subp_peak_position = default_peak_position
-
- except IndexError:
- subp_peak_position = default_peak_position # TODO: is this a good idea??
-
- return np.array(subp_peak_position) - np.array(default_peak_position)
-
-
-def sig2noise_ratio(corr, sig2noise_method="peak2peak", width=2):
- """
- Computes the signal to noise ratio from the correlation map.
-
- The signal to noise ratio is computed from the correlation map with
- one of two available method. It is a measure of the quality of the
- matching between to interogation windows.
-
- Parameters
- ----------
- corr : 2d np.ndarray
- the correlation map.
-
- sig2noise_method: string
- the method for evaluating the signal to noise ratio value from
- the correlation map. Can be `peak2peak`, `peak2mean` or None
- if no evaluation should be made.
-
- width : int, optional
- the half size of the region around the first
- correlation peak to ignore for finding the second
- peak. [default: 2]. Only used if ``sig2noise_method==peak2peak``.
-
- Returns
- -------
- sig2noise : float
- the signal to noise ratio from the correlation map.
-
- """
-
- # compute first peak position
- (peak1_i, peak1_j, peak1_z), corr_max1 = find_first_peak(corr)
-
- # now compute signal to noise ratio
- if sig2noise_method == "peak2peak":
- # find second peak height
- (peak1_i, peak1_j, peak1_z), corr_max2 = find_second_peak_3D(
- corr, peak1_i, peak1_j, peak1_z, width=width
- )
-
- # if it's an empty interrogation window
- # if the image is lacking particles, totally black it will correlate to very low value, but not zero
- # if the first peak is on the borders, the correlation map is also wrong
- if corr_max1 < 1e-3 or any(
- [
- x == 0 or x == corr.shape[i]
- for i, x in enumerate([peak1_i, peak1_j, peak1_z])
- ]
- ):
- return 0.0
-
- elif sig2noise_method == "peak2mean":
- # find mean of the correlation map
- corr_max2 = corr.mean()
-
- else:
- raise ValueError("wrong sig2noise_method")
-
- # avoid dividing by zero
- try:
- sig2noise = corr_max1 / corr_max2
- except ValueError:
- sig2noise = np.inf
-
- return sig2noise
-
-
-def correlate_windows(
- window_a, window_b, correlation_method="fft", nfftx=None, nffty=None, nfftz=None
-):
- """Compute correlation function between two interrogation windows.
-
- The correlation function can be computed by using the correlation
- theorem to speed up the computation.
-
- Parameters
- ----------
- window_a : 2d np.ndarray
- a two dimensions array for the first interrogation window,
-
- window_b : 2d np.ndarray
- a two dimensions array for the second interrogation window.
-
- correlation_method : string
- one method is currently implemented: 'fft'.
-
- nfftx : int
- the size of the 2D FFT in x-direction,
- [default: 2 x windows_a.shape[0] is recommended].
-
- nffty : int
- the size of the 2D FFT in y-direction,
- [default: 2 x windows_a.shape[1] is recommended].
-
- nfftz : int
- the size of the 2D FFT in z-direction,
- [default: 2 x windows_a.shape[2] is recommended].
-
-
- Returns
- -------
- corr : 3d np.ndarray
- a three dimensional array of the correlation function.
-
- Note that due to the wish to use 2^N windows for faster FFT
- we use a slightly different convention for the size of the
- correlation map. The theory says it is M+N-1, and the
- 'direct' method gets this size out
- the FFT-based method returns M+N size out, where M is the window_size
- and N is the search_area_size
- It leads to inconsistency of the output
- """
-
- if correlation_method == "fft":
- window_b = np.conj(window_b[::-1, ::-1, ::-1])
- if nfftx is None:
- nfftx = nextpower2(window_b.shape[0] + window_a.shape[0])
- if nffty is None:
- nffty = nextpower2(window_b.shape[1] + window_a.shape[1])
- if nfftz is None:
- nfftz = nextpower2(window_b.shape[2] + window_a.shape[2])
-
- f2a = rfftn(normalize_intensity(window_a), s=(nfftx, nffty, nfftz))
- f2b = rfftn(normalize_intensity(window_b), s=(nfftx, nffty, nfftz))
- corr = irfftn(f2a * f2b).real
- corr = corr[
- : window_a.shape[0] + window_b.shape[0],
- : window_b.shape[1] + window_a.shape[1],
- : window_b.shape[2] + window_a.shape[2],
- ]
- return corr
- # elif correlation_method == 'direct':
- # return convolve2d(normalize_intensity(window_a),
- # normalize_intensity(window_b[::-1, ::-1, ::-1]), 'full')
- else:
- raise ValueError("method is not implemented")
-
-
-def normalize_intensity(window):
- """Normalize interrogation window by removing the mean value.
-
- Parameters
- ----------
- window : 2d np.ndarray
- the interrogation window array
-
- Returns
- -------
- window : 2d np.ndarray
- the interrogation window array, with mean value equal to zero.
-
- """
- return window - window.mean()
-
-
-def nextpower2(i):
- """ Find 2^n that is equal to or greater than. """
- n = 1
- while n < i:
- n *= 2
- return n
-
-
-def check_input(window_size, overlap, search_area_size, frame_a, frame_b):
- """ check the inputs for validity """
- # if isinstance(window_size, int):
- # window_size = (window_size, window_size)
- # if isinstance(search_area_size, int):
- # search_area_size = (search_area_size, search_area_size)
-
- search_area_size = [
- ws if x == 0 or x is None else x for x, ws in zip(search_area_size, window_size)
- ]
-
- if any((np.array(window_size) - np.array(overlap)) <= 0):
- raise ValueError("Overlap has to be smaller than the window_size")
-
- if any((np.array(search_area_size) - np.array(window_size)) < 0):
- raise ValueError("Search size cannot be smaller than the window_size")
-
- if any([ws > ims for ws, ims in zip(window_size, frame_a.shape)]):
- raise ValueError("window size cannot be larger than the image")
-
- if any([ims_a != ims_b for ims_a, ims_b in zip(frame_a.shape, frame_b.shape)]):
- raise ValueError("frame a and frame b have different sizes.")
-
- return window_size, overlap, search_area_size
-
-
-def extended_search_area_piv3D(
- frame_a,
- frame_b,
- window_size,
- overlap=(0, 0, 0),
- dt=(1.0, 1.0, 1.0),
- search_area_size=None,
- correlation_method="fft",
- subpixel_method="gaussian",
- sig2noise_method=None,
- width=2,
- nfftx=None,
- nffty=None,
- nfftz=None,
-):
- """Standard PIV cross-correlation algorithm, with an option for
- extended area search that increased dynamic range. The search region
- in the second frame is larger than the interrogation window size in the
- first frame.
-
- This is a pure python implementation of the standard PIV cross-correlation
- algorithm. It is a zero order displacement predictor, and no iterative
- process is performed.
-
- Parameters
- ----------
- frame_a : 3d np.ndarray
- an two dimensions array of integers containing grey levels of
- the first frame.
-
- frame_b : 3d np.ndarray
- an two dimensions array of integers containing grey levels of
- the second frame.
-
- window_size : tuple
- the size of the (square) interrogation window, [default: 32 pix].
-
- overlap : tuple
- the number of pixels by which two adjacent windows overlap
- [default: 16 pix].
-
- dt : tuple
- the time delay separating the two frames [default: 1.0].
-
- correlation_method : string
- only one method is currently implemented: 'fft'
-
- subpixel_method : string
- one of the following methods to estimate subpixel location of the peak:
- 'centroid' [replaces default if correlation map is negative],
- 'gaussian' [default if correlation map is positive],
- 'parabolic'.
-
- sig2noise_method : string
- defines the method of signal-to-noise-ratio measure,
- ('peak2peak' or 'peak2mean'. If None, no measure is performed.)
-
- nfftx : int
- the size of the 3D FFT in x-direction,
- [default: 2 x windows_a.shape[0] is recommended]
-
- nffty : int
- the size of the 3D FFT in y-direction,
- [default: 2 x windows_a.shape[1] is recommended]
-
- nfftz : int
- the size of the 3D FFT in z-direction,
- [default: 2 x windows_a.shape[2] is recommended]
-
- width : int
- the half size of the region around the first
- correlation peak to ignore for finding the second
- peak. [default: 2]. Only used if ``sig2noise_method==peak2peak``.
-
- search_area_size : tuple
- the size of the interrogation window in the second frame,
- default is the same interrogation window size and it is a
- fallback to the simplest FFT based PIV
-
-
- Returns
- -------
- u : 3d np.ndarray
- a three dimensional array containing the u velocity component,
- in pixels/seconds.
-
- v : 3d np.ndarray
- a three dimensional array containing the v velocity component,
- in pixels/seconds.
-
- w : 3d np.ndarray
- a three dimensional array containing the w velocity component,
- in pixels/seconds.
-
- sig2noise : 3d np.ndarray, (optional: only if sig2noise_method is not None)
- a three dimensional array the signal to noise ratio for each
- window pair.
-
- """
-
- # checking if the input is correct
- window_size, overlap, search_area_size = check_input(
- window_size, overlap, search_area_size, frame_a, frame_b
- )
-
- # get field shape
- field_shape = get_field_shape(frame_a.shape, search_area_size, overlap)
-
- u = np.zeros(field_shape)
- v = np.zeros(field_shape)
- w = np.zeros(field_shape)
-
- # if we want sig2noise information, allocate memory
- if sig2noise_method is not None:
- sig2noise = np.zeros(field_shape)
-
- # shift for x and y coordinates of the search area windows so that the centers of search area windows have
- # the same distances to the image edge at all sides. For simplicity only shifts by integers are allowed
- x_centering = (
- frame_a.shape[1]
- - 1
- - (
- (field_shape[1] - 1) * (window_size[1] - overlap[1])
- + (search_area_size[1] - 1)
- )
- ) // 2
- y_centering = (
- frame_a.shape[0]
- - 1
- - (
- (field_shape[0] - 1) * (window_size[0] - overlap[0])
- + (search_area_size[0] - 1)
- )
- ) // 2
- z_centering = (
- frame_a.shape[2]
- - 1
- - (
- (field_shape[2] - 1) * (window_size[2] - overlap[2])
- + (search_area_size[2] - 1)
- )
- ) // 2
-
- # loop over the interrogation windows
- # i, j are the row, column indices of the center of each interrogation
- # window
- for k in tqdm(range(field_shape[0])):
- for m in range(field_shape[1]):
- for l in range(field_shape[2]):
-
- # centers of search area. (window_size - overlap) defines the distance between each center
- # and (search_area_size - 1)/2.0 moves the center points away from the left or top image edge
- y = k * (window_size[0] - overlap[0]) + (search_area_size[0] - 1) / 2.0
- x = m * (window_size[1] - overlap[1]) + (search_area_size[1] - 1) / 2.0
- z = l * (window_size[2] - overlap[2]) + (search_area_size[2] - 1) / 2.0
-
- # moving the coordinates a bit to the center, to guarantee that the distance of a extreme
- # point at the image edges is symmetric all all edges
- x += x_centering
- y += y_centering
- z += z_centering
-
- # left, right, top, bottom, front, back indices of the search area edges
- # note that x - (search_area_size +/- 1)/2 always returns an integer due to the definition of x and y
- # see also "get_coordinates()"
- il = int(y - (search_area_size[0] - 1) / 2.0)
- ir = int(y + (search_area_size[0] + 1) / 2.0)
- it = int(x - (search_area_size[1] - 1) / 2.0)
- ib = int(x + (search_area_size[1] + 1) / 2.0)
- ifr = int(z - (search_area_size[2] - 1) / 2.0)
- iba = int(z + (search_area_size[2] + 1) / 2.0)
- # picking the search area from frame b
- window_b = frame_b[il:ir, it:ib, ifr:iba]
-
- # left, right, top, bottom, front, back indices of the interrogation window
- # Sometimes the interrogation window cannot be placed in the middle of the search area, e.g.
- # in the case of window_size=3 search_area_size=4. In this case the interrogation window
- # is shifted 0.5 pixels to the left/top, which is achieved by rounding the indices
- # down during the int() conversion
- il = int(y - (window_size[0] - 1) / 2)
- ir = int(y + (window_size[0] + 1) / 2)
- it = int(x - (window_size[1] - 1) / 2)
- ib = int(x + (window_size[1] + 1) / 2)
- ifr = int(z - (window_size[2] - 1) / 2)
- iba = int(z + (window_size[2] + 1) / 2)
- # picking the interrogation window from frame a
- window_a = frame_a[il:ir, it:ib, ifr:iba]
-
- if np.any(window_a):
- corr = correlate_windows(
- window_a,
- window_b,
- correlation_method=correlation_method,
- nfftx=nfftx,
- nffty=nffty,
- nfftz=nfftz,
- )
-
- # get subpixel approximation for peak position row and column index
- row, col, z = find_subpixel_peak_position(
- corr, subpixel_method=subpixel_method
- )
-
- row -= (search_area_size[0] + window_size[0] - 1) // 2
- col -= (search_area_size[1] + window_size[1] - 1) // 2
- z -= (search_area_size[2] + window_size[2] - 1) // 2
-
- # get displacements, apply coordinate system definition
- u[k, m, l], v[k, m, l], w[k, m, l] = col, -row, -z
-
- # get signal to noise ratio
- if sig2noise_method is not None:
- sig2noise[k, m, l] = sig2noise_ratio(
- corr, sig2noise_method=sig2noise_method, width=width
- )
-
- # return output if user wanted sig2noise information
- if sig2noise_method is not None:
- return u / dt[0], v / dt[1], w / dt[2], sig2noise
- else:
- return u / dt[0], v / dt[1], w / dt[2]
diff --git a/openpiv/pyprocess_gpu.py b/openpiv/pyprocess_gpu.py
index e497dc1b..ddbe921a 100644
--- a/openpiv/pyprocess_gpu.py
+++ b/openpiv/pyprocess_gpu.py
@@ -9,6 +9,8 @@
from numpy.fft import rfft2 as rfft2_, irfft2 as irfft2_, fftshift as fftshift_
from scipy.signal import convolve2d as conv_
+from datetime import datetime
+
import cupy as cp
__licence_ = """
@@ -185,6 +187,7 @@ def sliding_window_array(
image: np.ndarray,
window_size: Tuple[int,int]=(64,64),
overlap: Tuple[int,int]=(32,32),
+ block_range = None
)-> np.ndarray:
'''
This version does not use numpy as_strided and is much more memory efficient.
@@ -200,13 +203,19 @@ def sliding_window_array(
# overlap = (overlap, overlap)
x, y = get_rect_coordinates(image.shape, window_size, overlap, center_on_field = False)
- x = (x - window_size[1]//2).astype(int)
- y = (y - window_size[0]//2).astype(int)
- x, y = np.reshape(x, (-1,1,1)), np.reshape(y, (-1,1,1))
+ x = (x - window_size[1]//2).astype(int).flatten()
+ y = (y - window_size[0]//2).astype(int).flatten()
win_x, win_y = np.meshgrid(np.arange(0, window_size[1]), np.arange(0, window_size[0]))
- win_x = win_x[np.newaxis,:,:] + x
- win_y = win_y[np.newaxis,:,:] + y
+ if block_range is None:
+ win_x = win_x[None,:,:] + x[:, None, None]
+ win_y = win_y[None,:,:] + y[:, None, None]
+
+ else:
+ win_x = win_x[None,:,:] + x[block_range[0]:block_range[1], None, None]
+ win_y = win_y[None,:,:] + y[block_range[0]:block_range[1], None, None]
+
+
windows = image[win_y, win_x]
return windows
@@ -924,7 +933,8 @@ def extended_search_area_piv(
width: int=2,
normalized_correlation: bool=False,
use_vectorized: bool=False,
-):
+ max_array_size: int = None,
+ ):
"""Standard PIV cross-correlation algorithm, with an option for
extended area search that increased dynamic range. The search region
in the second frame is larger than the interrogation window size in the
@@ -1049,10 +1059,7 @@ def extended_search_area_piv(
# get field shape
n_rows, n_cols = get_field_shape(frame_a.shape, search_area_size, overlap)
-
- # We implement the new vectorized code
- aa = sliding_window_array(frame_a, search_area_size, overlap)
- bb = sliding_window_array(frame_b, search_area_size, overlap)
+ num_areas = n_rows * n_cols
# for the case of extended seearch, the window size is smaller than
# the search_area_size. In order to keep it all vectorized the
@@ -1077,19 +1084,73 @@ def extended_search_area_piv(
mask = np.broadcast_to(mask, aa.shape)
aa *= mask
- corr = fft_correlate_images(aa, bb,
+
+ #full_arr_size = np.uint64(num_areas * window_size[0] * window_size[1])
+ #print(f'full_arr_size: {full_arr_size}')
+ #print(f'max_array_size: {max_array_size}')
+
+ if max_array_size is not None and num_areas > (max_array_size/ (window_size[0] * window_size[1])):
+
+ total_bad = 0
+ u, v = np.zeros(n_rows * n_cols), np.zeros(n_rows * n_cols)
+ area_size = search_area_size[0] * search_area_size[1]
+ #print(f'area_size: {area_size}')
+ areas_per_block = int(max_array_size // area_size)
+ #print(f'areas_per_block: {areas_per_block}')
+ num_blocks = int(np.ceil(num_areas / areas_per_block))
+ #print(f'num_blocks: {num_blocks}')
+
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: {num_blocks} blocks starting')
+ for i in range(num_blocks):
+
+ block_start, block_end = i*areas_per_block, (i+1)*areas_per_block
+
+ aa = sliding_window_array(frame_a, search_area_size, overlap,
+ block_range=(block_start, block_end))
+ bb = sliding_window_array(frame_b, search_area_size, overlap,
+ block_range=(block_start, block_end))
+
+ corr = fft_correlate_images(
+ aa, bb,
+ correlation_method=correlation_method,
+ normalized_correlation=normalized_correlation
+ )
+
+ aa, bb = None, None
+ mempool.free_all_blocks()
+
+ u[block_start:block_end], v[block_start:block_end], invalid = vectorized_correlation_to_displacements(
+ corr, subpixel_method=subpixel_method
+ )
+
+ total_bad += invalid
+
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: Block {i+1} / {num_blocks} : {total_bad} bad peaks so far', end='\r')
+
+ perc = 100*(total_bad/(2*num_areas))
+ print(f'\t{now.strftime("%H:%M:%S")}: All {num_blocks} blocks complete : {total_bad} ({perc:.2f}%) bad peaks')
+ u, v = u.reshape((n_rows, n_cols)), v.reshape((n_rows, n_cols))
+
+ else:
+ aa = sliding_window_array(frame_a, search_area_size, overlap)
+ bb = sliding_window_array(frame_b, search_area_size, overlap)
+ corr = fft_correlate_images(aa, bb,
correlation_method=correlation_method,
normalized_correlation=normalized_correlation)
- aa, bb = None, None
- mempool.free_all_blocks()
+ aa, bb = None, None
+ mempool.free_all_blocks()
- if use_vectorized is True:
- u, v = vectorized_correlation_to_displacements(corr, n_rows, n_cols,
- subpixel_method=subpixel_method)
- else:
- raise NotImplementedError('correlation_to_displacement')
- u, v = correlation_to_displacement(corr, n_rows, n_cols,
- subpixel_method=subpixel_method)
+ if use_vectorized is True:
+ u, v, invalid = vectorized_correlation_to_displacements(corr, n_rows, n_cols,
+ subpixel_method=subpixel_method)
+ perc = 100*(invalid/(2*num_areas))
+ print('\t{0} ({1:.2f}%) bad peaks'.format(invalid, perc))
+ else:
+ raise NotImplementedError('correlation_to_displacement')
+ u, v = correlation_to_displacement(corr, n_rows, n_cols,
+ subpixel_method=subpixel_method)
# return output depending if user wanted sig2noise information
if sig2noise_method is not None:
@@ -1195,7 +1256,7 @@ def vectorized_correlation_to_displacements(corr: np.ndarray,
peaks1_i[invalid] = corr.shape[1] // 2 # temp. so no errors would be produced
peaks1_j[invalid] = corr.shape[2] // 2
- print(f"Found {len(invalid)} bad peak(s)")
+ #print(f"Found {len(invalid)} bad peak(s)")
if len(invalid) == corr.shape[0]: # in case something goes horribly wrong
return np.zeros((np.size(corr, 0), 2))*np.nan
@@ -1229,7 +1290,7 @@ def vectorized_correlation_to_displacements(corr: np.ndarray,
den2 = 2 * log(cd) - 4 * log(c) + 2 * log(cu)
if not (np.all(den1 != 0.0) and np.all(den2 != 0.0)):
- print('rawhsdh, division by 0')
+ print('\trawhsdh, division by 0')
shift_i = nom1 / den1
shift_j = nom2 / den2
# shift_i = np.divide(
@@ -1265,9 +1326,9 @@ def vectorized_correlation_to_displacements(corr: np.ndarray,
#disp[ind, :] = np.vstack((disp_vx, disp_vy)).T
#return disp[:,0].reshape((n_rows, n_cols)), disp[:,1].reshape((n_rows, n_cols))
if n_rows == None or n_cols == None:
- return disp_vx.get(), disp_vy.get()
+ return disp_vx.get(), disp_vy.get(), len(invalid)
else:
- return disp_vx.get().reshape((n_rows, n_cols)), disp_vy.get().reshape((n_rows, n_cols))
+ return disp_vx.get().reshape((n_rows, n_cols)), disp_vy.get().reshape((n_rows, n_cols)), len(invalid)
def nextpower2(i):
diff --git a/openpiv/pyprocess_gpu_cpu.py b/openpiv/pyprocess_gpu_cpu.py
index c0a00063..1e981fc2 100644
--- a/openpiv/pyprocess_gpu_cpu.py
+++ b/openpiv/pyprocess_gpu_cpu.py
@@ -9,6 +9,8 @@
from numpy.fft import rfft2 as rfft2_, irfft2 as irfft2_, fftshift as fftshift_
from scipy.signal import convolve2d as conv_
+from datetime import datetime
+
import cupy as cp
__licence_ = """
@@ -185,6 +187,7 @@ def sliding_window_array(
image: np.ndarray,
window_size: Tuple[int,int]=(64,64),
overlap: Tuple[int,int]=(32,32),
+ block_range = None
)-> np.ndarray:
'''
This version does not use numpy as_strided and is much more memory efficient.
@@ -200,13 +203,19 @@ def sliding_window_array(
# overlap = (overlap, overlap)
x, y = get_rect_coordinates(image.shape, window_size, overlap, center_on_field = False)
- x = (x - window_size[1]//2).astype(int)
- y = (y - window_size[0]//2).astype(int)
- x, y = np.reshape(x, (-1,1,1)), np.reshape(y, (-1,1,1))
+ x = (x - window_size[1]//2).astype(int).flatten()
+ y = (y - window_size[0]//2).astype(int).flatten()
win_x, win_y = np.meshgrid(np.arange(0, window_size[1]), np.arange(0, window_size[0]))
- win_x = win_x[np.newaxis,:,:] + x
- win_y = win_y[np.newaxis,:,:] + y
+ if block_range is None:
+ win_x = win_x[None,:,:] + x[:, None, None]
+ win_y = win_y[None,:,:] + y[:, None, None]
+
+ else:
+ win_x = win_x[None,:,:] + x[block_range[0]:block_range[1], None, None]
+ win_y = win_y[None,:,:] + y[block_range[0]:block_range[1], None, None]
+
+
windows = image[win_y, win_x]
return windows
@@ -924,7 +933,8 @@ def extended_search_area_piv(
width: int=2,
normalized_correlation: bool=False,
use_vectorized: bool=False,
-):
+ max_array_size: int = None,
+ ):
"""Standard PIV cross-correlation algorithm, with an option for
extended area search that increased dynamic range. The search region
in the second frame is larger than the interrogation window size in the
@@ -1049,10 +1059,7 @@ def extended_search_area_piv(
# get field shape
n_rows, n_cols = get_field_shape(frame_a.shape, search_area_size, overlap)
-
- # We implement the new vectorized code
- aa = sliding_window_array(frame_a, search_area_size, overlap)
- bb = sliding_window_array(frame_b, search_area_size, overlap)
+ num_areas = n_rows * n_cols
# for the case of extended seearch, the window size is smaller than
# the search_area_size. In order to keep it all vectorized the
@@ -1077,19 +1084,71 @@ def extended_search_area_piv(
mask = np.broadcast_to(mask, aa.shape)
aa *= mask
- corr = fft_correlate_images(aa, bb,
+
+ #full_arr_size = np.uint64(num_areas * window_size[0] * window_size[1])
+ #print(f'full_arr_size: {full_arr_size}')
+ #print(f'max_array_size: {max_array_size}')
+
+ if max_array_size is not None and num_areas > (max_array_size/ (window_size[0] * window_size[1])):
+
+ total_bad = 0
+ u, v = np.zeros(n_rows * n_cols), np.zeros(n_rows * n_cols)
+ area_size = search_area_size[0] * search_area_size[1]
+ #print(f'area_size: {area_size}')
+ areas_per_block = int(max_array_size // area_size)
+ #print(f'areas_per_block: {areas_per_block}')
+ num_blocks = int(np.ceil(num_areas / areas_per_block))
+ #print(f'num_blocks: {num_blocks}')
+
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: {num_blocks} blocks starting')
+ for i in range(num_blocks):
+
+ block_start, block_end = i*areas_per_block, (i+1)*areas_per_block
+
+ aa = sliding_window_array(frame_a, search_area_size, overlap,
+ block_range=(block_start, block_end))
+ bb = sliding_window_array(frame_b, search_area_size, overlap,
+ block_range=(block_start, block_end))
+
+ corr = fft_correlate_images(
+ aa, bb,
+ correlation_method=correlation_method,
+ normalized_correlation=normalized_correlation
+ )
+
+ aa, bb = None, None
+ mempool.free_all_blocks()
+
+ u[block_start:block_end], v[block_start:block_end], invalid = vectorized_correlation_to_displacements(
+ corr, subpixel_method=subpixel_method
+ )
+
+ total_bad += invalid
+
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: Block {i+1} / {num_blocks} : {total_bad} bad peaks so far', end='\r')
+
+ print(f'\t{now.strftime("%H:%M:%S")}: All {num_blocks} blocks complete : {total_bad} bad peaks')
+ u, v = u.reshape((n_rows, n_cols)), v.reshape((n_rows, n_cols))
+
+ else:
+ aa = sliding_window_array(frame_a, search_area_size, overlap)
+ bb = sliding_window_array(frame_b, search_area_size, overlap)
+ corr = fft_correlate_images(aa, bb,
correlation_method=correlation_method,
normalized_correlation=normalized_correlation)
- aa, bb = None, None
- mempool.free_all_blocks()
+ aa, bb = None, None
+ mempool.free_all_blocks()
- if use_vectorized is True:
- u, v = vectorized_correlation_to_displacements(corr, n_rows, n_cols,
- subpixel_method=subpixel_method)
- else:
- raise NotImplementedError('correlation_to_displacement')
- u, v = correlation_to_displacement(corr, n_rows, n_cols,
- subpixel_method=subpixel_method)
+ if use_vectorized is True:
+ u, v, invalid = vectorized_correlation_to_displacements(corr, n_rows, n_cols,
+ subpixel_method=subpixel_method)
+ print('\t{0} bad peaks'.format(invalid))
+ else:
+ raise NotImplementedError('correlation_to_displacement')
+ u, v = correlation_to_displacement(corr, n_rows, n_cols,
+ subpixel_method=subpixel_method)
# return output depending if user wanted sig2noise information
if sig2noise_method is not None:
@@ -1195,7 +1254,7 @@ def vectorized_correlation_to_displacements(corr: np.ndarray,
peaks1_i[invalid] = corr.shape[1] // 2 # temp. so no errors would be produced
peaks1_j[invalid] = corr.shape[2] // 2
- print(f"Found {len(invalid)} bad peak(s)")
+ #print(f"Found {len(invalid)} bad peak(s)")
if len(invalid) == corr.shape[0]: # in case something goes horribly wrong
return np.zeros((np.size(corr, 0), 2))*np.nan
@@ -1265,9 +1324,9 @@ def vectorized_correlation_to_displacements(corr: np.ndarray,
#disp[ind, :] = np.vstack((disp_vx, disp_vy)).T
#return disp[:,0].reshape((n_rows, n_cols)), disp[:,1].reshape((n_rows, n_cols))
if n_rows == None or n_cols == None:
- return disp_vx, disp_vy
+ return disp_vx, disp_vy, len(invalid)
else:
- return disp_vx.reshape((n_rows, n_cols)), disp_vy.reshape((n_rows, n_cols))
+ return disp_vx.reshape((n_rows, n_cols)), disp_vy.reshape((n_rows, n_cols)), len(invalid)
def nextpower2(i):
diff --git a/openpiv/settings.py b/openpiv/settings.py
new file mode 100644
index 00000000..d818a1e0
--- /dev/null
+++ b/openpiv/settings.py
@@ -0,0 +1,162 @@
+import pathlib
+from dataclasses import dataclass
+from importlib_resources import files
+from typing import Optional, Tuple, Union
+import numpy as np
+
+@dataclass
+class PIVSettings:
+ """ All the settings for PIV. Default settings are set at the initiation"""
+
+ "Data related settings"
+
+ # Input directory (containing images to be processed)
+ filepath_images: Union[pathlib.Path, str] = files('openpiv') / "data" / "test1" # type: ignore
+
+ # Format and Image Sequence
+ frame_pattern_a: str = 'exp1_001_a.bmp'
+ frame_pattern_b: str = 'exp1_001_b.bmp'
+
+ # Output directory
+ save_directory: pathlib.Path = filepath_images.parent
+
+ # Output filename
+ save_filename: str = 'test1'
+
+ "Region of interest"
+
+ # (xmin,xmax,ymin,ymax) or 'full' for full image
+ roi: Union[Tuple[int, int, int, int], str] = "full"
+
+ "Image preprocessing"
+
+ # Every image would be processed separately and the
+ # average mask is applied to both A, B, but it's varying
+ # for the frames sequence
+ #: None for no masking
+ #: 'edges' for edges masking,
+ #: 'intensity' for intensity masking
+ dynamic_masking_method: Optional[str] = None # ['edge','intensity']
+ dynamic_masking_threshold: float = 0.005
+ dynamic_masking_filter_size: int = 7
+
+ # Static masking applied to all images, A,B
+ static_mask: Optional[np.ndarray] = None # or a boolean matrix of image shape
+
+ "Processing Parameters"
+
+ correlation_method: str="circular" # ['circular', 'linear']
+ normalized_correlation: bool = False
+
+ # add the interroagtion window size for each pass.
+ # For the moment, it should be a power of 2
+ windowsizes: Tuple[int, ...] = (64,32,16)
+
+ # The overlap of the interroagtion window for each pass.
+ overlap: Tuple[int, ...] = (32, 16, 8) # This is 50% overlap
+
+ # Has to be a value with base two. In general window size/2 is a good
+ # choice.
+
+ num_iterations: int = len(windowsizes) # select the number of PIV passes
+
+ # methode used for subpixel interpolation:
+ # 'gaussian','centroid','parabolic'
+ subpixel_method: str = "gaussian"
+ # use vectorized sig2noise and subpixel approximation functions
+ use_vectorized: bool = True
+ # 'symmetric' or 'second image', 'symmetric' splits the deformation
+ # both images, while 'second image' does only deform the second image.
+ deformation_method: str = 'second image' # 'symmetric' or 'second image'
+ # order of the image interpolation for the window deformation
+ interpolation_order: int = 3
+ scaling_factor: float = 1.0 # scaling factor pixel/meter
+ dt: float = 1.0 # time between to frames (in seconds)
+
+ # Signal to noise ratio:
+ # we can decide to estimate it or not at every vector position
+ # we can decided if we use it for validation or only store it for
+ # later post-processing
+ # plus we need some parameters for threshold validation and for the
+ # calculations:
+
+ sig2noise_method: Optional[str] = None # or "peak2peak" or "None"
+ # select the width of the masked to masked out pixels next to the main
+ # peak
+ sig2noise_mask: int = 2
+ # If extract_sig2noise::False the values in the signal to noise ratio
+ # output column are set to NaN
+
+ # "Validation based on the signal to noise ratio"
+ # Note: only available when extract_sig2noise::True and only for the
+ # last pass of the interrogation
+ # Enable the signal to noise ratio validation. Options: True or False
+ # sig2noise_validate: False # This is time consuming
+ # minmum signal to noise ratio that is need for a valid vector
+ sig2noise_threshold: float = 1.0
+ sig2noise_validate: bool = False # when it's False we can save time by not
+ #estimating sig2noise ratio at all, so we can set both sig2noise_method to None
+
+
+ "vector validation options"
+
+ # choose if you want to do validation of the first pass: True or False
+ validation_first_pass: bool = False
+ # only effecting the first pass of the interrogation the following
+ # passes in the multipass will be validated
+
+ "Validation Parameters"
+
+ # The validation is done at each iteration based on three filters.
+ # The first filter is based on the min/max ranges. Observe that these
+ # values are defined in
+ # terms of minimum and maximum displacement in pixel/frames.
+ min_max_validate: bool = False
+ min_max_u_disp: Tuple = (-10000, 10000)
+ min_max_v_disp: Tuple = (-10000, 10000)
+
+ # The second filter is based on the global STD threshold
+ std_validate: bool = False
+ std_threshold: int = 7 # threshold of the std validation
+
+ # The third filter is the median test (not normalized at the moment)
+ median_validate: bool = False
+ median_threshold: int = 3 # threshold of the median validation
+ # On the last iteration, an additional validation can be done based on
+ # the S/N.
+ median_size: int = 1 # defines the size of the local median
+
+ "Outlier replacement or Smoothing options"
+
+ # Replacment options for vectors which are masked as invalid by the
+ # validation
+ # Choose: True or False
+ replace_vectors: bool = True # Enable the replacement.
+ smoothn: bool = False # Enables smoothing of the displacement field
+ smoothn_p: float = 0.5 # This is a smoothing parameter
+ # select a method to replace the outliers:
+ # 'localmean', 'disk', 'distance'
+ filter_method: str = "localmean"
+ # maximum iterations performed to replace the outliers
+ max_filter_iteration: int = 3
+ filter_kernel_size: int = 2 # kernel size for the localmean method
+
+ "Output options"
+
+ # Select if you want to save the plotted vectorfield: True or False
+ save_plot: bool = False
+ # Choose wether you want to see the vectorfield or not:True or False
+ show_plot: bool = False
+ scale_plot: int = 100 # select a value to scale the quiver plot of
+ # the vectorfield run the script with the given settings
+
+ show_all_plots: bool=False
+
+ invert: bool = False # for the test_invert
+
+ fmt: str = "%.6e"
+
+ "CPU/GPU settings"
+
+ num_cpus: int = 1
+ max_array_size: int = None
\ No newline at end of file
diff --git a/openpiv/test/test_pyprocess3D.py b/openpiv/test/test_pyprocess3D.py
deleted file mode 100644
index c66a6c84..00000000
--- a/openpiv/test/test_pyprocess3D.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from openpiv.pyprocess3D import extended_search_area_piv3D
-import numpy as np
-
-from skimage.util import random_noise
-from skimage import img_as_ubyte
-
-from scipy.ndimage import shift as shift_img
-
-# import warnings
-
-threshold = 0.1
-
-
-def dist(u, shift):
- return np.mean(np.abs(u - shift))
-
-
-def create_pair(image_size=32, u=3, v=2, w=1):
- """ creates a pair of images with a roll/shift """
- frame_a = np.zeros((image_size, image_size, image_size))
- frame_a = random_noise(frame_a)
- frame_a = img_as_ubyte(frame_a)
- # note rolling positive vertical +2 means we create
- # negative vertical velocity as our origin is at 0,0
- # bottom left corner, and the image is rolled from the
- # top left corner
-
- frame_b = shift_img(frame_a, (v, u, w))
- return frame_a.astype(np.int32), frame_b.astype(np.int32)
-
-
-def test_piv():
- """
- test for 3D PIV with window_size==search_area_size
- """
- frame_a, frame_b = create_pair(image_size=32)
- u, v, w = extended_search_area_piv3D(
- frame_a, frame_b, window_size=(10, 10, 10), search_area_size=(10, 10, 10)
- )
- assert dist(u, -3) < threshold
- assert dist(v, 2) < threshold
- assert dist(w, 1) < threshold
-
-
-def test_piv_extended_search_area():
-
- """
- test for 3D PIV with larger search_area_size
- """
- frame_a, frame_b = create_pair(image_size=32)
- u, v, w = extended_search_area_piv3D(
- frame_a, frame_b, window_size=(10, 10, 10), search_area_size=(15, 15, 15)
- )
- assert dist(u, -3) < threshold
- assert dist(v, 2) < threshold
- assert dist(w, 1) < threshold
diff --git a/openpiv/tools.py b/openpiv/tools.py
index 46a5a6db..a1478b98 100644
--- a/openpiv/tools.py
+++ b/openpiv/tools.py
@@ -30,6 +30,8 @@
import matplotlib.patches as pt
from natsort import natsorted
+from datetime import datetime
+
# from builtins import range
from imageio.v3 import imread as _imread, imwrite as _imsave
from skimage.feature import canny
@@ -391,6 +393,7 @@ def save(
v: np.ndarray,
flags: Optional[np.ndarray] = None,
mask: Optional[np.ndarray] = None,
+ settings = None,
fmt: str="%.4e",
delimiter: str="\t",
)-> None:
@@ -425,6 +428,7 @@ def save(
mask: 2d np.ndarray boolean, marks the image masked regions (dynamic and/or static)
default: None - will be all False
+ settings: openpiv.settings.PIVSettings
fmt : string
a format string. See documentation of numpy.savetxt
@@ -450,28 +454,27 @@ def save(
if flags is None:
flags = np.zeros_like(u, dtype=int)
- # build output array
- out = np.vstack([m.flatten() for m in [x, y, u, v, flags, mask]])
-
- # save data to file.
- np.savetxt(
- filename,
- out.T,
- fmt=fmt,
- delimiter=delimiter,
- header="x"
- + delimiter
- + "y"
- + delimiter
- + "u"
- + delimiter
- + "v"
- + delimiter
- + "flags"
- + delimiter
- + "mask",
- )
-
+ extension = str(filename).split('.')[-1].lower()
+ # save data to an ascii txt file
+ if extension == 'txt':
+ out = np.vstack([m.flatten() for m in [x, y, u, v, flags, mask]])
+ np.savetxt(
+ filename, out.T, fmt=settings.fmt, delimiter=delimiter,
+ header="x" + delimiter + "y" + delimiter + "u"+ delimiter + "v" + delimiter + "flags" + delimiter + "mask",
+ )
+ # save data to a numpy npz file
+ elif extension == 'npz':
+ binning = settings.overlap[-1]
+ shape = u.shape
+
+ np.savez(
+ filename,
+ x = x, y = y, u = u, v = v,
+ format = 'OpenPIV', version = 'n/a',
+ binning = binning, shape = shape,
+ flags = flags, mask = mask)
+ else:
+ raise ValueError('File extension not supported. Use txt or npz')
def display(message):
"""Display a message to standard output.
diff --git a/openpiv/tutorials/masking_tutorial.py b/openpiv/tutorials/masking_tutorial.py
deleted file mode 100644
index 4fe6e9f9..00000000
--- a/openpiv/tutorials/masking_tutorial.py
+++ /dev/null
@@ -1,83 +0,0 @@
-import pathlib
-from importlib_resources import files
-import numpy as np
-import matplotlib.pyplot as plt
-from openpiv import tools, scaling, pyprocess, validation, filters,preprocess
-
-# we can run it from any folder
-path = files('openpiv') / "data" / "test4"
-
-im_a = tools.imread( path / "Camera1-0101.tif")
-im_b = tools.imread( path / "Camera1-0102.tif")
-
-plt.imshow(np.c_[im_a,im_b],cmap='gray')
-
-# let's crop the region of interest
-frame_a = im_a[380:1980,0:1390]
-frame_b = im_b[380:1980,0:1390]
-plt.imshow(np.c_[frame_a,frame_b],cmap='gray')
-
-# Process the original cropped image and see the OpenPIV result:
-
-# typical parameters:
-window_size = 32 #pixels
-overlap = 16 # pixels
-search_area_size = 64 # pixels
-frame_rate = 40 # fps
-
-# process again with the masked images, for comparison# process once with the original images
-u, v, sig2noise = pyprocess.extended_search_area_piv(
- frame_a.astype(np.int32) , frame_b.astype(np.int32),
- window_size = window_size,
- overlap = overlap,
- dt=1./frame_rate,
- search_area_size = search_area_size,
- sig2noise_method = 'peak2peak')
-x, y = pyprocess.get_coordinates( image_size = frame_a.shape, search_area_size = search_area_size, overlap = overlap )
-flags_g = validation.global_val( u, v, (-300.,300.),(-300.,300.))
-flags_s2n = validation.sig2noise_val(sig2noise, threshold = 1.1 )
-flags = flags_g | flags_s2n
-u, v = filters.replace_outliers( u, v, flags, method='localmean', max_iter = 3, kernel_size = 3)
-x, y, u, v = scaling.uniform(x, y, u, v, scaling_factor = 96.52 )
-x, y, u, v = tools.transform_coordinates(x, y, u, v)
-# save to a file
-tools.save(path / 'test.txt', x, y, u, v, flags, fmt='%9.6f', delimiter='\t')
-tools.display_vector_field( path / 'test.txt', scale=50, width=0.002)
-
-
-
-# masking using not optimal choice of the methods or parameters:
-masked_a, _ = preprocess.dynamic_masking(frame_a,method='edges',filter_size=7,threshold=0.005)
-masked_b, _ = preprocess.dynamic_masking(frame_b,method='intensity',filter_size=3,threshold=0.005)
-plt.imshow(np.c_[masked_a,masked_b],cmap='gray')
-
-
-
-# masking using optimal (manually tuned) set of parameters and the right method:
-masked_a, _ = preprocess.dynamic_masking(frame_a,method='edges',filter_size=7,threshold=0.01)
-masked_b, _ = preprocess.dynamic_masking(frame_b,method='edges',filter_size=7,threshold=0.01)
-plt.imshow(np.c_[masked_a,masked_b],cmap='gray')
-
-
-
-# Process the masked cropped image and see the OpenPIV result:
-
-# process again with the masked images, for comparison# process once with the original images
-u, v, sig2noise = pyprocess.extended_search_area_piv(
- masked_a.astype(np.int32) , masked_b.astype(np.int32),
- window_size = window_size,
- overlap = overlap,
- dt=1./frame_rate,
- search_area_size = search_area_size,
- sig2noise_method = 'peak2peak')
-x, y = pyprocess.get_coordinates( image_size = masked_a.shape, search_area_size = search_area_size, overlap = overlap )
-flags_g = validation.global_val( u, v, (-300.,300.),(-300.,300.))
-flags_s2n = validation.sig2noise_val( sig2noise, threshold = 1.1)
-flags = flags_g | flags_s2n
-u, v = filters.replace_outliers( u, v, flags, method='localmean', max_iter = 3, kernel_size = 3)
-x, y, u, v = scaling.uniform(x, y, u, v, scaling_factor = 96.52 )
-x, y, u, v = tools.transform_coordinates(x, y, u, v)
-# save to a file
-tools.save(path / 'test_masked.txt', x, y, u, v, flags, None, fmt='%9.6f', delimiter='\t')
-tools.display_vector_field( path / 'test_masked.txt', scale=50, width=0.002)
-
diff --git a/openpiv/tutorials/tutorial1.py b/openpiv/tutorials/tutorial1.py
deleted file mode 100644
index 1a1f2750..00000000
--- a/openpiv/tutorials/tutorial1.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from importlib_resources import files
-import numpy as np
-from openpiv import tools, pyprocess, scaling, validation, filters
-
-# we can run it from any folder
-path = files('openpiv') / "data" / "test1"
-
-
-frame_a = tools.imread( path / "exp1_001_a.bmp" )
-frame_b = tools.imread( path / "exp1_001_b.bmp" )
-
-frame_a = frame_a.astype(np.int32)
-frame_b = frame_b.astype(np.int32)
-
-u, v, sig2noise = pyprocess.extended_search_area_piv( frame_a, frame_b, \
- window_size=32, overlap=16, dt=1., search_area_size=64, sig2noise_method='peak2peak' )
-
-print(u,v,sig2noise)
-
-x, y = pyprocess.get_coordinates( image_size=frame_a.shape, search_area_size=64, overlap=16 )
-flags_s2n = validation.sig2noise_val(sig2noise, threshold = 1.2 )
-flags_g = validation.global_val( u, v, (-10, 10), (-10, 10) )
-flags = flags_s2n | flags_g
-
-u, v = filters.replace_outliers( u, v, flags, method='localmean', max_iter=10, kernel_size=2)
-x, y, u, v = scaling.uniform(x, y, u, v, scaling_factor = 96.52 )
-x, y, u, v = tools.transform_coordinates(x, y, u, v)
-tools.save(str(path / 'test_data.vec') , x, y, u, v, flags)
-# tools.display_vector_field(path / 'test_data.vec', scale=75, width=0.0035)
-tools.display_vector_field(
- str(path / 'test_data.vec'),
- scale=1,
- scaling_factor=96.52,
- width=0.0035,
- on_img=True,
- image_name = str(path / "exp1_001_a.bmp")
-)
\ No newline at end of file
diff --git a/openpiv/tutorials/tutorial2.py b/openpiv/tutorials/tutorial2.py
deleted file mode 100644
index 51cf0ad9..00000000
--- a/openpiv/tutorials/tutorial2.py
+++ /dev/null
@@ -1,39 +0,0 @@
-""" Tutorial of using window deformation multi-pass """
-from importlib_resources import files
-from openpiv import tools, pyprocess, validation, filters
-
-
-def func( args ):
- """A function to process each image pair."""
-
- # this line is REQUIRED for multiprocessing to work
- # always use it in your custom function
-
- file_a, file_b, counter = args
-
- # read images into numpy arrays
- frame_a = tools.imread( path / file_a )
- frame_b = tools.imread( path / file_b )
-
- # process image pair with extended search area piv algorithm.
- u, v, sig2noise = pyprocess.extended_search_area_piv( frame_a, frame_b, \
- window_size=64, overlap=32, dt=0.02, search_area_size=128, sig2noise_method='peak2peak')
- flags = validation.sig2noise_val( sig2noise, threshold = 1.5 )
- u, v = filters.replace_outliers( u, v, flags, method='localmean', max_iter=10, kernel_size=2)
- # get window centers coordinates
- x, y = pyprocess.get_coordinates( image_size=frame_a.shape, search_area_size=128, overlap=32 )
- # save to a file
- tools.save(str(path / f'test2_{counter:03d}.txt') , x, y, u, v, flags)
- tools.display_vector_field( str(path / f'test2_{counter:03d}.txt') )
-
-
-
-path = files('openpiv') / "data" / "test2"
-task = tools.Multiprocesser(
- data_dir = path, # type: ignore
- pattern_a='2image_*0.tif',
- pattern_b='2image_*1.tif')
-
-task.run( func = func, n_cpus=2 )
-
-
diff --git a/openpiv/tutorials/windef_tutorial.py b/openpiv/tutorials/windef_tutorial.py
deleted file mode 100644
index dff053ba..00000000
--- a/openpiv/tutorials/windef_tutorial.py
+++ /dev/null
@@ -1,105 +0,0 @@
-from importlib_resources import files
-from openpiv import windef
-
-
-
-settings = windef.PIVSettings()
-print(settings)
-
-# 'Data related settings'
-# Folder with the images to process
-settings.filepath_images = files('openpiv') / "data" / "test1"
-# Folder for the outputs
-settings.save_path = settings.filepath_images.parent
-
-# Root name of the output Folder for Result Files
-settings.save_folder_suffix = 'Test_1'
-# Format and Image Sequence
-settings.frame_pattern_a = 'exp1_001_a.bmp'
-settings.frame_pattern_b = 'exp1_001_b.bmp'
-
-# 'Region of interest'
-# (50,300,50,300) #Region of interest: (xmin,xmax,ymin,ymax) or 'full' for full image
-settings.roi = 'full'
-
-# 'Image preprocessing'
-# 'None' for no masking, 'edges' for edges masking, 'intensity' for intensity masking
-# WARNING: This part is under development so better not to use MASKS
-settings.dynamic_masking_method = None
-settings.dynamic_masking_threshold = 0.005
-settings.dynamic_masking_filter_size = 7
-
-# 'Processing Parameters'
-settings.correlation_method = 'circular' # 'circular' or 'linear'
-settings.normalized_correlation = False
-settings.num_iterations = 2 # select the number of PIV passes
-# add the interroagtion window size for each pass.
-# For the moment, it should be a power of 2
-# if longer than n iteration the rest is ignored
-settings.windowsizes = (64, 32, 16)
-# The overlap of the interroagtion window for each pass.
-settings.overlap = (32, 16, 8) # This is 50% overlap
-# Has to be a value with base two. In general window size/2 is a good choice.
-# methode used for subpixel interpolation: 'gaussian','centroid','parabolic'
-settings.subpixel_method = 'gaussian'
-# 'symmetric' or 'second image', 'symmetric' splits the deformation on bot images
-# while 'second image' does only deform the second image.
-settings.deformation_method = 'symmetric' # 'symmetric' or 'second image'
-# order of the image interpolation for the window deformation
-settings.interpolation_order = 3
-settings.scaling_factor = 1 # scaling factor pixel/meter
-settings.dt = 1 # time between to frames (in seconds)
-# Signal to noise ratio options (only for the last pass)'
-# It is possible to decide if the S/N should be computed (for the last
-# pass) or not
-# 'True' or 'False' (only for the last pass)
-# settings.extract_sig2noise = False
-# method used to calculate the signal to noise ratio 'peak2peak' or 'peak2mean'
-settings.sig2noise_method = 'peak2peak'
-# select the width of the masked to masked out pixels next to the main peak
-settings.sig2noise_mask = 2
-# If extract_sig2noise==False the values in the signal to noise ratio
-# output column are set to NaN
-# 'vector validation options'
-# choose if you want to do validation of the first pass: True or False
-settings.validation_first_pass = True
-# only effecting the first pass of the interrogation the following passes
-# in the multipass will be validated
-# 'Validation Parameters'
-# The validation is done at each iteration based on three filters.
-# The first filter is based on the min/max ranges. Observe that these values are defined in
-# terms of minimum and maximum displacement in pixel/frames.
-settings.min_max_u_disp = (-30, 30)
-settings.min_max_v_disp = (-30, 30)
-# The second filter is based on the global STD threshold
-settings.std_threshold = 7 # threshold of the std validation
-# The third filter is the median test (not normalized at the moment)
-settings.median_threshold = 3 # threshold of the median validation
-# On the last iteration, an additional validation can be done based on the S/N.
-settings.median_size = 1 # defines the size of the local median
-# 'Validation based on the signal to noise ratio'
-# Note: only available when extract_sig2noise==True and only for the last
-# pass of the interrogation
-# Enable the signal to noise ratio validation. Options: True or False
-settings.sig2noise_validate = False # This is time consuming
-# minmum signal to noise ratio that is need for a valid vector
-settings.sig2noise_threshold = 1.2
-# 'Outlier replacement or Smoothing options'
-# Replacment options for vectors which are masked as invalid by the validation
-settings.replace_vectors = True # Enable the replacment. Chosse: True or False
-settings.smoothn = True # Enables smoothing of the displacemenet field
-settings.smoothn_p = 0.5 # This is a smoothing parameter
-# select a method to replace the outliers: 'localmean', 'disk', 'distance'
-settings.filter_method = 'localmean'
-# maximum iterations performed to replace the outliers
-settings.max_filter_iteration = 4
-settings.filter_kernel_size = 2 # kernel size for the localmean method
-# Output options'
-# Select if you want to save the plotted vectorfield: True or False
-settings.save_plot = False
-# Choose wether you want to see the vectorfield or not :True or False
-settings.show_plot = True
-settings.scale_plot = 200 # select a value to scale the quiver plot of the vectorfield
-# run the script with the given settings
-
-windef.piv(settings)
diff --git a/openpiv/validation.py b/openpiv/validation.py
index 3ab10485..9ab20cca 100644
--- a/openpiv/validation.py
+++ b/openpiv/validation.py
@@ -24,6 +24,7 @@
from scipy.ndimage import generic_filter
import matplotlib.pyplot as plt
+from datetime import datetime
def global_val(
@@ -270,7 +271,8 @@ def typical_validation(
if settings.std_validate:
flag = flag | global_std(u, v, std_threshold=settings.std_threshold)
- print(f"std filter invalidated {sum(flag.flatten())} vectors")
+ now = datetime.now()
+ print(f"\t{now.strftime("%H:%M:%S")}: std filter invalidated {sum(flag.flatten())} vectors")
# u[flag_s] = np.ma.masked
# v[flag_s] = np.ma.masked
@@ -287,7 +289,8 @@ def typical_validation(
size=settings.median_size
)
- print(f"median filter invalidated {sum(flag.flatten())} vectors")
+ now = datetime.now()
+ print(f"\t{now.strftime("%H:%M:%S")}: median filter invalidated {sum(flag.flatten())} vectors")
# u[flag_m] = np.ma.masked
# v[flag_m] = np.ma.masked
@@ -303,8 +306,9 @@ def typical_validation(
# u[flag_s2n] = np.ma.masked
# v[flag_s2n] = np.ma.masked
-
- print(f"s2n filter invalidated {sum(flag_s2n.flatten())} vectors")
+
+ now = datetime.now()
+ print(f"\t{now.strftime("%H:%M:%S")}: s2n filter invalidated {sum(flag_s2n.flatten())} vectors")
# if settings.show_all_plots:
# plt.quiver(u,v,color='g')
# plt.show()
diff --git a/openpiv/windef.py b/openpiv/windef.py
index c8b8acbb..150fd71a 100644
--- a/openpiv/windef.py
+++ b/openpiv/windef.py
@@ -6,7 +6,6 @@
"""
import pathlib
-from dataclasses import dataclass
from typing import Optional, Tuple, Union
import numpy as np
import scipy.ndimage as scn
@@ -15,7 +14,6 @@
from scipy.interpolate import RectBivariateSpline
import matplotlib.pyplot as plt
-from importlib_resources import files
from openpiv.tools import Multiprocesser, display_vector_field, transform_coordinates
from openpiv import validation, filters, tools, scaling, preprocess
from openpiv.pyprocess import extended_search_area_piv, get_rect_coordinates, \
@@ -24,155 +22,8 @@
from datetime import datetime
+from openpiv.settings import PIVSettings
-@dataclass
-class PIVSettings:
- """ All the PIV settings for the batch analysis with multi-processing and
- window deformation. Default settings are set at the initiation
- """
- # "Data related settings"
- # Folder with the images to process
- filepath_images: Union[pathlib.Path, str] = files('openpiv') / "data" / "test1" # type: ignore
- # Folder for the outputs
- save_directory: pathlib.Path = filepath_images.parent
- save_filename: str = 'test1'
-
- # Format and Image Sequence
- frame_pattern_a: str = 'exp1_001_a.bmp'
- frame_pattern_b: str = 'exp1_001_b.bmp'
-
- # "Region of interest"
- # (50,300,50,300) #Region of interest: (xmin,xmax,ymin,ymax) or 'full'
- # for full image
- roi: Union[Tuple[int, int, int, int], str] = "full"
-
- # "Image preprocessing"
- # Every image would be processed separately and the
- # average mask is applied to both A, B, but it's varying
- # for the frames sequence
- #: None for no masking
- #: 'edges' for edges masking,
- #: 'intensity' for intensity masking
- dynamic_masking_method: Optional[str] = None # ['edge','intensity']
- dynamic_masking_threshold: float = 0.005
- dynamic_masking_filter_size: int = 7
-
- # Static masking applied to all images, A,B
- static_mask: Optional[np.ndarray] = None # or a boolean matrix of image shape
-
- # "Processing Parameters"
- correlation_method: str="circular" # ['circular', 'linear']
- normalized_correlation: bool=False
-
- # add the interroagtion window size for each pass.
- # For the moment, it should be a power of 2
- windowsizes: Tuple[int, ...]=(64,32,16)
-
- # The overlap of the interroagtion window for each pass.
- overlap: Tuple[int, ...] = (32, 16, 8) # This is 50% overlap
-
- # Has to be a value with base two. In general window size/2 is a good
- # choice.
-
- num_iterations: int = len(windowsizes) # select the number of PIV
- # passes
-
- # methode used for subpixel interpolation:
- # 'gaussian','centroid','parabolic'
- subpixel_method: str = "gaussian"
- # use vectorized sig2noise and subpixel approximation functions
- use_vectorized: bool = False
- # 'symmetric' or 'second image', 'symmetric' splits the deformation
- # both images, while 'second image' does only deform the second image.
- deformation_method: str = 'symmetric' # 'symmetric' or 'second image'
- # order of the image interpolation for the window deformation
- interpolation_order: int=3
- scaling_factor: float = 1.0 # scaling factor pixel/meter
- dt: float = 1.0 # time between to frames (in seconds)
-
- # Signal to noise ratio:
- # we can decide to estimate it or not at every vector position
- # we can decided if we use it for validation or only store it for
- # later post-processing
- # plus we need some parameters for threshold validation and for the
- # calculations:
-
- sig2noise_method: Optional[str]="peak2mean" # or "peak2peak" or "None"
- # select the width of the masked to masked out pixels next to the main
- # peak
- sig2noise_mask: int=2
- # If extract_sig2noise::False the values in the signal to noise ratio
- # output column are set to NaN
-
- # "Validation based on the signal to noise ratio"
- # Note: only available when extract_sig2noise::True and only for the
- # last pass of the interrogation
- # Enable the signal to noise ratio validation. Options: True or False
- # sig2noise_validate: False # This is time consuming
- # minmum signal to noise ratio that is need for a valid vector
- sig2noise_threshold: float=1.0
- sig2noise_validate: bool=True # when it's False we can save time by not
- #estimating sig2noise ratio at all, so we can set both sig2noise_method to None
-
-
- # "vector validation options"
- # choose if you want to do validation of the first pass: True or False
- validation_first_pass: bool=True
- # only effecting the first pass of the interrogation the following
- # passes
- # in the multipass will be validated
-
- # "Validation Parameters"
- # The validation is done at each iteration based on three filters.
- # The first filter is based on the min/max ranges. Observe that these
- # values are defined in
- # terms of minimum and maximum displacement in pixel/frames.
- min_max_validate: bool=True
- min_max_u_disp: Tuple=(-30, 30)
- min_max_v_disp: Tuple=(-30, 30)
- # The second filter is based on the global STD threshold
- std_validate: bool=True
- std_threshold: int=10 # threshold of the std validation
- # The third filter is the median test (not normalized at the moment)
- median_validate: bool=True
- median_threshold: int=3 # threshold of the median validation
- # On the last iteration, an additional validation can be done based on
- # the S/N.
- median_size: int=1 # defines the size of the local median
-
-
-
- # "Outlier replacement or Smoothing options"
- # Replacment options for vectors which are masked as invalid by the
- # validation
- # Choose: True or False
- replace_vectors: bool=True # Enable the replacement.
- smoothn: bool=False # Enables smoothing of the displacement field
- smoothn_p: float=0.05 # This is a smoothing parameter
- # select a method to replace the outliers:
- # 'localmean', 'disk', 'distance'
- filter_method: str="localmean"
- # maximum iterations performed to replace the outliers
- max_filter_iteration: int=4
- filter_kernel_size: int=2 # kernel size for the localmean method
-
- # "Output options"
- # Select if you want to save the plotted vectorfield: True or False
- save_plot: bool=False
- # Choose wether you want to see the vectorfield or not:True or False
- show_plot: bool=False
- scale_plot: int=100 # select a value to scale the quiver plot of
- # the vectorfield run the script with the given settings
-
- show_all_plots: bool=False
-
- invert: bool=False # for the test_invert
-
- fmt: str="%.4e"
-
- num_cpus: int=1
-
- max_array_size: int=None
def prepare_images(
file_a: pathlib.Path,
@@ -530,11 +381,9 @@ def multipass(args, settings):
x, y, u, v = transform_coordinates(x, y, u, v)
# Saving
- txt_file = settings.save_path
+ txt_file = settings.save_path
print(f'Saving to {txt_file}')
- #fig_name = settings.save_path / f'field_A{counter+1:04d}.png'
-
- tools.save(txt_file, x, y, u, v, flags, grid_mask, fmt=settings.fmt)
+ tools.save(txt_file, x, y, u, v, flags, grid_mask, settings)
if settings.show_plot or settings.save_plot:
fig, _ = display_vector_field(
@@ -748,6 +597,7 @@ def first_pass(frame_a, frame_b, settings):
normalized_correlation=settings.normalized_correlation,
use_vectorized = settings.use_vectorized,
max_array_size=settings.max_array_size,
+ settings=settings
)
shapes = np.array(get_field_shape(frame_a.shape,
@@ -960,6 +810,7 @@ def multipass_img_deform(
normalized_correlation=settings.normalized_correlation,
use_vectorized = settings.use_vectorized,
max_array_size=settings.max_array_size,
+ settings=settings
)
# get_field_shape expects tuples for rectangular windows
diff --git a/openpiv/windef_gpu.py b/openpiv/windef_gpu.py
index 3370c02e..01f35ab5 100644
--- a/openpiv/windef_gpu.py
+++ b/openpiv/windef_gpu.py
@@ -6,176 +6,25 @@
"""
import pathlib
-from dataclasses import dataclass
from typing import Optional, Tuple, Union
import numpy as np
-# import scipy.ndimage as scn
from skimage.util import invert
from scipy.interpolate import RectBivariateSpline
import matplotlib.pyplot as plt
-from importlib_resources import files
from openpiv.tools import Multiprocesser, display_vector_field, transform_coordinates
from openpiv import validation, filters, tools, scaling, preprocess
-# from openpiv.pyprocess import extended_search_area_piv, get_rect_coordinates, \
-# get_field_shape
-from openpiv import smoothn
+from openpiv.pyprocess_gpu import extended_search_area_piv, get_rect_coordinates, \
+ get_field_shape
from datetime import datetime
import cupy as cp
import cupyx.scipy.ndimage as scn
-from openpiv.pyprocess_gpu import extended_search_area_piv, get_rect_coordinates, \
- get_field_shape
-
-
-@dataclass
-class PIVSettings:
- """ All the PIV settings for the batch analysis with multi-processing and
- window deformation. Default settings are set at the initiation
- """
- # "Data related settings"
- # Folder with the images to process
- filepath_images: Union[pathlib.Path, str] = files('openpiv') / "data" / "test1" # type: ignore
- # Folder for the outputs
- save_directory: pathlib.Path = filepath_images.parent
- save_filename: str = 'test1'
- # Format and Image Sequence
- frame_pattern_a: str = 'exp1_001_a.bmp'
- frame_pattern_b: str = 'exp1_001_b.bmp'
-
- # "Region of interest"
- # (50,300,50,300) #Region of interest: (xmin,xmax,ymin,ymax) or 'full'
- # for full image
- roi: Union[Tuple[int, int, int, int], str] = "full"
-
- # "Image preprocessing"
- # Every image would be processed separately and the
- # average mask is applied to both A, B, but it's varying
- # for the frames sequence
- #: None for no masking
- #: 'edges' for edges masking,
- #: 'intensity' for intensity masking
- # dynamic_masking_method: Optional[str] = None # ['edge','intensity']
- # dynamic_masking_threshold: float = 0.005
- # dynamic_masking_filter_size: int = 7
-
- # Static masking applied to all images, A,B
- # static_mask: Optional[np.ndarray] = None # or a boolean matrix of image shape
-
- # "Processing Parameters"
- correlation_method: str="circular" # ['circular', 'linear']
- normalized_correlation: bool=False
-
- # add the interroagtion window size for each pass.
- # For the moment, it should be a power of 2
- windowsizes: Tuple[int, ...]=(64,32,16)
-
- # The overlap of the interroagtion window for each pass.
- overlap: Tuple[int, ...] = (32, 16, 8) # This is 50% overlap
-
- # Has to be a value with base two. In general window size/2 is a good
- # choice.
-
- num_iterations: int = len(windowsizes) # select the number of PIV
- # passes
-
- # methode used for subpixel interpolation:
- # 'gaussian','centroid','parabolic'
- subpixel_method: str = "gaussian"
- # use vectorized sig2noise and subpixel approximation functions
- use_vectorized: bool = False
- # 'symmetric' or 'second image', 'symmetric' splits the deformation
- # both images, while 'second image' does only deform the second image.
- deformation_method: str = 'symmetric' # 'symmetric' or 'second image'
- # order of the image interpolation for the window deformation
- interpolation_order: int=3
- scaling_factor: float = 1.0 # scaling factor pixel/meter
- dt: float = 1.0 # time between to frames (in seconds)
-
- # Signal to noise ratio:
- # we can decide to estimate it or not at every vector position
- # we can decided if we use it for validation or only store it for
- # later post-processing
- # plus we need some parameters for threshold validation and for the
- # calculations:
-
- sig2noise_method: Optional[str]="peak2mean" # or "peak2peak" or "None"
- # select the width of the masked to masked out pixels next to the main
- # peak
- sig2noise_mask: int=2
- # If extract_sig2noise::False the values in the signal to noise ratio
- # output column are set to NaN
-
- # "Validation based on the signal to noise ratio"
- # Note: only available when extract_sig2noise::True and only for the
- # last pass of the interrogation
- # Enable the signal to noise ratio validation. Options: True or False
- # sig2noise_validate: False # This is time consuming
- # minmum signal to noise ratio that is need for a valid vector
- sig2noise_threshold: float=1.0
- sig2noise_validate: bool=True # when it's False we can save time by not
- #estimating sig2noise ratio at all, so we can set both sig2noise_method to None
-
- # "vector validation options"
- # choose if you want to do validation of the first pass: True or False
- validation_first_pass: bool=True
- # only effecting the first pass of the interrogation the following
- # passes
- # in the multipass will be validated
-
- # "Validation Parameters"
- # The validation is done at each iteration based on three filters.
- # The first filter is based on the min/max ranges. Observe that these
- # values are defined in
- # terms of minimum and maximum displacement in pixel/frames.
- min_max_validate: bool=True
- min_max_u_disp: Tuple=(-30, 30)
- min_max_v_disp: Tuple=(-30, 30)
- # The second filter is based on the global STD threshold
- std_validate: bool=True
- std_threshold: int=10 # threshold of the std validation
- # The third filter is the median test (not normalized at the moment)
- median_validate: bool=True
- median_threshold: int=3 # threshold of the median validation
- # On the last iteration, an additional validation can be done based on
- # the S/N.
- median_size: int=1 # defines the size of the local median
-
-
-
- # "Outlier replacement or Smoothing options"
- # Replacment options for vectors which are masked as invalid by the
- # validation
- # Choose: True or False
- replace_vectors: bool=True # Enable the replacement.
- smoothn: bool=False # Enables smoothing of the displacement field
- smoothn_p: float=0.05 # This is a smoothing parameter
- # select a method to replace the outliers:
- # 'localmean', 'disk', 'distance'
- filter_method: str="localmean"
- # maximum iterations performed to replace the outliers
- max_filter_iteration: int=4
- filter_kernel_size: int=2 # kernel size for the localmean method
+from openpiv.settings import PIVSettings
- # "Output options"
- # Select if you want to save the plotted vectorfield: True or False
- save_plot: bool=False
- # Choose wether you want to see the vectorfield or not:True or False
- show_plot: bool=False
- scale_plot: int=100 # select a value to scale the quiver plot of
- # the vectorfield run the script with the given settings
-
- show_all_plots: bool=False
-
- invert: bool=False # for the test_invert
-
- fmt: str="%.4e"
-
- num_cpus: int=1
-
def prepare_images(
file_a: pathlib.Path,
file_b: pathlib.Path,
@@ -217,11 +66,29 @@ def prepare_images(
frame_b = np.pad(frame_b, pad_width=((a, aa), (b, bb)), mode='constant')
- print(frame_a.shape)
- print(frame_b.shape)
+ # Crop width if necesssary
+ if frame_b.shape[1] > frame_a.shape[1]:
+ offset = (frame_b.shape[1] -frame_a.shape[1]) // 2
+ frame_b = frame_b[:, offset : offset + frame_a.shape[1]]
+
+ # Crop height if necessary
+ if frame_b.shape[0] > frame_a.shape[0]:
+ offset = (frame_b.shape[0] - frame_a.shape[0]) // 2
+ frame_b = frame_b[offset : offset + frame_a.shape[0], :]
+
+ # Pad if necessary
+ if (frame_b.shape[0] < frame_a.shape[0]) or (frame_b.shape[1] < frame_a.shape[1]):
+ a = -(frame_b.shape[0] - frame_a.shape[0]) // 2
+ aa = - a + frame_a.shape[0] - frame_b.shape[0]
+
+ b = -(frame_b.shape[1] - frame_a.shape[1]) // 2
+ bb = - b + frame_a.shape[1] - frame_b.shape[1]
+
+ frame_b = np.pad(frame_b, pad_width=((a, aa), (b, bb)), mode='constant')
if (frame_b.shape[0] != frame_a.shape[0]) or (frame_b.shape[1] != frame_a.shape[1]):
raise ValueError('Images are different sizes.')
+
# crop to roi
if settings.roi == "full":
pass
@@ -247,7 +114,7 @@ def piv(settings):
# "Below is code to read files and create a folder to store the results"
#save_path_string = \
# f"OpenPIV_results_{settings.windowsizes[settings.num_iterations-1]}_{settings.save_folder_suffix}"
-
+
if not settings.save_directory.exists():
# os.makedirs(save_path)
settings.save_directory.mkdir(parents=True, exist_ok=True)
@@ -290,7 +157,7 @@ def multipass(args, settings):
frame_b = cp.array(frame_b)
now = datetime.now()
- print(f'Set {counter+1} starting first pass {now.strftime("%H:%M:%S")}')
+ print(f' {now.strftime("%H:%M:%S")}: starting pass 1 / {settings.num_iterations}')
# "first pass"
x, y, u, v, s2n = first_pass(
@@ -329,29 +196,13 @@ def multipass(args, settings):
kernel_size=settings.filter_kernel_size,
)
- # "adding masks to add the effect of all the validations"
- # if settings.smoothn:
- # u, *_ = smoothn.smoothn(
- # u,
- # s=settings.smoothn_p
- # )
- # v, *_ = smoothn.smoothn(
- # v,
- # s=settings.smoothn_p
- # )
-
- # # enforce grid_mask that possibly destroyed by smoothing
- # u = np.ma.masked_array(u, mask=grid_mask)
- # v = np.ma.masked_array(v, mask=grid_mask)
-
# Multi pass
for i in range(1, settings.num_iterations):
time_diff = datetime.now() - now
now = datetime.now()
- print(f'Set {counter+1} starting pass {i+1} '
- f'{now.strftime("%H:%M:%S")} {time_diff.total_seconds()}')
+ print(f' {now.strftime("%H:%M:%S")}: starting pass {i+1} / {settings.num_iterations}')
x, y, u, v, grid_mask, flags = multipass_img_deform(
frame_a,
@@ -365,27 +216,10 @@ def multipass(args, settings):
)
mempool.free_all_blocks()
- # If the smoothing is active, we do it at each pass
- # but not the last one
- # if settings.smoothn is True and i < settings.num_iterations-1:
- # u, dummy_u1, dummy_u2, dummy_u3 = smoothn.smoothn(
- # u, s=settings.smoothn_p
- # )
- # v, dummy_v1, dummy_v2, dummy_v3 = smoothn.smoothn(
- # v, s=settings.smoothn_p
- # )
- # if not isinstance(u, np.ma.MaskedArray):
- # raise ValueError('not a masked array anymore')
-
-
- # u = cp.ma.masked_array(u, cp.ma.nomask)
- # v = cp.ma.masked_array(v, cp.ma.nomask)
-
time_diff = datetime.now() - now
now = datetime.now()
- print(f'Set {counter+1} done {now.strftime("%H:%M:%S")} '
- f'{time_diff.total_seconds()}')
+ print(f' {now.strftime("%H:%M:%S")}: completed pass {i+1} / {settings.num_iterations}')
# we now use only 0s instead of the image
@@ -411,16 +245,16 @@ def multipass(args, settings):
# and so u,v
x, y, u, v = transform_coordinates(x, y, u, v)
- # Saving
- txt_file = settings.save_path
+ # Saving=
+ txt_file = settings.save_path
print(f'Saving to {txt_file}')
- tools.save(txt_file, x, y, u, v, flags, grid_mask, fmt=settings.fmt)
+ tools.save(txt_file, x, y, u, v, flags, grid_mask, settings)
print(f"Image Pair {counter + 1}")
print(file_a.stem, file_b.stem)
-def create_deformation_field(frame, x, y, u, v, window_size, overlap, interpolation_order = 3):
+def deform_windows(frame, x, y, u, v, window_size, overlap, interpolation_order = 1, interpolation_order2 = 3):
"""
Deform an image by window deformation where a new grid is defined based
on the grid and displacements of the previous pass and pixel values are
@@ -449,104 +283,70 @@ def create_deformation_field(frame, x, y, u, v, window_size, overlap, interpolat
in pixels/seconds.
interpolation_order: scalar
+ the degree of the frame interpolation (deformation) of the image
+
+ interpolation_order2: scalar
the degree of the interpolation of the B-splines over the rectangular mesh
Returns
-------
- x,y : new grid (after meshgrid)
- u,v : deformation field
+ frame_def:
+ a deformed image based on the meshgrid and displacements of the
+ previous pass
"""
- y1 = y[:, 0] # extract first coloumn from meshgrid
+
+ mempool = cp.get_default_memory_pool()
+
+ y1 = y[:, 0] # extract first column from meshgrid
x1 = x[0, :] # extract first row from meshgrid
side_x = cp.arange(frame.shape[1]) # extract the image grid
side_y = cp.arange(frame.shape[0])
+ x, y = cp.meshgrid(side_x, side_y)
+
+ #print(mempool.used_bytes()/1024/1024) #5914
+
+ #print(f' {datetime.now().strftime("%H:%M:%S")}')
ut = scn.map_coordinates(
cp.array(u),
cp.asarray(cp.meshgrid(
(side_x - x1[0]) / (window_size - overlap),
(side_y - y1[0]) / (window_size - overlap)
)[::-1]),
- order=interpolation_order
+ order=interpolation_order2,
+ mode='constant', cval=0
)
+
+ #print(mempool.used_bytes()/1024/1024) #9857
+ #print(f' {datetime.now().strftime("%H:%M:%S")}')
vt = scn.map_coordinates(
cp.array(v),
cp.asarray(cp.meshgrid(
(side_x - x1[0]) / (window_size - overlap),
(side_y - y1[0]) / (window_size - overlap)
)[::-1]),
- order=interpolation_order
+ order=interpolation_order2,
+ mode='constant', cval=0
)
- x, y = cp.meshgrid(side_x, side_y)
-
- return x, y, ut, vt
-
-
-def deform_windows(frame, x, y, u, v, window_size, overlap, interpolation_order=1, interpolation_order2=3,
- debugging=False):
- """
- Deform an image by window deformation where a new grid is defined based
- on the grid and displacements of the previous pass and pixel values are
- interpolated onto the new grid.
-
- Parameters
- ----------
- frame : 2d np.ndarray, dtype=np.int32
- an two dimensions array of integers containing grey levels of
- the first frame.
-
- x : 2d np.ndarray
- a two dimensional array containing the x coordinates of the
- interrogation window centers, in pixels.
-
- y : 2d np.ndarray
- a two dimensional array containing the y coordinates of the
- interrogation window centers, in pixels.
-
- u : 2d np.ndarray
- a two dimensional array containing the u velocity component,
- in pixels/seconds.
+ del x1, y1, side_x, side_y
+ mempool.free_all_blocks()
- v : 2d np.ndarray
- a two dimensional array containing the v velocity component,
- in pixels/seconds.
+ #print(f' {datetime.now().strftime("%H:%M:%S")}')
+ #print(mempool.used_bytes()/1024/1024) #13700
- interpolation_order: scalar
- the degree of the frame interpolation (deformation) of the image
-
- interpolation_order2: scalar
- the degree of the interpolation of the B-splines over the rectangular mesh
+ frame = frame.astype(np.float32)
- Returns
- -------
- frame_def:
- a deformed image based on the meshgrid and displacements of the
- previous pass
- """
-
- # frame = frame.astype(np.float32)
- x, y, ut, vt = \
- create_deformation_field(frame,
- x, y, u, v, window_size, overlap,
- interpolation_order=interpolation_order2)
- # print('______------_____')
- # print(y.shape)
- # print(vt.shape)
- # print(np.array((y - vt, x + ut)).shape)
frame_def = scn.map_coordinates(
- frame, cp.array((y - vt, x + ut)), order=interpolation_order, mode='nearest')
+ frame, cp.array((y - vt, x + ut)), order=interpolation_order, mode='nearest',
+ )
+
+ #print(mempool.used_bytes()/1024/1024) #17742
- if debugging:
- plt.figure()
- plt.quiver(x, y, ut, vt)
- plt.title('new, x,y, ut,vt')
- plt.show()
+ ut = None
+ vt = None
+ mempool.free_all_blocks()
- plt.figure()
- plt.imshow(frame-frame_def)
- plt.title('new deformed image')
- plt.show()
return frame_def
@@ -625,6 +425,7 @@ def first_pass(frame_a, frame_b, settings):
correlation_method=settings.correlation_method,
normalized_correlation=settings.normalized_correlation,
use_vectorized = settings.use_vectorized,
+ max_array_size=settings.max_array_size,
)
shapes = np.array(get_field_shape(frame_a.shape,
@@ -736,6 +537,7 @@ def multipass_img_deform(
x, y = get_rect_coordinates(frame_a.shape, window_size, overlap)
+
# The interpolation function dont like meshgrids as input.
# plus the coordinate system for y is now from top to bottom
# and RectBivariateSpline wants an increasing set
@@ -761,31 +563,23 @@ def multipass_img_deform(
y_int[0] - np.arange(y_add[0], 0, -1) * (window_size - overlap),
y_int,
y_int[-1] + np.arange(1, y_add[1] + 1) * (window_size - overlap)
- ))
+ )) #.astype(int)
x_int = np.hstack((
x_int[0] - np.arange(x_add[0], 0, -1) * (window_size - overlap),
x_int,
x_int[-1] + np.arange(1, x_add[1] + 1) * (window_size - overlap)
- ))
-
- x, y = np.meshgrid(x_int, y_int)
+ )) #.astype(int)
+ x, y = np.meshgrid(x_int, y_int, copy=True)
# interpolating the displacements from the old grid onto the new grid
# y befor x because of numpy works row major
- # ip = RectBivariateSpline(y_old, x_old, np.ma.filled(u_old, 0.),
- # print(f'y_old {type(y_old)}')
- # print(f'x_old {type(x_old)}')
- # print(f'u_old {type(u_old)}')
- # print(f'v_old {type(v_old)}')
- # u_old = u_old.get()
- # v_old = v_old.get()
- # print(f'u_old {type(u_old)}')
- # print(f'v_old {type(v_old)}')
ip = RectBivariateSpline(y_old, x_old, u_old,
kx=settings.interpolation_order,
ky=settings.interpolation_order)
+
u_pre = ip(y_int, x_int)
+ # dtype = float64
# ip2 = RectBivariateSpline(y_old, x_old, np.ma.filled(v_old, 0.),
ip2 = RectBivariateSpline(y_old, x_old, v_old,
@@ -802,26 +596,26 @@ def multipass_img_deform(
# previous pass which are stored in the physical units
# and so y from the get_coordinates
- if settings.deformation_method == "symmetric":
- raise NotImplementedError('settings.deformation_method == "symmetric"')
- # this one is doing the image deformation (see above)
- x_new, y_new, ut, vt = create_deformation_field(
- frame_a, x, y, u_pre, v_pre,
- interpolation_order=settings.interpolation_order)
- frame_a = scn.map_coordinates(
- frame_a, ((y_new - vt / 2, x_new - ut / 2)),
- order=settings.interpolation_order, mode='nearest')
- frame_b = scn.map_coordinates(
- frame_b, ((y_new + vt / 2, x_new + ut / 2)),
- order=settings.interpolation_order, mode='nearest')
- elif settings.deformation_method == "second image":
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: deform_windows')
+
+ if settings.deformation_method == "second image":
frame_b = deform_windows(
frame_b, x, y, u_pre, -v_pre, window_size, overlap,
interpolation_order=settings.interpolation_order,
interpolation_order2=settings.interpolation_order)
+ #if current_iteration == 6:
+ #plt.figure()
+ #plt.imshow(frame_b.get())
+ #plt.show()
else:
raise Exception("Deformation method is not valid.")
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: deform_windows complete')
+
+ mempool = cp.get_default_memory_pool()
+ mempool.free_all_blocks()
# if do_sig2noise is True
# sig2noise_method = sig2noise_method
@@ -834,6 +628,7 @@ def multipass_img_deform(
if settings.sig2noise_validate is False:
settings.sig2noise_method = None
+
u, v, s2n = extended_search_area_piv(
frame_a,
frame_b,
@@ -845,6 +640,7 @@ def multipass_img_deform(
correlation_method=settings.correlation_method,
normalized_correlation=settings.normalized_correlation,
use_vectorized = settings.use_vectorized,
+ max_array_size=settings.max_array_size,
)
frame_b = None
@@ -871,19 +667,28 @@ def multipass_img_deform(
# validate in the multi-pass by default
flags = validation.typical_validation(u, v, s2n, settings)
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: typical_validation complete')
+
if np.all(flags):
raise ValueError("Something happened in the validation")
- # we have to replace outliers
- u, v = filters.replace_outliers(
- u,
- v,
- flags,
- method=settings.filter_method,
- max_iter=settings.max_filter_iteration,
- kernel_size=settings.filter_kernel_size,
- )
- flags = np.zeros(u.shape)
+
+ ## Turn off remove_outliers for the last step
+ if current_iteration +1 != settings.num_iterations:
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: replace_outliers')
+
+ # we have to replace outliers
+ u, v = filters.replace_outliers(
+ u,
+ v,
+ flags,
+ method=settings.filter_method,
+ max_iter=settings.max_filter_iteration,
+ kernel_size=settings.filter_kernel_size,
+ )
+ flags = np.zeros(u.shape)
y = y[y_add[0]:-y_add[1], x_add[0]:-x_add[1]]
x = x[y_add[0]:-y_add[1], x_add[0]:-x_add[1]]
diff --git a/openpiv/windef_gpu_cpu.py b/openpiv/windef_gpu_cpu.py
index fe663fa9..2809bb20 100644
--- a/openpiv/windef_gpu_cpu.py
+++ b/openpiv/windef_gpu_cpu.py
@@ -6,176 +6,24 @@
"""
import pathlib
-from dataclasses import dataclass
from typing import Optional, Tuple, Union
import numpy as np
-# import scipy.ndimage as scn
from skimage.util import invert
from scipy.interpolate import RectBivariateSpline
import matplotlib.pyplot as plt
-from importlib_resources import files
from openpiv.tools import Multiprocesser, display_vector_field, transform_coordinates
from openpiv import validation, filters, tools, scaling, preprocess
-# from openpiv.pyprocess import extended_search_area_piv, get_rect_coordinates, \
-# get_field_shape
-from openpiv import smoothn
+from openpiv.pyprocess_gpu import extended_search_area_piv, get_rect_coordinates, \
+ get_field_shape
from datetime import datetime
import cupy as cp
import cupyx.scipy.ndimage as scn
-from openpiv.pyprocess_gpu import extended_search_area_piv, get_rect_coordinates, \
- get_field_shape
-
-@dataclass
-class PIVSettings:
- """ All the PIV settings for the batch analysis with multi-processing and
- window deformation. Default settings are set at the initiation
- """
- # "Data related settings"
- # Folder with the images to process
- filepath_images: Union[pathlib.Path, str] = files('openpiv') / "data" / "test1" # type: ignore
- # Folder for the outputs
- save_path: pathlib.Path = filepath_images.parent
- # Root name of the output Folder for Result Files
- save_folder_suffix: str = 'test1'
- # Format and Image Sequence
- frame_pattern_a: str = 'exp1_001_a.bmp'
- frame_pattern_b: str = 'exp1_001_b.bmp'
-
- # "Region of interest"
- # (50,300,50,300) #Region of interest: (xmin,xmax,ymin,ymax) or 'full'
- # for full image
- roi: Union[Tuple[int, int, int, int], str] = "full"
-
- # "Image preprocessing"
- # Every image would be processed separately and the
- # average mask is applied to both A, B, but it's varying
- # for the frames sequence
- #: None for no masking
- #: 'edges' for edges masking,
- #: 'intensity' for intensity masking
- # dynamic_masking_method: Optional[str] = None # ['edge','intensity']
- # dynamic_masking_threshold: float = 0.005
- # dynamic_masking_filter_size: int = 7
-
- # Static masking applied to all images, A,B
- # static_mask: Optional[np.ndarray] = None # or a boolean matrix of image shape
-
- # "Processing Parameters"
- correlation_method: str="circular" # ['circular', 'linear']
- normalized_correlation: bool=False
-
- # add the interroagtion window size for each pass.
- # For the moment, it should be a power of 2
- windowsizes: Tuple[int, ...]=(64,32,16)
-
- # The overlap of the interroagtion window for each pass.
- overlap: Tuple[int, ...] = (32, 16, 8) # This is 50% overlap
-
- # Has to be a value with base two. In general window size/2 is a good
- # choice.
-
- num_iterations: int = len(windowsizes) # select the number of PIV
- # passes
-
- # methode used for subpixel interpolation:
- # 'gaussian','centroid','parabolic'
- subpixel_method: str = "gaussian"
- # use vectorized sig2noise and subpixel approximation functions
- use_vectorized: bool = False
- # 'symmetric' or 'second image', 'symmetric' splits the deformation
- # both images, while 'second image' does only deform the second image.
- deformation_method: str = 'symmetric' # 'symmetric' or 'second image'
- # order of the image interpolation for the window deformation
- interpolation_order: int=3
- scaling_factor: float = 1.0 # scaling factor pixel/meter
- dt: float = 1.0 # time between to frames (in seconds)
-
- # Signal to noise ratio:
- # we can decide to estimate it or not at every vector position
- # we can decided if we use it for validation or only store it for
- # later post-processing
- # plus we need some parameters for threshold validation and for the
- # calculations:
-
- sig2noise_method: Optional[str]="peak2mean" # or "peak2peak" or "None"
- # select the width of the masked to masked out pixels next to the main
- # peak
- sig2noise_mask: int=2
- # If extract_sig2noise::False the values in the signal to noise ratio
- # output column are set to NaN
-
- # "Validation based on the signal to noise ratio"
- # Note: only available when extract_sig2noise::True and only for the
- # last pass of the interrogation
- # Enable the signal to noise ratio validation. Options: True or False
- # sig2noise_validate: False # This is time consuming
- # minmum signal to noise ratio that is need for a valid vector
- sig2noise_threshold: float=1.0
- sig2noise_validate: bool=True # when it's False we can save time by not
- #estimating sig2noise ratio at all, so we can set both sig2noise_method to None
-
-
- # "vector validation options"
- # choose if you want to do validation of the first pass: True or False
- validation_first_pass: bool=True
- # only effecting the first pass of the interrogation the following
- # passes
- # in the multipass will be validated
-
- # "Validation Parameters"
- # The validation is done at each iteration based on three filters.
- # The first filter is based on the min/max ranges. Observe that these
- # values are defined in
- # terms of minimum and maximum displacement in pixel/frames.
- min_max_validate: bool=True
- min_max_u_disp: Tuple=(-30, 30)
- min_max_v_disp: Tuple=(-30, 30)
- # The second filter is based on the global STD threshold
- std_validate: bool=True
- std_threshold: int=10 # threshold of the std validation
- # The third filter is the median test (not normalized at the moment)
- median_validate: bool=True
- median_threshold: int=3 # threshold of the median validation
- # On the last iteration, an additional validation can be done based on
- # the S/N.
- median_size: int=1 # defines the size of the local median
-
-
-
- # "Outlier replacement or Smoothing options"
- # Replacment options for vectors which are masked as invalid by the
- # validation
- # Choose: True or False
- replace_vectors: bool=True # Enable the replacement.
- smoothn: bool=False # Enables smoothing of the displacement field
- smoothn_p: float=0.05 # This is a smoothing parameter
- # select a method to replace the outliers:
- # 'localmean', 'disk', 'distance'
- filter_method: str="localmean"
- # maximum iterations performed to replace the outliers
- max_filter_iteration: int=4
- filter_kernel_size: int=2 # kernel size for the localmean method
-
- # "Output options"
- # Select if you want to save the plotted vectorfield: True or False
- save_plot: bool=False
- # Choose wether you want to see the vectorfield or not:True or False
- show_plot: bool=False
- scale_plot: int=100 # select a value to scale the quiver plot of
- # the vectorfield run the script with the given settings
-
- show_all_plots: bool=False
-
- invert: bool=False # for the test_invert
-
- fmt: str="%.4e"
-
- num_cpus: int=1
+from openpiv.settings import PIVSettings
def prepare_images(
file_a: pathlib.Path,
@@ -198,6 +46,30 @@ def prepare_images(
frame_b = tools.imread(file_b)
# print(frame_a.shape)
+
+ # Crop width if necesssary
+ if frame_b.shape[1] > frame_a.shape[1]:
+ offset = (frame_b.shape[1] -frame_a.shape[1]) // 2
+ frame_b = frame_b[:, offset : offset + frame_a.shape[1]]
+
+ # Crop height if necessary
+ if frame_b.shape[0] > frame_a.shape[0]:
+ offset = (frame_b.shape[0] - frame_a.shape[0]) // 2
+ frame_b = frame_b[offset : offset + frame_a.shape[0], :]
+
+ # Pad if necessary
+ if (frame_b.shape[0] < frame_a.shape[0]) or (frame_b.shape[1] < frame_a.shape[1]):
+ a = -(frame_b.shape[0] - frame_a.shape[0]) // 2
+ aa = - a + frame_a.shape[0] - frame_b.shape[0]
+
+ b = -(frame_b.shape[1] - frame_a.shape[1]) // 2
+ bb = - b + frame_a.shape[1] - frame_b.shape[1]
+
+ frame_b = np.pad(frame_b, pad_width=((a, aa), (b, bb)), mode='constant')
+
+ if (frame_b.shape[0] != frame_a.shape[0]) or (frame_b.shape[1] != frame_a.shape[1]):
+ raise ValueError('Images are different sizes.')
+
# crop to roi
if settings.roi == "full":
pass
@@ -219,17 +91,16 @@ def piv(settings):
# if teh settings.save_path is a string convert it to the Path
settings.filepath_images = pathlib.Path(settings.filepath_images)
- settings.save_path = pathlib.Path(settings.save_path)
+ settings.save_directory = pathlib.Path(settings.save_directory)
# "Below is code to read files and create a folder to store the results"
- save_path_string = \
- f"OpenPIV_results_{settings.windowsizes[settings.num_iterations-1]}_{settings.save_folder_suffix}"
-
- save_path = \
- settings.save_path / save_path_string
+ #save_path_string = \
+ # f"OpenPIV_results_{settings.windowsizes[settings.num_iterations-1]}_{settings.save_folder_suffix}"
- if not save_path.exists():
+ if not settings.save_directory.exists():
# os.makedirs(save_path)
- save_path.mkdir(parents=True, exist_ok=True)
+ settings.save_directory.mkdir(parents=True, exist_ok=True)
+
+ save_path = settings.save_directory / settings.save_filename
settings.save_path = save_path
@@ -267,7 +138,7 @@ def multipass(args, settings):
frame_b = cp.array(frame_b)
now = datetime.now()
- print(f'Set {counter+1} starting first pass {now.strftime("%H:%M:%S")}')
+ print(f' {now.strftime("%H:%M:%S")}: starting pass 1')
# "first pass"
x, y, u, v, s2n = first_pass(
@@ -306,29 +177,13 @@ def multipass(args, settings):
kernel_size=settings.filter_kernel_size,
)
- # "adding masks to add the effect of all the validations"
- # if settings.smoothn:
- # u, *_ = smoothn.smoothn(
- # u,
- # s=settings.smoothn_p
- # )
- # v, *_ = smoothn.smoothn(
- # v,
- # s=settings.smoothn_p
- # )
-
- # # enforce grid_mask that possibly destroyed by smoothing
- # u = np.ma.masked_array(u, mask=grid_mask)
- # v = np.ma.masked_array(v, mask=grid_mask)
-
# Multi pass
for i in range(1, settings.num_iterations):
time_diff = datetime.now() - now
now = datetime.now()
- print(f'Set {counter+1} starting pass {i+1} '
- f'{now.strftime("%H:%M:%S")} {time_diff.total_seconds()}')
+ print(f' {now.strftime("%H:%M:%S")}: starting pass {i+1}')
x, y, u, v, grid_mask, flags = multipass_img_deform(
frame_a,
@@ -342,27 +197,10 @@ def multipass(args, settings):
)
mempool.free_all_blocks()
- # If the smoothing is active, we do it at each pass
- # but not the last one
- # if settings.smoothn is True and i < settings.num_iterations-1:
- # u, dummy_u1, dummy_u2, dummy_u3 = smoothn.smoothn(
- # u, s=settings.smoothn_p
- # )
- # v, dummy_v1, dummy_v2, dummy_v3 = smoothn.smoothn(
- # v, s=settings.smoothn_p
- # )
- # if not isinstance(u, np.ma.MaskedArray):
- # raise ValueError('not a masked array anymore')
-
-
- # u = cp.ma.masked_array(u, cp.ma.nomask)
- # v = cp.ma.masked_array(v, cp.ma.nomask)
-
time_diff = datetime.now() - now
now = datetime.now()
- print(f'Set {counter+1} done {now.strftime("%H:%M:%S")} '
- f'{time_diff.total_seconds()}')
+ print(f' {now.strftime("%H:%M:%S")}: completed pass {i+1}')
# we now use only 0s instead of the image
@@ -389,7 +227,7 @@ def multipass(args, settings):
x, y, u, v = transform_coordinates(x, y, u, v)
# Saving
- txt_file = settings.save_path / f'field_A{counter+1:04d}.txt'
+ txt_file = settings.save_path
print(f'Saving to {txt_file}')
tools.save(txt_file, x, y, u, v, flags, grid_mask, fmt=settings.fmt)
@@ -601,6 +439,7 @@ def first_pass(frame_a, frame_b, settings):
correlation_method=settings.correlation_method,
normalized_correlation=settings.normalized_correlation,
use_vectorized = settings.use_vectorized,
+ max_array_size=settings.max_array_size,
)
shapes = np.array(get_field_shape(frame_a.shape,
@@ -773,6 +612,8 @@ def multipass_img_deform(
interpolation_order2=settings.interpolation_order)
else:
raise Exception("Deformation method is not valid.")
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: deform_windows complete')
# if do_sig2noise is True
@@ -797,6 +638,7 @@ def multipass_img_deform(
correlation_method=settings.correlation_method,
normalized_correlation=settings.normalized_correlation,
use_vectorized = settings.use_vectorized,
+ max_array_size=settings.max_array_size,
)
frame_b = None
@@ -823,18 +665,27 @@ def multipass_img_deform(
# validate in the multi-pass by default
flags = validation.typical_validation(u, v, s2n, settings)
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: typical_validation complete')
+
if np.all(flags):
raise ValueError("Something happened in the validation")
- # we have to replace outliers
- u, v = filters.replace_outliers(
- u,
- v,
- flags,
- method=settings.filter_method,
- max_iter=settings.max_filter_iteration,
- kernel_size=settings.filter_kernel_size,
- )
- flags = np.zeros(u.shape)
+
+ ## Turn off remove_outliers for the last step
+ if current_iteration +1 != settings.num_iterations:
+ now = datetime.now()
+ print(f'\t{now.strftime("%H:%M:%S")}: replace_outliers')
+
+ # we have to replace outliers
+ u, v = filters.replace_outliers(
+ u,
+ v,
+ flags,
+ method=settings.filter_method,
+ max_iter=settings.max_filter_iteration,
+ kernel_size=settings.filter_kernel_size,
+ )
+ flags = np.zeros(u.shape)
return x, y, u, v, grid_mask, flags
diff --git a/output_3D_test/displaced_bar_deformation_field.png b/output_3D_test/displaced_bar_deformation_field.png
deleted file mode 100644
index 9897f0f3..00000000
Binary files a/output_3D_test/displaced_bar_deformation_field.png and /dev/null differ
diff --git a/output_3D_test/displaced_bar_frame1.png b/output_3D_test/displaced_bar_frame1.png
deleted file mode 100644
index 6d5dc4b7..00000000
Binary files a/output_3D_test/displaced_bar_frame1.png and /dev/null differ
diff --git a/output_3D_test/displaced_bar_frame2.png b/output_3D_test/displaced_bar_frame2.png
deleted file mode 100644
index b6bbeb8e..00000000
Binary files a/output_3D_test/displaced_bar_frame2.png and /dev/null differ
diff --git a/output_3D_test/displaced_bar_sig2noise.png b/output_3D_test/displaced_bar_sig2noise.png
deleted file mode 100644
index 2100263d..00000000
Binary files a/output_3D_test/displaced_bar_sig2noise.png and /dev/null differ
diff --git a/output_3D_test/expanded_box_deformation_field.png b/output_3D_test/expanded_box_deformation_field.png
deleted file mode 100644
index f8977909..00000000
Binary files a/output_3D_test/expanded_box_deformation_field.png and /dev/null differ
diff --git a/output_3D_test/expanded_box_frame1.png b/output_3D_test/expanded_box_frame1.png
deleted file mode 100644
index 974821e6..00000000
Binary files a/output_3D_test/expanded_box_frame1.png and /dev/null differ
diff --git a/output_3D_test/expanded_box_frame2.png b/output_3D_test/expanded_box_frame2.png
deleted file mode 100644
index c1f2c024..00000000
Binary files a/output_3D_test/expanded_box_frame2.png and /dev/null differ
diff --git a/output_3D_test/expanded_box_sig2noise.png b/output_3D_test/expanded_box_sig2noise.png
deleted file mode 100644
index b8805008..00000000
Binary files a/output_3D_test/expanded_box_sig2noise.png and /dev/null differ
diff --git a/output_3D_test/reaL_data_max_proj.gif b/output_3D_test/reaL_data_max_proj.gif
deleted file mode 100644
index ac27442e..00000000
Binary files a/output_3D_test/reaL_data_max_proj.gif and /dev/null differ
diff --git a/output_3D_test/real_data_filtered.png b/output_3D_test/real_data_filtered.png
deleted file mode 100644
index 8c4243ff..00000000
Binary files a/output_3D_test/real_data_filtered.png and /dev/null differ
diff --git a/output_3D_test/real_data_unfiltered.png b/output_3D_test/real_data_unfiltered.png
deleted file mode 100644
index f9885601..00000000
Binary files a/output_3D_test/real_data_unfiltered.png and /dev/null differ
diff --git a/output_3D_test/replace_nan_filled.png b/output_3D_test/replace_nan_filled.png
deleted file mode 100644
index 4035e67b..00000000
Binary files a/output_3D_test/replace_nan_filled.png and /dev/null differ
diff --git a/output_3D_test/replace_nan_gap.png b/output_3D_test/replace_nan_gap.png
deleted file mode 100644
index 96cded37..00000000
Binary files a/output_3D_test/replace_nan_gap.png and /dev/null differ
diff --git a/recipe/meta.yaml b/recipe/meta.yaml
deleted file mode 100644
index 027910a3..00000000
--- a/recipe/meta.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-{% set data = load_setup_py_data(setup_file="../setup.py",
- from_recipe_dir=True) %}
-
-package:
- name: openpiv
- version: {{ data.get('version') }}
-
-source:
- path: ..
-
-build:
- number: 0
- noarch: python
- script: {{ PYTHON }} -m pip install . -vv
-
-requirements:
- build:
- - python >=3.7
- - pip
- run:
- - python >=3.7
- - numpy
- - imageio
- - matplotlib-base
- - scikit-image
- - scipy
- - natsort
- - tqdm
-
-test:
- imports:
- - openpiv
-
-about:
- home: https://github.com/openpiv/openpiv
- license: GPLv3
- license_file: LICENSE.txt
- summary: "Open Source Particle Image Velocimetry"
- doc_url: http://openpiv.readthedocs.io/
diff --git a/setup.py b/setup.py
index 542cbedd..35ba47ce 100644
--- a/setup.py
+++ b/setup.py
@@ -26,7 +26,8 @@
'scipy',
'natsort',
'tqdm',
- 'importlib_resources'
+ 'importlib_resources',
+ 'cupy-cuda12x',
],
extras_require={"tests": ["pytest"]},
classifiers=[
diff --git a/synimage/PIV_experiment_data.npz b/synimage/PIV_experiment_data.npz
deleted file mode 100644
index 6361cd18..00000000
Binary files a/synimage/PIV_experiment_data.npz and /dev/null differ
diff --git a/synimage/Synthetic_Image_Generator_examples.ipynb b/synimage/Synthetic_Image_Generator_examples.ipynb
deleted file mode 100644
index 4afafc10..00000000
--- a/synimage/Synthetic_Image_Generator_examples.ipynb
+++ /dev/null
@@ -1,341 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Synthetic Image Generation examples ##\n",
- "In this Notebook a number of test cases using the PIV sythetic image generator will be presented.\n",
- "\n",
- "The three examples shown are:\n",
- "1. Using a fully synthetic flow field created by a random equation\n",
- "2. Using pre attained experimental data\n",
- "3. Using flow simulation results\n",
- "\n",
- "In each of these cases the pattern to recieving the synthetic images is the same. The part that mostly varies is the data passed.\n",
- "\n",
- "1. Data is either syntheticly made or pass to the create_synimage_parameters function.\n",
- "2. The parameters for both images (frame_a, frame_b) are created\n",
- "3. The parameters are passed to the generate_particle_image function in order to create the image representation.\n",
- "4. Finally the images are shown on the screen as grayschale images."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "import synimagegen\n",
- "import matplotlib.pyplot as plt\n",
- "import numpy as np\n",
- "import os\n",
- "%matplotlib inline"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Example 1: synthetic flow field created by a random equation ###\n",
- "In this case no data is passed to the function, so a random equation is invoked from the cff module. (line 46,52 in synimagegen.py)\n",
- "\n",
- "This equation defines the velocities U,V for each point in the X,Y plane.\n",
- "\n",
- "This equation is ment to be changed to suit the testing needs of each users system.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Requested pair loss: 10 Actual pair loss: 11\n"
- ]
- }
- ],
- "source": [
- "ground_truth,cv,x_1,y_1,U_par,V_par,par_diam1,par_int1,x_2,y_2,par_diam2,par_int2 = synimagegen.create_synimage_parameters(None,[0,1],[0,1],[256,256],dt=0.0025)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [],
- "source": [
- "frame_a = synimagegen.generate_particle_image(256, 256, x_1, y_1, par_diam1, par_int1,16)\n",
- "frame_b = synimagegen.generate_particle_image(256, 256, x_2, y_2, par_diam2, par_int2,16)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Text(0.5, 1.0, 'frame_b')"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- },
- {
- "data": {
- "image/png": "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mU/dI71x40agjVP33nsv0M7dpGX0/J1mdK0mcdBBB82+5jzSb2yX9jOzYldfffWcY1WpN6kV38LgqBnPfnl81HhIRYNqVMdulRRW0FEB8cILLyy7nTvWGQ92q7pZ1QuTlokPK49tyPlDVbVtTJXpk08+CSzcpqr/o/3hnnvuAdq9irGeMdqw5ufav62UpZrV143FVLu88MILQOYwaOfQylpWfrXK2K5du4B2Dh0rJw3vP5588kl27NgBwL59+4CVq97VK/YnfZxuvvlmYL6C9c477wRav+z38UUhFEIIIYQQQgghhDBlTIRCyEyr+0tluR4frqxWjyAfzT654uqj/859ia62u3ptpmgpx2J22UyYmQOPUfWFGbBJzcCHlcc2ZDWwn//5nwfgxBNPBOA3fuM3ANi+fTuwcMUJs1G2d7NYVhPzudWWHn74YaBldwadQbWP2b/tY/5++5r9uPrkJBvVqHv+PZfVC2FQKplBY5sw8/rf//t/B/afl507dwKDy8TZLs2CmR2zcoW4f95MYdpzWCy1f6tksD9Uz5Pl4jijevP4448HWiU9fbJs07fccgvQ+uW3v/3tJR+L88QhhxwCNFWSmXfVC6ownO/M9g67YlMYfexPa9euBeBnf/ZngTafPvLII0BrY73GZMZYKiRUGrnLwVjMOaFWLRs0xhEqjk8++WSg9T3Pg358icnm47lwDPbecNLPlW3etvGVr3xltr3YD3ze7zG5zldeC2NC+53XwnnL+/oohEIIIYQQQgghhBDCijLWCqFaPUXFjq+bEV1qtSIzQO69dFVPVFKcd955AFx22WVAywyphHAF1tVIV9sXczx1D+0ZZ5wBwFlnnQW0lf09e/YAcMcddwAtCzws1UUYH2wb1XPEfrTULJGr7q52q5jz8339mWeemfM9w2qrVd1i/7fvOZ7YJ4ddGWAU8ZqrVNQzyIyn13pSs+T+Livmff7zn5/9m2PxoH67igXnqbvvvhto10Tsdx5X5oqwWOzfjpnGJY71K+1t6PcZm6mkqJUs9WowplOl83/+z/+Znd96be/V18RKTeeeey4AF1988ZxjuvXWWwG44YYbgO6VF0Oo2E+cR6+99lqgKfBU8PTan2plWGMZP8d5+YknngBavx21HQaJuXrHtuGYp2fQQw89NOd11SqTOu873j711FOz7bz6m/b7t7vL4Cd/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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
- }
- ],
- "source": [
- "fig = plt.figure(figsize=(20,10))\n",
- "a = fig.add_subplot(1, 2, 1,)\n",
- "imgplot = plt.imshow(frame_a, cmap='gray')\n",
- "a.set_title('frame_a')\n",
- "a = fig.add_subplot(1, 2, 2)\n",
- "imgplot = plt.imshow(frame_b, cmap='gray')\n",
- "a.set_title('frame_b')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Example 2: pre attained experimental data ###\n",
- "In this case experiment data is passed to the function, and the interpolation flag is enabled. Thus using the data to create a continous flow field by interpolation and then using the field to create the paramters."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [],
- "source": [
- "data = np.load('PIV_experiment_data.npz')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [],
- "source": [
- "data = np.stack([data['X'], data['Y'],data['U'] ,data['V']], axis=2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Requested pair loss: 10 Actual pair loss: 11\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/user/miniconda3/envs/openpiv/lib/python3.7/site-packages/scipy/interpolate/_fitpack_impl.py:976: RuntimeWarning: No more knots can be added because the additional knot would\n",
- "coincide with an old one. Probable cause: s too small or too large\n",
- "a weight to an inaccurate data point. (fp>s)\n",
- "\tkx,ky=1,1 nx,ny=4,4 m=256 fp=67208.139125 s=0.000000\n",
- " warnings.warn(RuntimeWarning(_iermess2[ierm][0] + _mess))\n",
- "/home/user/miniconda3/envs/openpiv/lib/python3.7/site-packages/scipy/interpolate/_fitpack_impl.py:976: RuntimeWarning: No more knots can be added because the additional knot would\n",
- "coincide with an old one. Probable cause: s too small or too large\n",
- "a weight to an inaccurate data point. (fp>s)\n",
- "\tkx,ky=1,1 nx,ny=4,4 m=256 fp=120693.580633 s=0.000000\n",
- " warnings.warn(RuntimeWarning(_iermess2[ierm][0] + _mess))\n"
- ]
- }
- ],
- "source": [
- "ground_truth,cv,x_1,y_1,U_par,V_par,par_diam1,par_int1,x_2,y_2,par_diam2,par_int2 = synimagegen.create_synimage_parameters(data,[0,1],[0,1],[256,256],inter=True,dt=0.0025)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [],
- "source": [
- "frame_a = synimagegen.generate_particle_image(256, 256, x_1, y_1, par_diam1, par_int1,16)\n",
- "frame_b = synimagegen.generate_particle_image(256, 256, x_2, y_2, par_diam2, par_int2,16)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "scrolled": true
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Text(0.5, 1.0, 'frame_b')"
- ]
- },
- "execution_count": 9,
- "metadata": {},
- "output_type": "execute_result"
- },
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
- }
- ],
- "source": [
- "fig = plt.figure(figsize=(20,10))\n",
- "a = fig.add_subplot(1, 2, 1)\n",
- "imgplot = plt.imshow(frame_a, cmap='gray')\n",
- "a.set_title('frame_a')\n",
- "a = fig.add_subplot(1, 2, 2)\n",
- "imgplot = plt.imshow(frame_b, cmap='gray')\n",
- "a.set_title('frame_b')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Example 3: flow simulation results ###\n",
- "In this case flow simulation results are passed to the function, in the form of a tab-delimited text file.\n",
- "The file is parsed and the data is used in order to continous flow field by interpolation.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/user/miniconda3/envs/openpiv/lib/python3.7/site-packages/scipy/interpolate/_fitpack_impl.py:976: RuntimeWarning: No more knots can be added because the number of B-spline\n",
- "coefficients already exceeds the number of data points m.\n",
- "Probable causes: either s or m too small. (fp>s)\n",
- "\tkx,ky=1,1 nx,ny=81,67 m=5106 fp=0.183584 s=0.000000\n",
- " warnings.warn(RuntimeWarning(_iermess2[ierm][0] + _mess))\n"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Requested pair loss: 10 Actual pair loss: 10\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/user/miniconda3/envs/openpiv/lib/python3.7/site-packages/scipy/interpolate/_fitpack_impl.py:976: RuntimeWarning: No more knots can be added because the number of B-spline\n",
- "coefficients already exceeds the number of data points m.\n",
- "Probable causes: either s or m too small. (fp>s)\n",
- "\tkx,ky=1,1 nx,ny=49,112 m=5106 fp=1.616903 s=0.000000\n",
- " warnings.warn(RuntimeWarning(_iermess2[ierm][0] + _mess))\n"
- ]
- }
- ],
- "source": [
- "path_to_file = os.getcwd() + '/velocity_report.txt'\n",
- "ground_truth,cv,x_1,y_1,U_par,V_par,par_diam1,par_int1,x_2,y_2,par_diam2,par_int2 = synimagegen.create_synimage_parameters(None,[0,1],[0,1],[256,256],path=path_to_file,inter=True,dt=0.0025)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [],
- "source": [
- "frame_a = synimagegen.generate_particle_image(256, 256, x_1, y_1, par_diam1, par_int1,16)\n",
- "frame_b = synimagegen.generate_particle_image(256, 256, x_2, y_2, par_diam2, par_int2,16)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Text(0.5, 1.0, 'frame_b')"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- },
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
- }
- ],
- "source": [
- "fig = plt.figure(figsize=(20,10))\n",
- "a = fig.add_subplot(1, 2, 1)\n",
- "imgplot = plt.imshow(frame_a, cmap='gray')\n",
- "a.set_title('frame_a')\n",
- "a = fig.add_subplot(1, 2, 2)\n",
- "imgplot = plt.imshow(frame_b, cmap='gray')\n",
- "a.set_title('frame_b')"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "openpiv",
- "language": "python",
- "name": "openpiv"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.7.4"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/synimage/synimagegen.py b/synimage/synimagegen.py
deleted file mode 100644
index 2ab099ec..00000000
--- a/synimage/synimagegen.py
+++ /dev/null
@@ -1,305 +0,0 @@
-"""This module contains a pure python implementation of the basic
-cross-correlation algorithm for PIV image processing."""
-
-__licence_ = """
-Copyright (C) 2011 www.openpiv.net
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-import os
-import numpy as np
-import scipy
-import scipy.special
-import scipy.interpolate
-from scipy import io
-import matplotlib.pyplot as pl
-import matplotlib.cm as cm
-from PIL import Image
-
-class continuous_flow_field:
- def __init__(self,data,inter=False):
- '''
- Checks if the continous flow should be created from a set of data points
- if so it interpolates them for a continuous flow field
- '''
- self.inter = inter
- if inter:
- self.f_U = scipy.interpolate.interp2d(data[:,0],data[:,1],data[:,2])
- self.f_V = scipy.interpolate.interp2d(data[:,0],data[:,1],data[:,3])
-
-
- '''
- Defining a synthetic flow field
- '''
- def f_U(self,x,y):
- #example for synthetic U velocity
- u=2.5+0.5*np.sin((x**2+y**2)/0.01)
- return u
-
-
- def f_V(self,x,y):
- #example for synthetic V velocity
- v=0.5+0.1*np.cos((x**2+y**2)/0.01)
- return v
-
- def get_U_V(self,x,y):
- #return the U and V velocity at a certain position
- if self.inter:
- return self.f_U(x,y)[0],self.f_V(x,y)[0]
- else:
- return self.f_U(x,y),self.f_V(x,y)
-
- def create_syn_quiver(self,number_of_grid_points,path=None):
- #return and save a synthetic flow map
- X,Y = np.meshgrid(np.linspace(0,1,number_of_grid_points),np.linspace(0,1,number_of_grid_points))
- U = np.zeros(X.shape)
- V = np.zeros(Y.shape)
- for r in range(X.shape[0]):
- for c in range(X.shape[1]):
- u,v = self.get_U_V(X[r,c],Y[r,c])
- U[r,c] = u
- V[r,c] = v
-
-
- m = np.sqrt(np.power(U, 2) + np.power(V, 2))
- fig = pl.quiver(X, Y, U, V,m,clim=[1.5,m.max()],scale=100,width=0.002,headwidth=6,minshaft=2)
- cb = pl.colorbar(fig)
- cb.set_clim(vmin=1.5, vmax=m.max())
-
-
- if not path:
- pl.savefig('syn_quiver.png', dpi=400)
- pl.close()
- else:
- pl.savefig(path + 'syn_quiver.png', dpi=400)
- pl.close()
-
- return X,Y,U,V
-
-
-def create_synimage_parameters(input_data,x_bound,y_bound,image_size,path='None',inter=False,den=0.008,per_loss_pairs=2,par_diam_mean=15**(1.0/2),par_diam_std=1.5,par_int_std=0.25,dt=0.1):
- """Creates the synthetic image with the synthetic image parameters
-
- Parameters
- ----------
- input_data: None or numpy array
- If you have data from which to genrate the flow feild the synthetic image.
- It should be passed on as a numpy array with columns being (X grid position,Y grid position,U velocity at (X,Y) grid point,V velocity at (X,Y) grid point)
- Else, pass None and define a synthetic flow field in continuous_flow_field class.
-
- x_bound,y_bound: list/tuple of floats
- The boundries of interest in the synthetic flow field.
-
- image_size: list/tuple of ints
- The desired image size in pixels.
-
- path: str('None' for no generating data)
- Path to txt file of input data.
-
- inter: boolean
- False if no interpolation of input data is needed.
- True if there is data you want to interpolate from.
-
- den: float
- Defines the number of particles per image.
-
- per_loss_pairs: float
- Percentage of synthetic pairs loss.
-
- par_diam_mean: float
- Mean particle diamter in pixels.
-
- par_diam_std: float
- Standard deviation of particles diamter in pixels.
-
- par_int_std: float
- Standard deviation of particles intensities.
-
- dt: float
- Synthetic time difference between both images.
-
- Returns
- -------
- ground_truth: continuous_flow_field class
- The synthetic ground truth as a continuous_flow_field class.
-
- cv:
- Convertion value to convert U,V from pixels/images to meters/seconds.
-
- x_1,y_1: numpy array
- Position of particles in the first synthetic image.
-
- U_par,V_par: numpy array
- Velocity speeds for each particle.
-
- par_diam1: numpy array
- Particle diamters for the first synthetic image.
-
- par_int1: numpy array
- Particle intensities for the first synthetic image.
-
- x_2,y_2: numpy array
- Position of particles in the second synthetic image.
-
- par_diam2: numpy array
- Particle diamters for the second synthetic image.
-
- par_int2: numpy array
- Particle intensities for the second synthetic image.
- """
-
- #Data processing
-
- if not path == 'None':
- f = open(path,'r')
- data = f.readlines()
- f.close()
- data = [line.split('\t') for line in data]
- data = np.array(data).astype(float)
- data = np.array([line for line in data.tolist() if 1.2*x_bound[1]>=line[1]>=0.8*x_bound[0] and 1.2*y_bound[1]>=line[2]>=0.8*y_bound[0]])
-
- else:
- data = input_data
-
- if inter:
- cff = continuous_flow_field(data,inter=True)
- else:
- cff = continuous_flow_field(None)
-
- #Creating syn particles
-
- num_of_par = int(image_size[0]*image_size[1]*den)
- num_of_lost_pairs = num_of_par*(per_loss_pairs/100)
- x_1 = np.random.uniform(x_bound[0]*0.8,x_bound[1]*1.2,num_of_par)
- y_1 = np.random.uniform(y_bound[0]*0.8,y_bound[1]*1.2,num_of_par)
- par_diam1 = np.random.normal(par_diam_mean,par_diam_std,num_of_par)
- particleCenters = np.random.uniform(size=num_of_par)-0.5
- par_int1 = np.exp(-particleCenters**2/(2*par_int_std**2))
- U_par = np.zeros(x_1.shape)
- V_par = np.zeros(y_1.shape)
- x_2 = np.zeros(x_1.shape)
- y_2 = np.zeros(y_1.shape)
- par_diam2 = np.zeros(par_diam1.shape)
- par_int2 = np.zeros(par_int1.shape)
-
- def Move_par(i):
- U_par[i],V_par[i] = cff.get_U_V(x_1[i],y_1[i])
- x_2[i] = x_1[i]+U_par[i]*dt
- y_2[i] = y_1[i]+V_par[i]*dt
- par_diam2[i] = par_diam1[i]
- par_int2[i] = par_int1[i]
-
- cpl = 0
- for i in range(num_of_par):
- if cplparticleCenters[i] or 0.4=xy[0]>=x_bound[0] and y_bound[1]>=xy[1]>=y_bound[0]])
- bounded_xy_2 = np.asarray([xy for xy in xy_2 if x_bound[1]>=xy[0]>=x_bound[0] and y_bound[1]>=xy[1]>=y_bound[0]])
-
- #Tranforming coordinates into pixels
-
- x1 = ((bounded_xy_1[:,0]-x_bound[0])/(x_bound[1]-x_bound[0]))*image_size[0]
- y1 = ((bounded_xy_1[:,1]-y_bound[0])/(y_bound[1]-y_bound[0]))*image_size[1]
-
- x2 = ((bounded_xy_2[:,0]-x_bound[0])/(x_bound[1]-x_bound[0]))*image_size[0]
- y2 = ((bounded_xy_2[:,1]-y_bound[0])/(y_bound[1]-y_bound[0]))*image_size[1]
-
- conversion_value = min((x_bound[1]-x_bound[0])/image_size[0],(y_bound[1]-y_bound[0])/image_size[1])/dt
-
- return cff,conversion_value,x1,y1,bounded_xy_1[:,2],bounded_xy_1[:,3],bounded_xy_1[:,4],bounded_xy_1[:,5],x2,y2,bounded_xy_2[:,2],bounded_xy_2[:,3]
-
-
-
-def generate_particle_image(HEIGHT, WIDTH, X, Y, PARTICLE_DIAMETERS, PARTICLE_MAX_INTENSITIES,BIT_DEPTH):
- """Creates the synthetic image with the synthetic image parameters
- Should be run with the parameters of each image (first,second) separately.
-
- Parameters
- ----------
- HEIGHT, WIDTH: int
- The number of pixels in the desired output image.
-
- X,Y: numpy array
- The X and Y positions of the particles, created by create_synimage_parameters().
-
- PARTICLE_DIAMETERS, PARTICLE_MAX_INTENSITIES: numpy array
- The intensities and diameters of the particles, created by create_synimage_parameters().
-
- BIT_DEPTH: int
- The bit depth of the desired output image.
-
- Returns
- -------
- Image: numpy array
- The desired synthetic image.
-
- """
- render_fraction = 0.75
- IMAGE_OUT = np.zeros([HEIGHT, WIDTH])
-
- minRenderedCols = (X - render_fraction * PARTICLE_DIAMETERS).astype(int)
- maxRenderedCols = (np.ceil(X + render_fraction * PARTICLE_DIAMETERS)).astype(int)
- minRenderedRows = (Y - render_fraction * PARTICLE_DIAMETERS).astype(int)
- maxRenderedRows = (np.ceil(Y + render_fraction * PARTICLE_DIAMETERS)).astype(int)
-
- index_to_render = []
-
- for i in range(X.size):
- if 1