3

I have a 2D matrix containing zeros and ones. The ones define a shape from which I want to plot its contour/edge on a matplotlib figure. The initial 2D binary matrix:

[[0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 1 1 1 1 1 0 0 0]
 [0 0 0 1 1 1 1 1 0 0 0]
 [0 0 0 1 1 1 1 1 0 0 0]
 [0 0 0 1 1 1 1 1 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0]]

I found here the method to get the corresponding 2D binary matrix of the edge of the shape:

[[0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 1 1 1 1 1 0 0 0]
 [0 0 0 1 0 0 0 1 0 0 0]
 [0 0 0 1 0 0 0 1 0 0 0]
 [0 0 0 1 1 1 1 1 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0]]

Using plt.imshow, I get the following result: enter image description here

How would you do to plot the ones in this matrix as a dotted line in a matplotlib figure using plt.plot() ? I would like to get this result: enter image description here

2 Answers 2

3

For more complex geometries than a rectangle you can use the ConvexHull from scipy.spatial:

#starting with the original data
data = [
 [0,0,0,0,0,0,0,0,0,0,0]
,[0,0,0,1,1,1,1,1,0,0,0]
,[0,0,0,1,1,1,1,1,0,0,0]
,[0,0,0,1,1,1,1,1,0,0,0]
,[0,0,0,1,1,1,1,1,0,0,0]
,[0,0,0,0,0,0,0,0,0,0,0]]

#convert the data array into x-y coordinates
#assume (0,0) is the lower left corner of the array
def array_to_coords(data):
    for y, line in enumerate(reversed(data)):
        for x, point in enumerate(line):
            if point == 1:
                yield(x, y)

points = list(array_to_coords(data))

#plot the points, skip this if you only need the dotted line
x,y = zip(*points)
plt.plot(x, y, 'o')

plt.xlim(0,10)
plt.ylim(0,5)

#plot the convex hull
from scipy.spatial import ConvexHull
hull = ConvexHull(points)
for simplex in hull.simplices:
    plt.plot(hull.points[simplex,0], hull.points[simplex,1], 'ro-')

enter image description here

A more complex situation:

data = [
 [0,0,0,0,0,1,0,0,0,0,0]
,[0,0,0,1,1,1,1,1,0,0,0]
,[0,0,0,1,1,1,1,1,0,0,0]
,[0,0,0,1,1,1,1,1,0,0,0]
,[0,0,1,1,1,1,1,0,0,0,0]
,[0,0,0,0,0,0,0,0,0,0,0]]

complexer situation

Sign up to request clarification or add additional context in comments.

Comments

1

This isn't exactly the same, but maybe it can give you a start. You can see what I did. I extracted the x,y locations of the 1 values, then plotted x against y in a scatter plot.

import matplotlib.pyplot as plt
import numpy as np
array = np.array(
[[0,0,0,0,0,0,0,0,0,0,0],
 [0,0,0,1,1,1,1,1,0,0,0],
 [0,0,0,1,0,0,0,1,0,0,0],
 [0,0,0,1,0,0,0,1,0,0,0],
 [0,0,0,1,1,1,1,1,0,0,0],
 [0,0,0,0,0,0,0,0,0,0,0]])

coords = np.argwhere(array==1)
plt.xlim(0,10)
plt.ylim(0,5)
plt.scatter(coords[:,1],coords[:,0])
plt.show()

Output: enter image description here

Followup

import matplotlib.pyplot as plt
import numpy as np
array = np.array(
[[0,0,0,0,0,0,0,0,0,0,0],
 [0,0,0,1,1,1,1,1,0,0,0],
 [0,0,0,1,0,0,0,1,0,0,0],
 [0,0,0,1,0,0,0,1,0,0,0],
 [0,0,0,1,1,1,1,1,0,0,0],
 [0,0,0,0,0,0,0,0,0,0,0]])

coords = np.argwhere(array==1)
xmin = np.min(coords[:,1])
xmax = np.max(coords[:,1])
ymin = np.min(coords[:,0])
ymax = np.max(coords[:,0])
x = [xmin,xmin,xmax,xmax,xmin]
y = [ymin,ymax,ymax,ymin,ymin]

plt.xlim(0,10)
plt.ylim(0,5)
plt.plot(x, y, '--')
plt.show()

Output: Second answer

2 Comments

Thanks for your answer. I already tried with scatter which is not what I'm looking for, that's why I clarified in my post that I want to use the plot method to get a proper line, not indépendant points !
If you know it's always going to be a rectangle, then it doesn't take much imagination to derive the corners from what I've done there. I'll modify the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.