Numpy/Scipy,遍历子数组

3

最近我一直在处理8x8像素块的图像数据。通常的做法是使用嵌套的for循环来提取这些块,例如:

for y in xrange(0,height,8):
    for x in xrange(0,width,8):
        d = image_data[y:y+8,x:x+8]
        # further processing on the 8x8-block

我不禁想知道是否有一种方法可以向量化此操作或使用numpy/scipy的其他方法代替?有没有某种迭代器?
一个最小工作示例(MWE)1
#!/usr/bin/env python

import sys
import numpy as np
from scipy.fftpack import dct, idct
import scipy.misc
import matplotlib.pyplot as plt

def dctdemo(coeffs=1):
    unzig = np.array([
         0,  1,  8, 16,  9,  2,  3, 10,
        17, 24, 32, 25, 18, 11,  4, 5,
        12, 19, 26, 33, 40, 48, 41, 34,
        27, 20, 13,  6,  7, 14, 21, 28,
        35, 42, 49, 56, 57, 50, 43, 36,
        29, 22, 15, 23, 30, 37, 44, 51,
        58, 59, 52, 45, 38, 31, 39, 46,
        53, 60, 61, 54, 47, 55, 62, 63])

    lena = scipy.misc.lena()
    width, height = lena.shape

    # reconstructed
    rec = np.zeros(lena.shape, dtype=np.int64)

    # Can this part be vectorized?
    for y in xrange(0,height,8):
        for x in xrange(0,width,8):
            d = lena[y:y+8,x:x+8].astype(np.float)
            D = dct(dct(d.T, norm='ortho').T, norm='ortho').reshape(64)
            Q = np.zeros(64, dtype=np.float)
            Q[unzig[:coeffs]] = D[unzig[:coeffs]]
            Q = Q.reshape([8,8])
            q = np.round(idct(idct(Q.T, norm='ortho').T, norm='ortho'))
            rec[y:y+8,x:x+8] = q.astype(np.int64)

    plt.imshow(rec, cmap='gray')
    plt.show()

if __name__ == '__main__':
    try:
        c = int(sys.argv[1])
    except ValueError:
        sys.exit()
    else:
        if 1 <= int(sys.argv[1]) <= 64:
            dctdemo(int(sys.argv[1]))

注释:

  1. 实际应用:https://github.com/figgis/dctdemo

1
目前正在尝试调整代码,使我建议的函数能够与您的代码配合使用... - YXD
2个回答

5

Scikit Image中有一个名为view_as_windows的函数来实现这个功能。

不幸的是,我必须在另一个时间完成这个答案,但你可以以一种形式获取窗口,以便可以将其传递给dct

from skimage.util import view_as_windows
# your code...
d = view_as_windows(lena.astype(np.float), (8, 8)).reshape(-1, 8, 8)
dct(d, axis=0)

3

在scikit-learn的特征提取程序中,有一个名为extract_patches的函数。您需要指定patch_sizeextraction_step。结果将是图像的补丁视图,可能会重叠。生成的数组是4D,前两个索引是补丁,最后两个索引是补丁的像素。尝试一下。

from sklearn.feature_extraction.image import extract_patches
patches = extract_patches(image_data, patch_size=(8, 8), extraction_step=(4, 4))

这将生成重叠一半的(8, 8)大小的补丁。
请注意,到目前为止,这使用了没有额外的内存,因为它是通过步幅技巧实现的。您可以通过重塑来强制进行复制。
patches = patches.reshape(-1, 8, 8)

基本上会生成一个补丁列表。

有没有一种方法可以保留图像边缘的部分补丁? - Joshua Farina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接