簡體   English   中英

包含 2D NumPy 數組中每個值的鄰居的 3D NumPy 數組?

[英]3D NumPy array which contains the neighbors of every value in a 2D NumPy array?

我想構建一個形狀(HEIGHT, WIDTH, 3)的 NumPy 數組,其中HEIGHTWIDTH對應於存儲在標准 NumPy 數組中的圖像的形狀,其中每個(i, j)位置都有中間鄰居(在一個某個方向)那個位置。 例如,如果A = [[0, 1, 2, 3, 4],[5, 6, 7, 8, 9]]並且我希望(1, 2)的鄰居位於北方,我會得到結果[1, 2, 3] 所以,我的結果矩陣在其各自的(1, 2)處應該有[1, 2, 3] = A[1:4]

現在,我嘗試了一種簡單的方法,我不使用這樣的矩陣,而是遍歷數組中的所有值並相應地對其進行切片以獲得所需的鄰居。 盡管如此,如果我可以事先計算該矩陣,那么我之后使用的算法可以被向量化(我沒有將這部分包含在問題中,因為它與我的問題無關),這幾乎總是更快,但會消耗更多內存.

    scales = 3
    padded_img = np.pad(img, scales, mode='constant')
    feature_vectors = np.zeros((img.shape[0]*img.shape[1], 4*scales))
    z = 0
    for i in range(scales, padded_img.shape[0] - scales):
        for j in range(scales, padded_img.shape[1] - scales):
            for scale in range(1, scales + 1):
                N = padded_img[i - scale, j - scale: j + scale + 1]
                E = padded_img[i - scale: i + scale + 1, j + scale]
                S = padded_img[i + scale, j - scale: j + scale + 1]
                W = padded_img[i - scale: i + scale + 1, j - scale]

                neighbors = np.vstack((N, E, S, W))
                avgs = np.mean(neighbors, axis=1)
                           
                feature_vectors[z, 4*(scale-1):4*scale] = avgs.flatten()
            z += 1

img是我原來的 NumPy 數組; 我墊它以避免在角落出現問題。 另一方面,我使用scales是因為我基本上不僅需要中間鄰居,還需要那些距離 1 到某個位置的scales 因為我也對所有可能的方向感興趣,所以我使用N, E, S, W作為我在循環內的鄰居向量。 最重要的是,這個想法是為了減少這個算法的時間復雜度。 有任何想法嗎? 謝謝你。

編輯:每次迭代獲得這 4 個向量后,我計算它們的平均值,將它們展平並將它們附加到一個特征向量,其行包含所有 4 個尺度上所有方向的信息。

您的代碼不運行(有問題pad填充的RGB尺寸和形狀avgs不允許分配到feature_vectors ),因此,如果這正是你想要什么,我說不出來,但是這應該讓你開始:

import numpy as np
from scipy.ndimage import convolve

scales = 3

img = np.random.rand(256, 256, 3)

feature_vectors = np.zeros((scales, 4) + img.shape[:-1])

for n in range(scales):
    dim = 2 * n + 3
    orig = np.zeros((dim, dim, 3), dtype = float)
    orig[:, 0, :] = 1 / (dim * 3)
    kernel = np.array([np.rot90(orig, i, (0, 1)) for i in range(4)])
    feature_vectors[n] = convolve( img[None, ...], 
                                   kernel,
                                   mode = 'constant')[..., 1]
    
feature_vectors = feature_vectors.transpose(2, 3, 1, 0).reshape(-1, scales * 4)

feature_vectors.shape
Out[]: (65536, 12)

我在這里發布此信息,以便可能遇到此問題的人可以全面了解。 我遇到過,當我創建一個Python實現多尺度的提取中的結構特征,使用像素統計由G. Impoco,L. Tuminello,N富卡,M.卡卡莫和奶酪顯微照片分段功能解釋這個問題G. 利西特拉。 您可以在ScienceDirect 中查看。

我首先創建了一個簡單的方法,由一個不太優雅的三重 for 循環組成,如下所示(發布在我的原始問題中):

import numpy as np

padded_img = np.pad(img, scales, mode="constant")
for i in range(scales, padded_img.shape[0] - scales):
    for j in range(scales, padded_img.shape[1] - scales):
        for scale in range(1, scales + 1):
            N = padded_img[i - scale, j - scale : j + scale + 1]
            E = padded_img[i - scale : i + scale + 1, j + scale]
            S = padded_img[i + scale, j - scale : j + scale + 1]
            W = padded_img[i - scale : i + scale + 1, j - scale]

這種方法通過使用將在預定義的窗口半徑上迭代的可變scale來獲得所需的鄰域信息。 這個變量允許我訪問(i, j)的相鄰像素。 盡管如此,正如@Daniel F 指出的那樣,這可以像這樣進行卷積和簡化:

import scipy.ndimage

directions = 4
for scale in range(1, scales + 1):
    filter_size = 2 * (scale - 1) + 3
    orig = np.zeros((filter_size, filter_size), dtype=np.float64)
    orig[:, 0] = 1 / filter_size
    for c in range(directions):
        # c = 0 -> North; c = 1 -> East; c = 2 -> South; c = 3 -> West
        correlation_filter = np.rot90(orig, 3 - c, (0, 1))
        convolution_filter = np.flip(correlation_filter)

        directions_img = scipy.ndimage.convolve(img, convolution_filter, cval=0.0, mode="constant")

因此,不是迭代每個像素並多次計算我想要的東西,而是迭代所需的directions (我天真的方法中的NEWS )並計算每個像素所需的一切,而無需實際上迭代它們中的每一個。

自然地,性能上的差異是令人興奮的。 我用timeit模塊測試了兩個版本( mean ± std. dev. of 7 runs, 1 loop each ),並獲得了以下基准測試,圖像的形狀為(630, 630)scales=1

Naïve approach: 46.4 ± 1.65 s per loop 
Convolution approach: 204 ± 11.7 ms per loop

scales=1不同圖像尺寸的比較

naive 方法和卷積方法的比較

scales=3不同圖像尺寸的卷積方法

卷積方法基准

代碼

你可以在這個 GitHub gist 中查看我的兩個版本的代碼。 請記住,此代碼是專門為灰度圖像編寫的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM