Существует простой фильтр размытия, который считает светлые и темные окружающие пиксели. Вот код Но моя реализация довольно медленная (около 3 секунд для массива 780x1200). Конечно, это может быть намного быстрее
import time
import numpy as np
from skimage.data import imread
def _filter_step(in_img, out_img, n, pos=(0,0)):
y = (pos[0] - n//2, pos[0]+n//2+1) # frame borders
x = (pos[1] - n//2, pos[1]+n//2+1)
frame = in_img[y[0]:y[1], x[0]:x[1]] # get frame
whites = np.count_nonzero(frame) # count light pixels
k = whites/(n*n) # calculate proportion
out_img[pos[0], pos[1]] = int(k * 255) # write new pixel
def make_filter(img, n):
if not n % 2:
raise ValueError("n must be odd")
img = img > 180 # binarize
out_img = np.empty_like(img) # output array
for i in range(img.shape[0]):
for j in range(img.shape[1]):
_filter_step(img, out_img, n, (i, j))
return out_img
if __name__ == "__main__":
image = imread("img780x1200.jpg", as_gray=True)
n = 11
time_start = time.time()
image1 = make_filter(image, n)
print(time.time() - time_start) # ~3 sec
Я пытался провести параллельные вычисления:
import multiprocessing as mp
import ctypes as ct
def iter_image(x1, y1, x2, y2, img, out_img, n, mode=0):
out_img = np.frombuffer(out_img, dtype=ct.c_int).reshape(img.shape)
for y in range(img.shape[0])[::(-1)**mode]:
for x in range(img.shape[1])[::(-1)**mode]:
if mode:
y2.value, x2.value = y, x
else:
y1.value, x1.value = y, x
if y1.value < y2.value or x1.value < x2.value:
_filter_step(img, out_img, n, ((y1.value,x1.value), (y2.value,x2.value))[mode])
else:
return ((y1, x1), (y2, x2))[mode]
return ((y1, x1), (y2, x2))[mode]
def mp_make_filter(img, n):
if not n % 2:
raise ValueError("n must be odd")
img = img > 180
x1 = mp.Value('i', 0, lock=False)
y1 = mp.Value('i', 0, lock=False)
x2 = mp.Value('i', 0, lock=False)
y2 = mp.Value('i', 0, lock=False)
out_img = mp.Array('i', np.empty(img.shape[0] * img.shape[1], dtype=ct.c_int), lock=False)
p1 = mp.Process(target=iter_image, args=(x1, y1, x2, y2, img, out_img, n, 0))
p2 = mp.Process(target=iter_image, args=(x1, y1, x2, y2, img, out_img, n, 1))
p1.start()
p2.start()
p1.join()
p2.join()
return np.frombuffer(out_img, dtype=ct.c_int).reshape(img.shape)
Этот код повторяет массив в 2 потока, пока они не "встречаются" друг с другом. Но это делает производительность еще медленнее (около 5 секунд)
Как я могу ускорить код?