繁体   English   中英

用NxN帧迭代numpy二维数组以过滤图像的最佳方法是什么?

[英]What is the best way to iterate over numpy 2d array by NxN frame for filtering image?

有一个简单的模糊滤镜,可以对周围的明暗像素进行计数。 这是代码。 但是我的实现相当慢(对于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)

此代码在两个线程彼此不“相遇”时迭代数组中的两个线程。 但这会使性能降低(约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')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM