Skip to content

Instantly share code, notes, and snippets.

@alexlib
Forked from nepomnyi/MinMaxForPIV.py
Created October 19, 2022 21:28
Show Gist options
  • Save alexlib/9156596592e6f0e7673fbd1457dd3680 to your computer and use it in GitHub Desktop.
Save alexlib/9156596592e6f0e7673fbd1457dd3680 to your computer and use it in GitHub Desktop.
A python min-max filter implementation after Adrain & Westerweel, "Particle image velocimetry", 2011, p.250.
import cv2
import numpy as np
def minMaxFilter(img, filterSize, minContrast):
"""
After R.Adrian, J.Westerweel, "Particle image velocimetry", Cambridge
university press, 2011. See ch.6.1.2, p.248-250.
Parameters: img (cv2.imread) - image to be filtered
filterSize (nd.array) - a 1x2 numpy array of the filter height
and width correspondingly
minContrast (float) - minimum contrast value imposed on the
image (if the calculated contrast falls
bellow this level, this level is imposed
as the contrast: see the referenced book)
Returns: imgFiltered (cv2.imread) - filtered image
"""
# cv2 doesn't have min and max filters, erode and dilate play the role of
# min and max filters correspondingly. Note, that, in opencv, erode and
# dilate can be implemented to gray scale images (recall, that normally
# they can only be implemented to binary images.)
# Define the lower and upper envelopes (see the book) of the image intensity
showWindowWell("original image", img, 0, 0)
low = cv2.erode(img,
cv2.getStructuringElement(cv2.MORPH_RECT, filterSize))
showWindowWell("low before blurrig", low, 0, 0)
upp = cv2.dilate(img,
cv2.getStructuringElement(cv2.MORPH_RECT, filterSize))
showWindowWell("upp before blurring", upp, 0, 0)
# Smooth the lower and upper envelopes with a uniform filter of the same size
low = lowPassFilter(low, filterSize)
showWindowWell("low after blurring", low, 0, 0)
upp = lowPassFilter(upp, filterSize)
showWindowWell("upp after blurring", upp, 0, 0)
# Define contrast and put a lower limit on it
contrast = cv2.subtract(upp, low)
showWindowWell("contrast before capping", contrast, 0, 0)
contrast[contrast < minContrast] = minContrast
showWindowWell("contrast after capping", contrast, 0, 0)
# Normalize image intensity, multiplication by 255 is necessary because
# if the pixel value of the original image is smaller than the corresponding
# value of the contrast, you get a less than 1 value after the division,
# which at the show image operation gets converted to 0 and you get black
# image
showWindowWell("img - low", cv2.subtract(img, low), 0, 0)
imgFiltered = cv2.divide(cv2.subtract(img, low), contrast) * 255
showWindowWell("filtered image", cv2.subtract(img, low), 0, 0)
return imgFiltered
def showWindowWell(winname, img, x, y):
"""
cv2.imshow locates the image at the corner of the screen where I
can't see the full image. I have to relocate it programmatically.
This function wraps up all the image-showing and locating procedures to
ease image showing.
Note: don't forget to press "Enter" to close the window.
Parameters: winname (string) - the name of the window
img (cv2.imread) - the image I want to display in the window
x, y (int) - pixel coordinates of the window location in the
screen
Returns: none - just shows the image in the chosen location on the screen
"""
img = cv2.resize(img, (1200, 800)) # first, resize the image
cv2.namedWindow(winname) # second, create a window for the image
cv2.moveWindow(winname, x, y) # move it to (x,y)
cv2.imshow(winname, img)
cv2.waitKey()
cv2.destroyAllWindows()
def lowPassFilter(img_src, kernelSize):
"""
This is a uniform low pass filter, which measn that all the values in the
filter kernel are equal to 1.
Parameters: img_src (cv2.imread) - image to be filtered
kernelSize (nd.array) - 1x2 numpy array where the first value is
the kernel's height, the second value is
the kernel's width
Returns: img_rst (cv2.imread) - filtered image
"""
kernel = np.ones(kernelSize)
kernel = kernel/(np.sum(kernel) if np.sum(kernel)!=0 else 1)
img_rst = cv2.filter2D(img_src, -1, kernel)
return img_rst
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment