Extract indices of a NumPy array

2020-04-18 07:53发布

I have a NumPy array consisting of only the 0 and 1 elements as follows:

import numpy as np
data = np.array([[1, 1 , 0 , 0 , 0 , 0 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [0, 0 , 1 , 1 , **1** , 1 , 1 , 0],
                 [0, 0 , 1 , 1 , 1 , 1 , 1 , 1],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [1, 1 , 0 , 0 , 0 , 0 , 0 , 0]])

I have to find out the indices of the element 1 which is surrounded by 1 in 2 by 2 pixels in every directions.

The location of the expected answer is shown in bold.

I am looking for easier and faster way of doing it.

2条回答
迷人小祖宗
2楼-- · 2020-04-18 08:19

You could use some signal processing -

import numpy as np
from scipy import signal

# Input
data = np.array([[1, 1 , 0 , 0 , 0 , 0 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [0, 0 , 1 , 1 , 1 , 1 , 1 , 0],
                 [0, 0 , 1 , 1 , 1 , 1 , 1 , 1],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [1, 1 , 0 , 0 , 0 , 0 , 0 , 0]])

# Extent of the search           
extent = 2;

# Kernel to be used with 2D convolution                 
kernel = np.ones((2*extent+1,2*extent+1))

# Perform 2D convolution with input data and kernel 
filt_out = signal.convolve2d(data, kernel, boundary='symm', mode='same')

# Find where the convolution resulted in a perfect score, 
# i.e is equal to the number of elements in kernel
R,C = np.where( filt_out == kernel.size )

Output -

In [66]: print(R,C)
[3] [4]

Listed in this section is an alternative approach with ndimage to perform the same convolution as with the previous approach, keeping rest of the steps same. Here's the code to get the convolution output filt_out -

import scipy.ndimage
filt_out = scipy.ndimage.convolve(data,kernel)
查看更多
对你真心纯属浪费
3楼-- · 2020-04-18 08:26

This is easy with a basic morphological operation:

import numpy as np
from scipy.ndimage.morphology import binary_erosion


data = np.array([[1, 1 , 0 , 0 , 0 , 0 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [0, 0 , 1 , 1 , 1 , 1 , 1 , 0],
                 [0, 0 , 1 , 1 , 1 , 1 , 1 , 1],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [1, 1 , 0 , 0 , 0 , 0 , 0 , 0]])

expected = np.array([[0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
                     [0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
                     [0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
                     [0, 0 , 0 , 0 , 1 , 0 , 0 , 0],
                     [0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
                     [0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
                     [0, 0 , 0 , 0 , 0 , 0 , 0 , 0]])

# otherwise known as np.ones((5, 5))
structuring_element = np.array([[1, 1, 1, 1, 1],
                                [1, 1, 1, 1, 1],
                                [1, 1, 1, 1, 1],
                                [1, 1, 1, 1, 1],
                                [1, 1, 1, 1, 1]])

# will be of dtype np.bool but you can convert with .astype(np.int)
# if you really need
result = binary_erosion(data, structuring_element)

print(result)

print(np.allclose(result, expected))
查看更多
登录 后发表回答