Cluster non-zero values in a 2D NumPy array - python

I want to cluster non-zero locations in a NumPy 2D array for MSER detection. Then I want to find the number of points in each cluster and remove those clusters which do not have number of points between some x and y (10 and 300).
I have tried clustering them by searching with neighbouring points but the method fails for concave-shaped non-zero clusters.
[[0, 1, 0, 0, 1],
[0, 1, 1, 1, 1],
[0, 0, 0, 0, 0],
[1, 1, 0, 1, 1],
[1, 0, 0, 1, 1]]
should output, for x=4 and y=5 (both included)
[[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 1, 1],
[0, 0, 0, 1, 1]]

I'm not sure I have understood your question correctly, but I think scikit-image's label and regionprops could get the job done.
In [6]: import numpy as np
In [7]: from skimage import measure, regionprops
In [8]: img = np.array([[0, 7, 0, 0, 7],
...: [0, 9, 1, 1, 4],
...: [0, 0, 0, 0, 0],
...: [2, 1, 0, 2, 1],
...: [1, 0, 0, 6, 4]])
...:
In [9]: arr = measure.label(img > 0)
In [10]: arr
Out[10]:
array([[0, 1, 0, 0, 1],
[0, 1, 1, 1, 1],
[0, 0, 0, 0, 0],
[2, 2, 0, 3, 3],
[2, 0, 0, 3, 3]])
In [11]: print('Label\t# pixels')
...: for region in measure.regionprops(arr):
...: print(f"{region['label']}\t{region['area']}")
...:
Label # pixels
1 6
2 3
3 4

Related

Selecting rows in 2-D numpy array based on subset of column values

Suppose I have the following numpy array:
a = np.array([[1, 1, 0, 0, 1],
[1, 1, 0, 0, 0],
[1, 0, 0, 1, 1],
[1, 1, 0, 0, 0],
[1, 1, 0, 0, 0],
[1, 1, 0, 0, 0],
[0, 0, 0, 1, 0],
[1, 1, 0, 0, 0],
[1, 1, 0, 0, 0],
[1, 1, 1, 0, 1],
[1, 1, 0, 0, 0],
[1, 1, 0, 0, 1],
[1, 1, 0, 0, 0],
[1, 0, 0, 1, 0],
[1, 0, 1, 1, 0]])
I want to select only the rows, where column with index 1 have value 1 and column with index 2 have value 0.
i tried the following:
evidence = {1:1,2:0}
mask = a[:,list(evidence.keys())] == list(evidence.values())
But after that i am stuck.
how can I do it in numpy 2-D array?
Try:
out = a[(a[:, 1] == 1) & (a[:, 2] == 0)]
Given a dictionary of column, value pairs, you could use:
evidence = {1:1,2:0}
out = a[ np.logical_and.reduce([a[:, c] == v for c, v in evidence.items()]) ]
which generalizes the above solution to a sequence of &.

Extracting zones of ones in a binary numpy array

I'm looking for a way to extract zones of ones in a binary numpy array to put different values, for instance, for the following array:
x=[[0,1,1,0,0,0],
[0,1,1,0,0,0],
[0,1,0,0,0,0],
[0,0,0,1,1,0],
[0,0,1,1,1,0],
[0,0,0,0,0,0]]
Expected result:
x=[[0,2,2,0,0,0],
[0,2,2,0,0,0],
[0,2,0,0,0,0],
[0,0,0,3,3,0],
[0,0,3,3,3,0],
[0,0,0,0,0,0]]
Use scipy.ndimage.label:
x=[[0,1,1,0,0,0],
[0,1,1,0,0,0],
[0,1,0,0,0,0],
[0,0,0,1,1,0],
[0,0,1,1,1,0],
[0,0,0,0,0,0]]
a = np.array(x)
from scipy.ndimage import label
b = label(a)[0]
output:
# b
array([[0, 1, 1, 0, 0, 0],
[0, 1, 1, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 0, 2, 2, 0],
[0, 0, 2, 2, 2, 0],
[0, 0, 0, 0, 0, 0]], dtype=int32)
to start labeling from 2:
b = (label(a)[0]+1)*a
output:
array([[0, 2, 2, 0, 0, 0],
[0, 2, 2, 0, 0, 0],
[0, 2, 0, 0, 0, 0],
[0, 0, 0, 3, 3, 0],
[0, 0, 3, 3, 3, 0],
[0, 0, 0, 0, 0, 0]])

How to find the indices of a certain value that exists in the same location in two matrices?

