def PIVanalysis(dataArray,
imageShape,
searchAreaSize,
overlap,
scalingFactor,
deltaT,
mask,
saveToDir,
counter,
threshold = 0.8
):
"""
See ensemble_correlation.ipynb OpenPIV tutorial.
Parameters: dataArray (numpy array) - an array of PIV images that contains only
one PIV pair, its structure is
dataArray = np.asarray([frameA, frameB])
Returns: None
"""
# The name of the OpenPIV txt file.
nameTXT = saveToDir / 'OpenPIVtxtFileForPair{}.txt'.format(counter)
# Find the correlations map.
corrs = pyprocess.fft_correlate_images(
pyprocess.moving_window_array(dataArray[0],searchAreaSize,overlap),
pyprocess.moving_window_array(dataArray[1],searchAreaSize,overlap),
normalized_correlation=False
)
mesh = pyprocess.get_field_shape(imageShape,
search_area_size = searchAreaSize,
overlap = overlap
)
nrows, ncols = mesh[0], mesh[1]
# Having found correlations, we can find corresponding displacements in pix.
# IMPOTANT: they use u and v for displacements as well as for velocities in
# OpenPIV. Since that's confusing, I decided to use xDisp and yDisp for
# displacements and u and v for velocities.
xDisp, yDisp = pyprocess.correlation_to_displacement(corrs, nrows, ncols)
# Having found displacements in pix, we can find corresponding velocities in
# pix/time
u = xDisp/deltaT # pix/s
v = yDisp/deltaT # pix/s
x, y = pyprocess.get_coordinates(imageShape,
search_area_size = searchAreaSize,
overlap = overlap
)
# Mask out the areas without the flow right now (bubbles or corners).
grid_mask = preprocess.prepare_mask_on_grid(x, y, mask[:,::-1])
masked_u = np.ma.masked_array(u, mask=grid_mask)
masked_v = np.ma.masked_array(v, mask=grid_mask)
# Now let's do validation. Pay attention, that validation doesn't mean automatic
# replacement of the outliers, it means that we are going to detect the outliers
# and mark them as outliers. Their replacement is a separate procedure and will
# be done next. Important: I don't remember why, below, I do median test first
# and signal to noise ratio second. But I remember I did it on purpose. I am
# going to just go with it.
# Do the validation based on the median test (as described in the
# German PIV book on p.185).
invalid_mask_median = validation.local_median_val(masked_u,
masked_v,
u_threshold=50, # abs difference with the median
v_threshold=50, # abs difference with the median
size=2 # size=2 is a 5x5 kernel
)
# Now we can replace outliers flagged by the invalid_mask.
masked_u, masked_v = filters.replace_outliers(masked_u.flatten(), masked_v.flatten(),
invalid_mask_median.flatten(),
method = 'localmean',
max_iter = 3,
kernel_size = 1
) # kernel_size=1 is the best; IMPORTANT to flatten u and v
# Do the validation of the correlation peaks.
corrs = corrs.astype('float64')
s2n = pyprocess.sig2noise_ratio(corrs, "peak2mean")
invalid_mask_s2n = validation.sig2noise_val(s2n, threshold = threshold)
# Now we can replace outliers flagged by the invalid_mask.
masked_u, masked_v = filters.replace_outliers(masked_u.flatten(), masked_v.flatten(),
invalid_mask_s2n,
method = 'localmean',
max_iter = 3,
kernel_size = 1 # uset to be 3
) # kernel_size=1 is the best; IMPORTANT to flatten u and v
# Combine the two masks (the way they are combined is copied from the code
# for OpenPIV.validation.typical_validation line 295). These are, actually,
# flags, not masks.
invalid_mask = invalid_mask_s2n | invalid_mask_median.flatten()
x, y, masked_u, masked_v = scaling.uniform(x, y, masked_u, masked_v, scaling_factor = scalingFactor)
# MASK OUT VELOCITY FIELD.
# Before saving the field to a .txt file, give zeros to those vectors that lie in the masked regions.
# Right now, x and y are in the image system of coordinates: x is to the right, y is downwards, (0,0)
# is in the top left corner. I learnt that from the GitHub code of tools.transform_coordinates.
# Since my x and y are in mm, I'm going to use scaling factor to convert them to pix. The I'm going
# to use them to identify whether or not their place on an example masked image is masked.
xFlat = x.flatten()
yFlat = y.flatten()
for i in range(xFlat.size):
if mask[int(yFlat[i]*scalingFactor), int(xFlat[i]*scalingFactor)] == 255:
masked_u[i] = 0
masked_v[i] = 0
x, y, masked_u, masked_v = tools.transform_coordinates(x, y, masked_u, masked_v)
tools.save(str(nameTXT), x, y, masked_u, masked_v, invalid_mask)
# FOR DEBUGGING PURPOSE USE THIS CODE TO PLOT VELOCITY FIELDS INSTEAD OF SAVING THEM:
# figure, _ = tools.display_vector_field(str(nameTXT),
# scaling_factor = scalingFactor,
# scale = 100,
# on_img = False,
# show_invalid = True
# )
# plt.show()