通过NxN帧迭代numpy 2d数组过滤图像的最佳方法是什么?

问题描述 投票:0回答:1

有简单的模糊滤镜可以计算周围像素的亮和暗。这是代码。但是我的实现相当慢(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秒)我如何加快代码速度?

python performance numpy blur scikit-image
1个回答
0
投票

首先,您的窗口代码中存在一个小错误。你需要剪切为零,因为负指数环绕。

    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')
© www.soinside.com 2019 - 2024. All rights reserved.