How to improve a variable lens blur in Python OpenCV?
I want to emulate the blur of a cheap camera lens (like Holga). It's not the same as standard Gaussian blur with constant kernel size.
So I'm not sure that I have to use GaussianBlur or 2D filter.
I wrote the code and it works in general.
Input:
Result:
But I feel that it can be done better and faster.
I've found a similar question but it still has no answer.
How to implement different variable kernel shapes and avoid a black border?
import cv2
import numpy as np
import requests
url = r'https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png'
resp = requests.get(url, stream=True).raw
img = np.asarray(bytearray(resp.read()), dtype="uint8")
img = cv2.imdecode(img, cv2.IMREAD_COLOR)
img_lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(img_lab)
# make blur map
height, width = l.shape[:2]
center = np.array([height/2, width/2])
diag = ((height / 2) ** 2 + (width / 2) ** 2) ** 0.5
blur_map = np.linalg.norm(
np.indices(img.shape[:2]) - center[:,None,None] + 0.5,
axis = 0
)
blur_map = blur_map / diag
blur_map = blur_map * blur_rad
cv2.imwrite('blur_map.png', cv2.normalize(blur_map, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_32F))
blur_rad = 15
# bluring
l_blur = np.copy(l)
for x in range(width):
for y in range(height):
kernel_size = int(blur_map[y, x])
cut = l[y - kernel_size:y + kernel_size, x - kernel_size:x + kernel_size].mean()
if kernel_size == 0:
#print(kernel_size)
l_blur[y, x] = l[y, x]
continue
l_blur[y, x] = cut
cv2.imwrite('result_blur.png', l_blur)
Comments
Post a Comment