Skip to content

Instantly share code, notes, and snippets.

@alexlib
Forked from nepomnyi/customDeen.py
Created October 19, 2022 21:28
Show Gist options
  • Save alexlib/4b95d54f6fdc33097794b6fcfc76b017 to your computer and use it in GitHub Desktop.
Save alexlib/4b95d54f6fdc33097794b6fcfc76b017 to your computer and use it in GitHub Desktop.
The custom implementation of the PIV image preprocessing algorithm after N. Deen et al., "On image preprocessing for PIV of single- and two-phase flows over reflecting objects", Exp. Fluids, 49(2):525-530, 2010.
def customDeen(frame0,
frame1,
algorithmType = 'basic',
cliplimit = 2.0,
tileGridSize = (4, 4)
):
"""
This is the custom implementation of the image processing alogrithm for PIV
after Deen, Willems, Annaland, Kuipers, Lammertink, Kemperman, Wessling,
Meer, "On image preprocessing for PIV of single and two phase flows over
reflecting objects", 2010, Exp Fluids, p.526, Fig.1.
I say custom because I substituted the first min-max filtering block
(i.e. normalization block) with the adaptive histogram equalization. That's
because neither the basic normalization as shown in the article itself, nor
the Adrian&Westerweel min-max filter gave me expected result (I kept getting
binarized image, whereas I should've gotten gray scaled image; strectching
doesn't do anything to binary images).
Parameters: frame0 (cv2.imread) - the original image of the first PIV frame
frame1 (cv2.imread) - the original image of the second PIV frame
algorithmType (str) - 'basic' which is default or 'advanced';
'basic' is the single phase flow
implementation (see Fig.1 in the
referenced article),
'advanced' is the two phase flow
implementation (see Fig.1 in the
referenced article)
clipLimit (float) - 2.0 by default, is the parameter of the
adaptive histogram equalization
tileGridSize (nd.array) - (4, 4) by default, is the parameter of
the adaptive histogram equalization
Returns: frame0Subtracted (cv2.imread) - processed frame0
frame1Subtracted (cv2.imread) - processed frame1
"""
# Right now only 'basic' option is implemented, thus, no if statements ...
# Start with checking if the images are gray scaled
if len(frame0.shape) > 2:
frame0 = cv2.cvtColor(frame0, cv2.COLOR_BGR2GRAY)
if len(frame1.shape) > 2:
frame1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
# First block: adaptive histogram equalization which is the substitue for
# normalization
clahe = cv2.createCLAHE(clipLimit = cliplimit, tileGridSize = tileGridSize)
frame0Enhanced = clahe.apply(frame0)
frame1Enhanced = clahe.apply(frame1)
# Second block: stretching
frame0Stretched = stretchFilter(frame0Enhanced)
frame1Stretched = stretchFilter(frame1Enhanced)
# Third block: background subtraction. Note, that it can result in negative
# values. That's why the formula in the article takes max.
# But cv2.subtract takes care of the negative values, so we don't need max.
frame0Subtracted = cv2.subtract(frame0Stretched, frame1Stretched)
frame1Subtracted = cv2.subtract(frame1Stretched, frame0Stretched)
return frame0Subtracted, frame1Subtracted
def stretchFilter(img):
"""
This is the implementation of the stretching step after Deen, Willems,
Annaland, Kuipers, Lammertink, Kemperman, Wessling, Meer, "On image
preprocessing for PIV of single and two phase flows over reflecting
objects", 2010, Exp Fluids, p.526, Fig.1.
Parameters: img (cv2.imread) - original image
Returns: stretchedImg (cv2.imread) - image with the stretched intensities
"""
# cv2.minMaxLoc finds min and max intensities in an image. It works with
# single channel images only, therefore we have to make sure
# we don't have more than 1 channel in the original image. I'm not going to
# use the if statement for that. Instead, no matter what, automatically
# convert the original image into a 1D array using np.flatten().
Imin, Imax, _, _ = cv2.minMaxLoc(img.flatten()) # min and max intensities
stretchedImg = (img - Imin) / (Imax - Imin)
return stretchedImg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment