Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
矢量化模糊图像的Python函数_Python_Numpy_Image Processing_Vectorization - Fatal编程技术网

矢量化模糊图像的Python函数

矢量化模糊图像的Python函数,python,numpy,image-processing,vectorization,Python,Numpy,Image Processing,Vectorization,我已经使用纯Python制作了一个函数来模糊我给出的任何图像。现在我想使用NumPy并删除循环的所有 def模糊图像(src、dst): (h,w,c)=src形状 对于范围(h-1)内的x: 对于范围内的y(w-1): 对于范围(c)内的z: 如果x!=0或y!=0: dst[x,y,z]=(src[x,y,z] +src[x-1,y,z] +src[x+1,y,z] +src[x,y-1,z] +src[x,y+1,z] +src[x-1,y-1,z] +src[x-1,y+1,z] +sr

我已经使用纯Python制作了一个函数来模糊我给出的任何图像。现在我想使用NumPy并删除循环的所有

def模糊图像(src、dst):
(h,w,c)=src形状
对于范围(h-1)内的x:
对于范围内的y(w-1):
对于范围(c)内的z:
如果x!=0或y!=0:
dst[x,y,z]=(src[x,y,z]
+src[x-1,y,z]
+src[x+1,y,z]
+src[x,y-1,z]
+src[x,y+1,z]
+src[x-1,y-1,z]
+src[x-1,y+1,z]
+src[x+1,y-1,z]
+src[x+1,y+1,z])/9
如果x==0:
dst[x,y,z]=(src[x,y,z]
+src[x,y,z]
+src[x+1,y,z]
+src[x,y-1,z]
+src[x,y+1,z]
+src[x,y-1,z]
+src[x,y+1,z]
+src[x+1,y-1,z]
+src[x+1,y+1,z])/9
如果y==0:
dst[x,y,z]=(src[x,y,z]
+src[x-1,y,z]
+src[x+1,y,z]
+src[x,y,z]
+src[x,y+1,z]
+src[x-1,y,z]
+src[x-1,y+1,z]
+src[x+1,y,z]
+src[x+1,y+1,z])/9
返回dst
如何使用NumPy使此代码变得更好?最好的情况是删除所有
for
循环?有什么建议吗

编辑:我试图在没有任何库帮助我模糊图像的情况下解决这个问题。我使用纯python对其进行模糊处理,现在寻找一些技巧,以便所有计算量大的位都使用numpy数组。没有很多使用numpy的经验://

只需编译它 我假设你想加速你的功能。最简单也是最快的方法是使用Cython或Numba之类的编译器

这个问题同样令人尴尬

示例

import numpy as np
import numba as nb

@nb.njit(error_model="numpy",parallel=True)
def blur_image_nb(src, dst):
    (h, w, c) = src.shape
    for x in nb.prange(h-1):
        for y in range(w-1):
            for z in range(c):
                if x != 0 or y != 0:
                    dst[x, y, z] = (src[x, y, z]
                    + src[x-1, y, z]
                    + src[x+1, y, z]
                    + src[x, y-1, z]
                    + src[x, y+1, z]
                    + src[x-1, y-1, z]
                    + src[x-1, y+1, z]
                    + src[x+1, y-1, z]
                    + src[x+1, y+1, z]) / 9
                if x == 0:
                    dst[x, y, z] = (src[x, y, z]
                    + src[x, y, z]
                    + src[x+1, y, z]
                    + src[x, y-1, z]
                    + src[x, y+1, z]
                    + src[x, y-1, z]
                    + src[x, y+1, z]
                    + src[x+1, y-1, z]
                    + src[x+1, y+1, z]) / 9
                if y == 0:
                    dst[x, y, z] = (src[x, y, z]
                    + src[x-1, y, z]
                    + src[x+1, y, z]
                    + src[x, y, z]
                    + src[x, y+1, z]
                    + src[x-1, y, z]
                    + src[x-1, y+1, z]
                    + src[x+1, y, z]
                    + src[x+1, y+1, z]) / 9
    return dst
编辑

当然,也有一些简单的优化是可能的,比如不必要的除以常量值。也可以乘以只计算一次的因子

#You can achieve the same with fastmath=True
#Divisions are quite costly
@nb.njit(error_model="numpy",parallel=True)
def blur_image_nb_2(src, dst):
    (h, w, c) = src.shape
    fact=1./9.
    for x in nb.prange(h-1):
        for y in range(w-1):
            for z in range(c):
                if x != 0 or y != 0:
                    dst[x, y, z] = (src[x, y, z]
                    + src[x-1, y, z]
                    + src[x+1, y, z]
                    + src[x, y-1, z]
                    + src[x, y+1, z]
                    + src[x-1, y-1, z]
                    + src[x-1, y+1, z]
                    + src[x+1, y-1, z]
                    + src[x+1, y+1, z]) *fact
                if x == 0:
                    dst[x, y, z] = (src[x, y, z]
                    + src[x, y, z]
                    + src[x+1, y, z]
                    + src[x, y-1, z]
                    + src[x, y+1, z]
                    + src[x, y-1, z]
                    + src[x, y+1, z]
                    + src[x+1, y-1, z]
                    + src[x+1, y+1, z]) *fact
                if y == 0:
                    dst[x, y, z] = (src[x, y, z]
                    + src[x-1, y, z]
                    + src[x+1, y, z]
                    + src[x, y, z]
                    + src[x, y+1, z]
                    + src[x-1, y, z]
                    + src[x-1, y+1, z]
                    + src[x+1, y, z]
                    + src[x+1, y+1, z]) *fact
    return dst
计时

src=np.random.rand(1024,1024,3)
dst=np.empty((1024,1024,3))

%timeit blur_image(src, dst)
8.08 s ± 52.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit blur_image_nb(src, dst)
5.19 ms ± 954 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit blur_image_nb_2(src, dst)
3.13 ms ± 167 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

#Just for comparison
%timeit res=np.copy(src)
11.1 ms ± 28.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit np.copyto(dst, src)
2.44 ms ± 53.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

import numpy as np
from PIL import Image, ImageFilter
import scipy.signal as ss

src=(np.random.rand(1024,1024,3)*255).astype(np.uint8)
img = Image.fromarray(src.astype(np.uint8))

%timeit img.filter(ImageFilter.BoxBlur(radius=3))
16.1 ms ± 65 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

kernel = np.ones((3, 3)) / 9  # The 'boxcar'.
#3x in a example where src.shape[2]==3
%timeit ss.convolve(src[:,:,0], kernel, mode='same')
76.6 ms ± 16.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
结论


通常情况下,您只需使用已经可用的函数,如他的答案中所示的@kwinkunks,但简单地编译函数会显示出比PIL更好的性能(PIL在数据类型方面也有一些限制)和更一般的卷积。

如果我正确地阅读了您的代码,您正在描述使用3×3 boxcar过滤器进行过滤。如果您关心性能,那么使用现有库来实现这一点可能是一个好主意,因为它将比您可以轻松实现的任何功能都要优化

例如,您所做的可以通过卷积来实现,卷积在中提供。因此,您可以对每个通道执行此操作,然后堆叠生成的阵列:

import numpy as np
import scipy.signal as ss

arr = np.random.random((100, 100))  # Some fake data.
kernel = np.ones((3, 3)) / 9  # The 'boxcar'.

ss.convolve(arr, kernel, mode='same')
模糊也可在以下位置使用:

还有很多其他的方法可以做到这一点,包括在傅立叶空间()中


这些其他方法的一个很好的特点是,它们不会将过滤器设计硬编码到代码中,因此很容易尝试其他内核,例如高斯核。

我想不久前我也做过类似的事情。我解决这个问题的方法是制作一个图像副本,其中每个像素值实际上是围绕中心像素的像素值的3x3数组。然后,您应该能够将所有这些值添加到原始像素值。如果您使用这种方法,可能会有很大帮助。您主要关心的是性能还是如何将其矢量化?另一种可能是利用gpu计算卷积滤波器模糊。这可以使用pyopengl来利用,但不是一个预构建的解决方案。谢谢!我知道有很多不同的库可以为我模糊图像。我只是想找到一种不用所有的图书馆就能做到这一点的方法。并要求一些提示,以帮助我的方式。我没有很多使用numpy的经验:)@Panini所以你想要一个纯numpy(无SciPy)的方式来做吗?你知道NumPy是一个库(建立在许多其他库的基础上),对吗?它的许多功能(例如,
np.convolve
)都是一维的,因此存在局限性。所以你必须在一个方向卷积,然后在另一个方向卷积。这有意义吗?为了纯粹的指导目的,而不是为了生产,以下是如何实现具有1D过滤器两个正交通道的2D过滤器:
import numpy as np
from PIL import Image, ImageFilter

arr = np.random.randint(0, 256, size=((100, 100, 3)), dtype=np.uint8)
img = Image.fromarray(arr)

img.filter(ImageFilter.BoxBlur(radius=3))