Adding patches to numpy array opened in matplotlib - python

I want to draw boxes on an image opened from an array in matplotlib. One way I have found to draw boxes is by using add_patch, but I can't find the way to use it on an image loaded from an array.
This code
arr = np.random.rand(400,400)
fig = plt.imshow(arr)
fig.add_patch(patches.Rectangle((100, 100), 100, 100, fill=False))
produces the error: AttributeError: 'AxesImage' object has no attribute 'add_patch'

You have to add your patch to the matplotlib Axes :
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
arr = np.random.rand(400,400)
fig,ax = plt.subplots(1)
ax.imshow(arr)
rect = patches.Rectangle((100, 100), 100, 100, fill=False)
ax.add_patch(rect)
plt.show()

Related

plotting a grid of png with matplotlib

I have found multiple similar questions with this subject but so far I couldn't adapt any solution to my needs, so I'm sorry for reposting.
I'm trying to plot a grid of png images using matplotlib, the closest I've got to what I want is using the code below, which can be found here https://matplotlib.org/stable/gallery/axes_grid1/simple_axesgrid.html .
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import ImageGrid
import numpy as np
im1 = np.arange(100).reshape((10, 10))
im2 = im1.T
im3 = np.flipud(im1)
im4 = np.fliplr(im2)
fig = plt.figure(figsize=(4., 4.))
grid = ImageGrid(fig, 111, # similar to subplot(111)
nrows_ncols=(2, 2), # creates 2x2 grid of axes
axes_pad=0.1, # pad between axes in inch.
)
for ax, im in zip(grid, [im1, im2, im3, im4]):
# Iterating over the grid returns the Axes.
ax.imshow(im)
plt.show()
My question is, how do I get rid of the x and y ticks/labels and also give each image a title?
Again, I'm sorry for repeating the question.
This code
import matplotlib.pyplot as plt
image = plt.imread("sample.png")
fig, axes = plt.subplots(2, 3)
for row in [0, 1]:
for column in [0, 1, 2]:
ax = axes[row, column]
ax.set_title(f"Image ({row}, {column})")
ax.axis('off')
ax.imshow(image)
plt.show()
is going to produce

matplotlib: how to draw a rectangle on image

