[英]Pixel neighbors in 2d array (image) using Python
我有一個像這樣的 numpy 數組:
x = np.array([[1,2,3],[4,5,6],[7,8,9]])
我需要創建一個函數,讓我們使用以下輸入參數將其稱為“鄰居”:
作為輸出,我想獲得具有給定距離d
的單元格i,j
的鄰居。 所以如果我跑
neighbors(im, i, j, d=1) with i = 1 and j = 1 (element value = 5)
我應該得到以下值的索引: [1,2,3,4,6,7,8,9]
。 我希望我說清楚。 有沒有像 scipy 這樣的圖書館處理這個問題?
我已經做了一些工作,但這是一個粗略的解決方案。
def pixel_neighbours(self, p):
rows, cols = self.im.shape
i, j = p[0], p[1]
rmin = i - 1 if i - 1 >= 0 else 0
rmax = i + 1 if i + 1 < rows else i
cmin = j - 1 if j - 1 >= 0 else 0
cmax = j + 1 if j + 1 < cols else j
neighbours = []
for x in xrange(rmin, rmax + 1):
for y in xrange(cmin, cmax + 1):
neighbours.append([x, y])
neighbours.remove([p[0], p[1]])
return neighbours
我該如何改進?
看看scipy.ndimage.generic_filter
。
舉個例子:
import numpy as np
import scipy.ndimage as ndimage
def test_func(values):
print(values)
return values.sum()
x = np.array([[1,2,3],[4,5,6],[7,8,9]])
footprint = np.array([[1,1,1],
[1,0,1],
[1,1,1]])
results = ndimage.generic_filter(x, test_func, footprint=footprint)
默認情況下,它將“反映”邊界處的值。 您可以使用mode
關鍵字參數來控制它。
但是,如果您想做這樣的事情,您很有可能將您的問題表示為某種卷積。 如果是這樣,將其分解為卷積步驟並使用更優化的函數(例如大部分scipy.ndimage
)會scipy.ndimage
。
編輯:啊廢話,我的答案只是寫im[id:i+d+1, jd:j+d+1].flatten()
但寫得難以理解:)
舊的滑動窗口技巧可能會在這里有所幫助:
import numpy as np
from numpy.lib.stride_tricks import as_strided
def sliding_window(arr, window_size):
""" Construct a sliding window view of the array"""
arr = np.asarray(arr)
window_size = int(window_size)
if arr.ndim != 2:
raise ValueError("need 2-D input")
if not (window_size > 0):
raise ValueError("need a positive window size")
shape = (arr.shape[0] - window_size + 1,
arr.shape[1] - window_size + 1,
window_size, window_size)
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)
return as_strided(arr, shape=shape, strides=strides)
def cell_neighbors(arr, i, j, d):
"""Return d-th neighbors of cell (i, j)"""
w = sliding_window(arr, 2*d+1)
ix = np.clip(i - d, 0, w.shape[0]-1)
jx = np.clip(j - d, 0, w.shape[1]-1)
i0 = max(0, i - d - ix)
j0 = max(0, j - d - jx)
i1 = w.shape[2] - max(0, d - i + ix)
j1 = w.shape[3] - max(0, d - j + jx)
return w[ix, jx][i0:i1,j0:j1].ravel()
x = np.arange(8*8).reshape(8, 8)
print x
for d in [1, 2]:
for p in [(0,0), (0,1), (6,6), (8,8)]:
print "-- d=%d, %r" % (d, p)
print cell_neighbors(x, p[0], p[1], d=d)
在這里沒有做任何計時,但這個版本可能具有合理的性能。
有關更多信息,請使用短語“rolling window numpy”或“sliding window numpy”搜索網絡。
我不知道有關此的任何庫函數,但是您可以使用 numpy 的強大切片功能輕松地自己編寫這樣的東西:
import numpy as np
def neighbors(im, i, j, d=1):
n = im[i-d:i+d+1, j-d:j+d+1].flatten()
# remove the element (i,j)
n = np.hstack((b[:len(b)//2],b[len(b)//2+1:] ))
return n
當然,您應該進行一些范圍檢查以避免越界訪問。
通過使用max
和min
,您可以處理上限和下限的像素:
im[max(i-1,0):min(i+2,i_end), max(j-1,0):min(j+2,j_end)].flatten()
我同意 Joe Kingtons 的回應,只是增加了足跡
import numpy as np
from scipy.ndimage import generate_binary_structure
from scipy.ndimage import iterate_structure
foot = np.array(generate_binary_structure(2, 1),dtype=int)
或更大/不同的足跡,例如。
np.array(iterate_structure(foot , 2),dtype=int)
我們首先使用 numpy 初始化我們的興趣矩陣
import numpy as np
x = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(x)
[[1 2 3]
[4 5 6]
[7 8 9]]
我們的鄰居是距離的函數,例如我們可能對距離為 2 的鄰居感興趣,這告訴我們應該如何填充矩陣 x。 我們選擇用零填充,但您可以填充任何您喜歡的可能是平均值、模式、行/列的中位數
d = 2
x_padded = np.pad(x,d,mode='constant')
print(x_padded)
[[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]
[0 0 1 2 3 0 0]
[0 0 4 5 6 0 0]
[0 0 7 8 9 0 0]
[0 0 0 0 0 0 0]
[0 0 0 0 0 0 0]]
我們使用x_padded
矩陣來獲取矩陣x
中任何值的鄰居。 設(i,j)
和(s,t)
分別是x
和x_padded
索引。 現在我們需要將(i,j)
為(s,t)
以獲得(i,j)
鄰居
i,j = 2,1
s,t = 2*d+i+1, 2*d+j+1
window = x_padded[i:s, j:t]
print(window)
[[0 1 2 3 0]
[0 4 5 6 0]
[0 7 8 9 0]
[0 0 0 0 0]
[0 0 0 0 0]]
請注意!!! 索引(i,j)
指向您希望在矩陣x
獲得其鄰居的任何值
人們可能希望迭代矩陣x
每個點,獲取其鄰居並使用鄰居進行計算,例如在圖像處理中,使用內核進行卷積。 人們可能會執行以下操作來獲取圖像x
中每個像素的鄰居
for i in range(x.shape[0]):
for j in range(x.shape[1]):
i,j = 2,1
s,t = 2*d+i+1, 2*d+j+1
window = x_padded[i:s, j:t]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.