My goal is to implement a median-filter, which is a function, that replaces each pixel in a (mostly) 2d-array with the median of its surrounding pixels. It can be used to denoise images.
My implementation extracts submatrices from the original matrix, that contain the pixel itself and its neighbors. This extraction is currently done with a for-loop and as you can imagine that for-loop takes away approximately 95% of execution-time.
Here is my current implementation:
def median_blur(img, fsize=3):
img_intermediate = np.zeros((img.shape[0] + 2, img.shape[1] + 2), np.uint8) # First intermediate img, used for padding original image
img_intermediate[1:img.shape[0]+1, 1:img.shape[1]+1] = img
img_result = np.empty((*img.shape, fsize, fsize), np.uint8) # Will contain result, first receives kernel-submatrices
# Extract submatrices from image
for i in range(img.shape[0]):
for j in range(img.shape[1]):
img_result[i, j] = img_intermediate[i:i+fsize, j:j+fsize]
img_result = img_result.reshape(*img.shape, fsize**2) # Reshape Result-Matrix
img_result = np.median(img_result, axis=2) # Calculate median in one go
return img_result.astype('uint8')
How can i extract these submatrices using a vectorized operation?
As a bonus, if someone with experience in computer-vision is reading this: Is there an better approach of implementing a median-filter other than applying it to an intermediate zero-padded matrix?
Thank you very much.
view-as_windows: stackoverflow.com/questions/42831022 and then usenp.median?view_as_windowsis a standalone function codebase. So, you can just pick it up from source.