In what I am working on, I have two numpy matrices, both the same size, filled with 0's and 1's for simplicity (but let's say it could be filled with any numbers). What I would like to know is a way to extract, from these two matrices, the position of the 1's that exist in the same position in both matrices.
For example, if I have the following two matrices and value
a = np.array([[0, 0, 0, 1, 0, 1],
[1, 1, 0, 1, 1, 1],
[1, 0, 1, 1, 0, 1],
[1, 0 ,1, 1, 1, 0],
[0, 0, 1, 0, 0, 0]])
b = np.array([[0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 1],
[0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 0]])
value = 1
then I would like a way to somehow get the information of all the locations where the value "1" exists in both matrices, i.e.:
result = [(0,5),(1,1),(2,3),(4,2)]
I guess the result could be thought of as an intersection, but in my case the position is important which is the reason I don't think np.intersect1d() would be much help. In the actual matrices I am working with, they are on the order of about 10,000 by 10,000, so this list would probably be a lot longer.
Thanks in advance for any help!
You could use numpy.argwhere:
import numpy as np
a = np.array([[0, 0, 0, 1, 0, 1],
[1, 1, 0, 1, 1, 1],
[1, 0, 1, 1, 0, 1],
[1, 0, 1, 1, 1, 0],
[0, 0, 1, 0, 0, 0]])
b = np.array([[0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 1],
[0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 0]])
result = np.argwhere(a & b)
print(result)
Output
[[0 5]
[1 1]
[2 3]
[2 5]
[4 2]]

Generate samples from a random matrix

Assume we have a random matrix A of size n*m. Each elements A_ij is the success probability of a Bernoulli distribution.
I want to draw a sample z from A with the following rule:
z_ij draw from Bernoulli(A_ij)
Is there any numpy function support this?
EDIT: operations such as
arr = numpy.random.random([10, 5])
f = lambda x: numpy.random.binomial(1, x)
sp = map(f, arr)
are inefficient. Is there any faster method?
You can directly give an array as one of the arguments of your binomial distribution, for example:
import numpy as np
arr = np.random.random([10, 5])
sp = np.random.binomial(1, arr)
sp
gives
array([[0, 0, 0, 0, 0],
[1, 0, 0, 1, 1],
[1, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1],
[0, 1, 0, 1, 0],
[0, 1, 1, 0, 0],
[0, 0, 0, 1, 1],
[0, 1, 0, 0, 0],
[1, 0, 0, 1, 0]])

How do I add a guard ring to a matrix in NumPy?

Using NumPy, a matrix A has n rows and m columns, and I want add a guard ring to matrix A. That guard ring is all zero.
What should I do? Use Reshape? But the element is not enough to make a n+1 m+1 matrix.
Or etc.?
Thanks in advance
I mean an extra ring of cells that always contain 0 surround matrix A.Basically there is a Matrix B has n+2rows m+2columns where the first row and columns and the last row and columns are all zero,and the rest of it are same as matrix A.
Following up on your comment:
>>> import numpy
>>> a = numpy.array(range(9)).reshape((3,3))
>>> b = numpy.zeros(tuple(s+2 for s in a.shape), a.dtype)
>>> b[tuple(slice(1,-1) for s in a.shape)] = a
>>> b
array([[0, 0, 0, 0, 0],
[0, 0, 1, 2, 0],
[0, 3, 4, 5, 0],
[0, 6, 7, 8, 0],
[0, 0, 0, 0, 0]])
This is a less general but easier to understand version of Alex's answer:
>>> a = numpy.array(range(9)).reshape((3,3))
>>> a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> b = numpy.zeros(a.shape + numpy.array(2), a.dtype)
>>> b
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]])
>>> b[1:-1,1:-1] = a
>>> b
array([[0, 0, 0, 0, 0],
[0, 0, 1, 2, 0],
[0, 3, 4, 5, 0],
[0, 6, 7, 8, 0],
[0, 0, 0, 0, 0]])
This question is ancient now, but I just want to alert people finding it that numpy has a function pad that very easily accomplishes this now.
import numpy as np
a = np.array(range(9)).reshape((3, 3))
a
Out[15]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
a = np.pad(a, pad_width=((1,1),(1,1)), mode='constant', constant_values=0)
a
Out[16]:
array([[0, 0, 0, 0, 0],
[0, 0, 1, 2, 0],
[0, 3, 4, 5, 0],
[0, 6, 7, 8, 0],
[0, 0, 0, 0, 0]])

Categories