How to draw a rectangle on an image, like this:
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
im = np.array(Image.open('dog.png'), dtype=np.uint8)
plt.imshow(im)
I don't know how to proceed.
You can add a Rectangle patch to the matplotlib Axes.
For example (using the image from the tutorial here):
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
im = Image.open('stinkbug.png')
# Create figure and axes
fig, ax = plt.subplots()
# Display the image
ax.imshow(im)
# Create a Rectangle patch
rect = patches.Rectangle((50, 100), 40, 30, linewidth=1, edgecolor='r', facecolor='none')
# Add the patch to the Axes
ax.add_patch(rect)
plt.show()
There is no need for subplots, and pyplot can display PIL images, so this can be simplified further:
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image
im = Image.open('stinkbug.png')
# Display the image
plt.imshow(im)
# Get the current reference
ax = plt.gca()
# Create a Rectangle patch
rect = Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')
# Add the patch to the Axes
ax.add_patch(rect)
Or, the short version:
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image
# Display the image
plt.imshow(Image.open('stinkbug.png'))
# Add the patch to the Axes
plt.gca().add_patch(Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none'))
You need use patches.
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig2 = plt.figure()
ax2 = fig2.add_subplot(111, aspect='equal')
ax2.add_patch(
patches.Rectangle(
(0.1, 0.1),
0.5,
0.5,
fill=False # remove background
) )
fig2.savefig('rect2.png', dpi=90, bbox_inches='tight')
From my understanding matplotlib is a plotting library.
If you want to change the image data (e.g. draw a rectangle on an image), you could use PIL's ImageDraw, OpenCV, or something similar.
Here is PIL's ImageDraw method to draw a rectangle.
Here is one of OpenCV's methods for drawing a rectangle.
Your question asked about Matplotlib, but probably should have just asked about drawing a rectangle on an image.
Here is another question which addresses what I think you wanted to know:
Draw a rectangle and a text in it using PIL
If you have a set of coordinates of ordered points you can also use the plot function and plot them directly without using the Rect patch. Here I recreate the example proposed by #tmdavison using that:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
im = Image.open('/content/stinkbug.png')
# Create figure and axes
fig, ax = plt.subplots()
# Display the image
ax.imshow(im)
# Coordinates of rectangle vertices
# in clockwise order
xs = [50, 90, 90, 50, 50]
ys = [100, 100, 130, 130, 100]
ax.plot(xs, ys, color="red")
plt.show()

Superimpose 2 plots in matplotlib - empty plot

I am trying to plot a circle and a rectangle on the same graph with matplotlib.
Instead, I get an empty plot. What should I do?
Here is my code:
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.axes()
circle = plt.Circle((0, 0), radius=0.75, fc='y')
plt.axis('scaled')
rectangle = plt.Rectangle((10, 10), 100, 100, fc='r')
plt.gca().add_patch(rectangle)
Your code is mostly working. The only issue is
plt.axis('scaled')
Double check your axis limits - this line only works with normal plot objects, not patches, so if you remove this line you should see the rectangle (though you also forgot to add the circle in your pasted code), as long you you update the axis limits (I used plt.axis([-1, 120, -1, 120]) below to achieve this).
A full working listing is:
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.axes()
circle = plt.Circle((0, 0), radius=0.75, fc='y')
plt.gca().add_patch(circle)
rectangle = plt.Rectangle((10, 10), 100, 100, fc='r')
plt.gca().add_patch(rectangle)
plt.axis([-1, 120, -1, 120])
Alternatively, plt.autoscale also works to set the data limits as suggested by tom.
you need to set the axes limits. You can do this with plt.autoscale(), or plt.xlim and plt.ylim. You also need to add the circle patch. Add these lines at the end of your script:
plt.gca().add_patch(circle)
plt.autoscale()

How to plot a 3D histogram of RGB image in python

I want to plot a 3D histogram of my RGB image.
Below is my code:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from scipy.misc import imread
import pylab
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
img1 = imread('image.jpg')
img_reshaped = img1.reshape(img1.shape[0] * img1.shape[1], img1.shape[2])
hist, edges = np.histogramdd(img_reshaped, bins=(100, 100, 100))
Please tell me how to plot the hist histogram that I have obtained.
Have you taken a look at the 3d histogram example from the matplotlib gallery?
see: http://matplotlib.org/examples/mplot3d/hist3d_demo.html

customized matplotlib colorbar

colors = ['white', '#FFFFBB', '#C3FDB8', '#B5EAAA', '#64E986', '#54C571',
'#4AA02C','#347C17','#347235','#25383C','#254117']
I made a plot using matplotlib (similar to a heatmap)
I would like to either :
1) make a legend using the colors I defined in the list or
2) is there anyway of automating it in matplotlib to create as beautiful as an effect in R?
the normal matplotlib color gradient is too "sharp" looking...
Thanks!
Fairly simple using ListedColormap:
import matplotlib.cm as cm # color map
import matplotlib.gridspec as gridspec
import matplotlib as mpl
import numpy as np
#dummy data
hm = np.random.randint(0, 100, size=(5, 5))
#define colors
cmap = mpl.colors.ListedColormap(['white', '#FFFFBB', '#C3FDB8', '#B5EAAA', '#64E986', '#54C571',
'#4AA02C', '#347C17', '#347235', '#25383C', '#254117'])
#create plot frames
gs = gridspec.GridSpec(2,2, height_ratios=[6,2], width_ratios=[20,1],)
ax = plt.subplot(gs[0, 0])
#heatmap and colorbar
im = ax.pcolor(hm, cmap=cmap)
cbar = plt.colorbar(im, cax=plt.subplot(gs[1]))
plt.show()

Categories