有简单的模糊滤镜可以计算周围像素的亮和暗。这是代码。但是我的实现相当慢(780x1200阵列大约需要3秒)。当然可以快得多
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秒)我如何加快代码速度?
首先,您的窗口代码中存在一个小错误。你需要剪切为零,因为负指数环绕。
y = (max(pos[0] - n//2, 0), pos[0]+n//2+1) # frame borders
x = (max(pos[1] - n//2, 0), pos[1]+n//2+1)
此外,您可能希望将out_img = np.empty_like(img)
行移动到使img
成为布尔数组之前。
这是使用cumsum
的更快的方法:
y, x = image.shape
padded = np.zeros((y+k, x+k), 'i1')
padded[k//2+1:-k//2+1, k//2+1:-k//2+1] = image > 180
dint = padded.cumsum(1).cumsum(0)
result = dint[k:, k:] + dint[:-k, :-k] - dint[k:, :-k] - dint[:-k, k:]
result = (result * 255 / (k*k)).astype('u1')