I need to plot a Voronoi tessellation on top of an existing image using scipy.spatial.Voronoi. I have imported an image as a numpy array using matplotlib.pyplot:
img_file = 'my_image.png'
img = plt.imread(os.path.join(data_dir, img_file))
fig = plt.figure()
ax = fig.add_subplot(111)
When I display the image it works ok:
ax.imshow(img)
my initial image
Then I want to add a Voronoi graph (for some points I choose arbitrarily) on it so I do:
points = np.array([[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]])
vor = Voronoi(points)
voronoi_plot_2d(vor, ax=ax)
plt.show()
and I get this:
Failed attempt to overlay the graph on the image
And when I plot just the graph this is what I get:
Voronoi tessellation separately
So, I wanted to draw them on top of each other by using the same axis (ax) but this ended up coloring in the regions of Voronoi instead. Any help with figuring out how to have the image on the background and the Voronoi on top would be much appreciated!
It actually works, i guess the voronoi points need to be chosen properly:
import matplotlib.pylab as plt
import numpy as np
from scipy.spatial import Voronoi, voronoi_plot_2d
import scipy.ndimage as ndimage
img_file = 'bear.png'
img = plt.imread(img_file)
points = []
for i in range(100):
points.append([np.random.uniform(0, img.shape[0]),np.random.uniform(0, img.shape[1])])
points = np.array(points)
vor = Voronoi(points)
fig = plt.figure(figsize=(20,20))
ax = fig.add_subplot(111)
ax.imshow(ndimage.rotate(img, 90))
voronoi_plot_2d(vor, point_size=10, ax=ax)
plt.show()
Related
I have been trying to make a Rubix Cube in python using Matplotlib. I've struggled to get each face of the cube to have its own colour? How do I do this in Matplotlib?
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
axes = [3, 3, 3]
data = np.ones(axes)
alpha = 0.9
colours = np.empty(axes + [4])
colours[0] = [1, 0, 0, alpha] # red
colours[1] = [0, 0, 1, alpha] # blue
colours[2] = [1, 1, 0, alpha] # yellow
figure = plt.figure()
ax = figure.add_subplot(111, projection = '3d')
ax.voxels(data, facecolors = colours, edgecolors = 'grey')
plt.show()
I am converting polylines to images and the cv2.polylines function seems as a good place to start. Minimal example:
import cv2
import matplotlib.pyplot as plt
import numpy as np
image = np.zeros((16, 16, 3), dtype=np.uint8)
pts = np.array([[2, 2], [14, 13]], np.int32)
color = 255
image = cv2.polylines(image, [pts], False, color, 1)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.imshow(image, origin="lower")
plt.show()
Produce the following image:
What I am asking is if there is a way to encode the z coordinate of a polyline as the color of the image, i.e
pts = np.array([[2, 2, 10], [14, 13, 230]], np.int32)
Would then instead produce the image:
Does anyone know a way to do it with cv2 or in any other way without having to write the entire conversion from polyline to an image?
Jakob
I would like to draw a parallelepiped in Python using matplotlib centred in (0,0,0), with the top face of a different color (or each face of a different parametrized color), and with these dimensions:
L = 1
l = 0.7
s = 0.4
This is the code I developed to draw a cube with the same face color.
import matplotlib.pyplot as plt
import numpy as np
# Create axis
axes = [5, 5, 5]
# Create Data
data = np.ones(axes, dtype = np.bool)
# Control Tranperency
alpha = 0.9
# Control colour
colors = np.empty(axes + [4], dtype = np.float32)
colors[:] = [1, 0, 0, alpha] # red
# Plot figure
fig2 = plt.figure()
ax = fig2.add_subplot(111, projection='3d')
ax.voxels(data, facecolors=colors)
Any suggestion to modify it? Considering that I would like to rotate it with a rotation matrix/quaternion operator in a second time, it would be useful to define the coordinates of the vertices or of some ley points of the parallelepiped.
thank you all!
I was looking for a way to build cubes of the same size, then draw a line through this space and output the result in the form of coordinates of cubes that this line intersects and paint these cubes with a different color. The line can be either straight or curved.
I used matplotlib to plot cubes and lines. From these sources:
https://www.geeksforgeeks.org/how-to-draw-3d-cube-using-matplotlib-in-python/
Representing voxels with matplotlib
Example code:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
axes = [5, 5, 5]
# Create Data
data = np.ones(axes, dtype=np.bool)
# Controll Tranperency
alpha = 0.3
# Control colour
colors = np.empty(axes + [4], dtype=np.float32)
colors[0] = [1, 0, 0, alpha] # red
colors[1] = [0, 1, 0, alpha] # green
colors[2] = [0, 0, 1, alpha] # blue
colors[3] = [1, 1, 0, alpha] # yellow
colors[4] = [1, 1, 1, alpha] # grey
# Plot figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x1 = [1, 4]
y1 = [0, 5]
z1 = [0, 5]
ax.plot3D(x1, y1, z1, 'black', linewidth = 5)
# Voxels is used to customizations of
# the sizes, positions and colors.
ax.voxels(data, facecolors=colors, edgecolors='grey')
result
In short: I need to plot a grid of cubes and draw a line through it. After determine which cubes this line intersects.
Is it possible to do this in Matplotlib or do I need to use another library to solve my question?
God, why do I put myself though this.
Anyways, here is an iterative solution because I do not feel like doing linear algebra. I tried and I failed.
# Here be dragons
def linelamb(x,y,z):
return lambda s: [int(i) for i in [x[0]+s*(x[1]-x[0]), y[0]+s*(y[1]-y[0]), z[0]+s*(z[1]-z[0])]]
line = linelamb(x1,y1,z1)
hitboxes = np.zeros(axes)
x,y,z = 0,0,0
for r in [i for i in np.arange(0,1,0.001)]:
xnew,ynew,znew = line(r)
if not (x == xnew and y == ynew and z == znew):
hitboxes[xnew,ynew,znew] = 1
x,y,z = xnew,ynew,znew
ax.voxels(hitboxes, facecolors=[0,0,0,0.5], edgecolors='black');
I spent some extra time to make this more adaptable but my brain stopped working. You might want to adaptively change the step size of the range but good luck.
I am trying to rotate a given figure 90 degree.
fig = plt.figure()
points = [[0.3036, 0.1960], [0.6168, 0.2977], [0.7128, 0.4169], [0.7120, 0.1960],[0.9377,0.2620],\
[0.7120,0.5680],[0.3989,0.6697],[0.3028,0.7889],[0.3036,0.5680],[0.5293,0.5020]]
bird = matplotlib.patches.Polygon(points, facecolor='blue')
fig, ax = plt.subplots()
ax.set_aspect("equal")
ax.add_patch(bird)
ax.set_xlim(0.2,1)
ax.set_ylim(0.2,0.9)
plt.show()
To rotate a matrix, you basically multiply your coordinates with a rotation matrix, that is given by
[[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]
theta being the angle of rotation (so in your case [[0, -1], [1, 0]]).
So you just calculate the dot product like this:
points = np.array(points)
rotation_matrix = np.array([[0, -1], [1, 0]])
new_points = points.dot(rotation_matrix)
and then you can plot your new set of coordinates. This is the results (after adding (0, 1) to the coordinates so that the bird is in the frame...