平铺图像需要很长时间

时间:2014-04-30 01:52:01

标签: python image-processing

我有以下代码基本上采用图像并将其放在像素上,换句话说,获取图像的每个像素并创建一个10x10“像素”,其中包含它们之间的空白,如下所示:

enter image description here

这变得非常缓慢,我想知道这是不正常还是我做了多余的操作?

import numpy as np
from scipy.misc import lena 
import matplotlib.pyplot as plt

def rect(x, y):

    res = (np.abs(x) < .5)*(np.abs(y) < .5)
    return res

def placeOnSLM(FF, image):

    step = .1
    x, y = np.mgrid[0:image.shape[0]+step:step, 0:image.shape[1]+step:step]
    outImage = np.zeros(x.shape)+np.min(image)
    for ix in range(image.shape[0]):
        print ix,'of',image.shape[0]
        for iy in range(image.shape[1]):
            outImage[(np.abs(x-ix-.5)/FF < .5) * (np.abs(y-iy-.5)/FF < .5)] = image[ix, iy]
#             outImage += image[ix, iy]*rect((x-ix-.5)/FF, (y-iy-.5)/FF)
    return outImage

if __name__ == '__main__':

    num = 10
    image = placeOnSLM(.9, lena()[:num,:num])
    plt.imshow(lena()[:num,:num],'gray', interpolation='none')
    plt.colorbar()
    plt.figure()
    plt.imshow(image,'gray',interpolation='none')
    plt.colorbar()
    plt.show()

编辑:

我使用的操作系统是Ubuntu 13.10

2 个答案:

答案 0 :(得分:2)

没有使用for循环的解决方案怎么样?不确定,因为我没有太多使用matplotlib,但我认为它与matlab类似,所以我将用matlab编写,希望将它转换为matplotlib是微不足道的。

解决方案很简单:使用matlabs imresize函数调整图像大小,但设置插值为&#34;最接近&#34;而不是双线性/双三次。如果使图像大10倍,它基本上会产生10x10个色块,其值等于原始图像的一个像素。下面的代码执行它然后添加边距。 (for循环只是测试n的各种值。)

ns= [10:10:100, 500, 1000];
times= zeros(size(ns));

for i= 1:length(ns)

    n= ns(i);
    s= 10; % 10x10 pixels in the result = 1x1 of the original image
    margin= 2;

    % create the image
    im= rand(n,n);

    tic
    % resize the image
    im2= imresize(im, (s+margin)*size(im), 'nearest');

    % add margins
    [x,y]= meshgrid([0:n]*(s+margin), [1:margin]);
    inds= x(:)+y(:);
    im2(inds,:)=0; im2(:, inds)=0;

    times(i)= toc;
    % imagesc(im2); pause; % visualize

end

plot(ns, times);

在我的测试中,当n = 1000时,图像在0.96秒内创建(尽管我有一个四核i5 @ 3.3 GHz。操作系统:Ubuntu 11.10。

答案 1 :(得分:1)

您的重要处理步骤如下:

for ix in range(image.shape[0]):
    print ix,'of',image.shape[0]
    for iy in range(image.shape[1]):
        outImage[(np.abs(x-ix-.5)/FF < .5) * (np.abs(y-iy-.5)/FF < .5)] = image[ix, iy]

您的运行时为O(n^2),正如您在评论中正确提到的那样。 n = 10的1s运行时应缩放到100s。但是,您没有考虑存储图像造成的内存损失。每次通过内部for循环时,都会在图像中添加一块像素。对于较小的n值,这不是一个很大的问题,但对于较大的n值,这会增加很多空间(确切地与n*n成比例!) 。你没有提到你的操作系统,但是在这些较大的n值下检查Python的内存使用情况可能是值得的。您可能会看到一个阈值,操作开始使批次更长(即不能很好地扩展到代码的运行时)。

祝你好运!

编辑:好奇心得到了我的好处,我想看看它在我的机器上是如何工作的。我做了一个快速(尽管有大n,不那么快)的运行时分析。

红色=实际,蓝色=使用理想的n ^ 2运行时

运行时间与n ,对数比例

graph with log scale

运行时间与n

graph

正如你可以清楚地看到的那样,某事发生在n = 60左右。我的内存使用量在那里达到了约80-90%,并且在其余的运行中保持在90%的范围内。我最好的猜测是由于图像本身在内存中,因为在这些运行期间CPU使用率也非常高。

编辑2

结果是这条线创造了大瓶颈

outImage[(np.abs(x-ix-.5)/FF < .5) * (np.abs(y-iy-.5)/FF < .5)] = image[ix, iy]

使用以下代码替换它会显着加快速度:

ixD = int(np.ceil((-FF/2 + ix + .5)*10))
ixU = int(np.ceil((FF/2 + ix + .5)*10))
iyD = int(np.ceil((-FF/2 + iy + .5)*10))
iyU = int(np.ceil((FF/2 + iy + .5)*10))
outImage[ixD:ixU, iyD:iyU] = image[ix, iy]