Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I dissolve a pattern in a numpy array?

Excuse the strange title, I couldn't really think of a suitable wording.

Say I have an array like:

arr = [[0 1 1 1 1 1 1 1 0],
       [0 0 1 1 1 1 1 0 0],
       [0 0 0 1 1 1 0 0 0],
       [0 0 0 0 1 0 0 0 0],
       [0 0 0 0 0 0 0 0 0]]

I'm looking to "etch" away the 1s that touch 0s, which would result in:

arr = [[0 0 1 1 1 1 1 0 0],
       [0 0 0 1 1 1 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]] .

I've tried a few things with the likes of np.roll but it seems inefficient (and has edge effects). Is there a nice short way of doing this?

like image 733
Kieran Hunt Avatar asked Jan 16 '15 17:01

Kieran Hunt


People also ask

How do I remove part of a NumPy array?

To remove an element from a NumPy array: Specify the index of the element to remove. Call the numpy. delete() function on the array for the given index.

How do you break an array in Python?

To split a list into n parts in Python, use the numpy. array_split() function. The np. split() function splits the array into multiple sub-arrays.

What is array manipulation in NumPy?

Data manipulation in Python is nearly synonymous with NumPy array manipulation: even newer tools like Pandas (Chapter 3) are built around the NumPy array. This section will present several examples of using NumPy array manipulation to access data and subarrays, and to split, reshape, and join the arrays.


2 Answers

Morpholocial erosion can be used here.

Morphological erosion sets a pixel at (i, j) to the minimum over all pixels in the neighborhood centered at (i, j). source

data
Out[39]: 
array([[0, 1, 1, 1, 1, 1, 1, 1, 0],
       [0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 1, 1, 1, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0]])

structure
Out[40]: 
array([[0, 1, 0],
       [1, 1, 1],
       [0, 1, 0]])

eroded = binary_erosion(data, structure, border_value=1).astype(int)

eroded
Out[42]: 
array([[0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 1, 1, 1, 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]])
like image 179
M4rtini Avatar answered Oct 21 '22 12:10

M4rtini


Consider convolving with a cross-shaped kernel.

import numpy as np
from scipy.signal import convolve2d
kernel = np.array([[0,1,0], [1,1,1], [0,1,0]])
mask = convolve2d(arr, kernel, boundary='symm', mode='same')
arr[mask!=5] = 0

This method works correctly for all inputs:

In [143]: D = np.random.random_integers(0,1, (5,5))

In [144]: D2 = D.copy()

In [145]: mask = convolve2d(D, kernel, boundary='symm', mode='same')

In [146]: D2[mask!=5] = 0

In [147]: binary_erosion(D, kernel2, border_value=1).astype(int)
Out[147]: 
array([[0, 1, 0, 1, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]])

In [148]: D2
Out[148]: 
array([[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]])

In [149]: D
Out[149]: 
array([[1, 0, 1, 1, 1],
       [0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0],
       [0, 0, 1, 1, 0],
       [1, 0, 1, 0, 0]])
In [150]: kernel
Out[150]: 
array([[0, 1, 0],
       [1, 1, 1],
       [0, 1, 0]])

In [151]: kernel2
Out[151]: 
array([[0, 1, 0],
       [1, 0, 1],
       [0, 1, 0]])

Look into the corners to see the differences.

like image 37
Oliver W. Avatar answered Oct 21 '22 13:10

Oliver W.