0

我正在尝试编写一个像素插值(合并?)算法(例如,我想取四个像素并取它们的平均值并将该平均值作为新像素产生)。我在加快“分区”过程的步幅技巧方面取得了成功,但实际计算速度确实很慢。对于 256x512 16 位灰度图像,我得到平均代码以在我的机器上花费 7 秒。我必须根据数据集处理从 2k 到 20k 的图像。目的是减少图像的噪音(我知道我提出的方法会降低分辨率,但这对我的目的来说可能不是一件坏事)。

import numpy as np
from numpy.lib.stride_tricks import as_strided
from scipy.misc import imread
import matplotlib.pyplot as pl
import time

def sliding_window(arr, footprint):
    """ Construct a sliding window view of the array"""
    t0 = time.time()
    arr = np.asarray(arr)
    footprint = int(footprint)
    if arr.ndim != 2:
        raise ValueError("need 2-D input")
    if not (footprint > 0):
        raise ValueError("need a positive window size")
    shape = (arr.shape[0] - footprint + 1,
             arr.shape[1] - footprint + 1, footprint, footprint)
    if shape[0] <= 0:
        shape = (1, shape[1], arr.shape[0], shape[3])
    if shape[1] <= 0:
        shape = (shape[0], 1, shape[2], arr.shape[1])
    strides = (arr.shape[1]*arr.itemsize, arr.itemsize,
               arr.shape[1]*arr.itemsize, arr.itemsize)

    t1 = time.time()
    total = t1-t0
    print "strides"
    print total

    return as_strided(arr, shape=shape, strides=strides)




def binning(w,footprint):

    #the averaging block
    #prelocate memory
    binned = np.zeros(w.shape[0]*w.shape[1]).reshape(w.shape[0],w.shape[1])
    #print w
    t2 = time.time()
    for i in xrange(w.shape[0]):
        for j in xrange(w.shape[1]):
            binned[i,j] = w[i,j].sum()/(footprint*footprint + 0.0)

    t3 = time.time()
    tot = t3-t2
    print tot

    return binned

Output:
5.60283660889e-05
7.00565886497

是否有一些内置/优化的功能可以满足我的需求,或者我应该尝试做一个 C 扩展(甚至是其他东西)?

下面是代码的附加部分,只是为了完整起见,因为我认为函数在这里是最重要的。图像绘图很慢,但我认为有一种方法可以改进它,例如这里

for i in range(2000):
    arr = imread("./png/frame_" + str("%05d" % (i + 1) ) + ".png").astype(np.float64)
    w = sliding_window(arr,footprint)
    binned = binning(w,footprint)
    pl.imshow(binned,interpolation = "nearest")
    pl.gray()
    pl.savefig("binned_" + str(i) + ".png")
    enter code here

我正在寻找的可以称为插值。我只是使用了建议我这样做的人使用的术语。可能这就是我找到直方图相关内容的原因!

除了 median_filter 我尝试了 scipy.ndimage 中的 generic_filter 但那些并没有给我想要的结果(它们没有像卷积那样的“有效”模式,即这些依赖于在移动内核环绕时超出数组的范围)。我在代码审查中问过,似乎 stackoverflow 会更适合这个问题。

4

3 回答 3

2

在不深入研究您的代码的情况下,我认为您只是通过插值调整图像大小。您应该为此操作使用图像库,因为它将具有高度优化的代码。

由于您使用的是 SciPy,因此您可能希望从 Python 图像库 PIL 开始。使用 resize 方法,如果您可以传递所需的插值参数,可能是 Image.BILINEAR 在您的情况下。

它应该看起来像这样:

import Image
im = Image.fromarray(your_numpy)
im.resize((w/2, h/2), Image.BILINEAR)

编辑:我刚刚注意到,您甚至可以使用 scipy 本身来做到这一点,请查看文档

scipy.misc.imresize

a = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]], dtype=np.uint8)
res = scipy.misc.imresize(a, (3,2), interp="bilinear")
于 2013-07-30T15:49:06.563 回答
1

为了完整起见,scipy 博客上有一个有趣的解决方案。这个想法是将数组重塑为更高的维度,然后应用mean在一维上,然后再次重塑为更小的数组。估计也很快。

https://scipython.com/blog/binning-a-2d-array-in-numpy/

于 2021-10-05T20:10:22.060 回答
0

对于 scipy.ndimage.filters.uniform_filter 的平均查看,在 scipy.ndimage.filters 中,您有很多用于卷积的内核,它们比使用 scipy.convolve 的直接卷积要快得多。

于 2013-09-23T19:07:33.450 回答