Displaying an image with matplotlib having resolution greater than screen resolution - python-3.x

I am trying to display a sentinel-1 satellite image which is of size 26000(width) X 17000(height) pixels and using Python 3.5. I am able to load this image in numpy as an array and trying to display in matplotlib but unable to do as it gives Memory Error..The screen resolution is 1600(width) X 1200(height) pixels.I am using windows 7 with 8GB RAM. I agree that it might not be able to display due to memory constraints but is there any way I can display such huge image ?
Also I have seen many satellite image processing softwares such as SNAP(sentinel toolbox) which can display such huge images in the above specified screen resolution, but cannot find how they do it.
Kindly help.

Tried to create an image with the width and height as specified by you. My screen resolution is 1920 by 1080, FHD
import matplotlib
matplotlib.rcParams['figure.dpi'] = 120
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from numpy.random import randn
fig, ax = plt.subplots()
data = np.clip(randn(26000, 17000), -1, 1)
cax = ax.imshow(data, interpolation='nearest', cmap=cm.coolwarm)
cbar = fig.colorbar(cax, ticks=[-1, 0, 1])
cbar.ax.set_yticklabels(['< -1', '0', '> 1'])
plt.show()
The plot is generated but about 7GB of memory is eaten by python!

Related

Matplotlib runs out of memory

Here is the code that I'm using to plot many plots and save them, but it is eating up all of the available RAM and causes the notebook to crash. I tried adding fig.clf(), del fig, gc.collect, and yet nothing seems to work.
I'm able to save only 38 figures around, then session gets crashed on Google Colab, since RAM gets full.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
print(np.__version__) # 1.19.5
print(mpl.__version__) # 3.2.2, also tried with latest 3.4.1
x = np.arange(0, 280, 0.1)
y = np.sin(x)
for k in range(100):
fig, ax = plt.subplots(6, 2, sharex = True)
fig.set_size_inches(37.33, 21)
for i in range(2):
for j in range(6):
ax[j][i].plot(x, y)
fig.savefig(f'figure{k}.png', dpi = 300)
plt.close(fig)
This is related to the inline backend. The memory leak can be avoided by explicitly switching to the agg backend.
cross ref: matplotlib/issues/20067
maybe if you try to save each figure after it is generated, I mean try putting fig. savefig in the for loop.
Edit: after looking for the issue on google, I found that you might need to buy Colab pro.

How to save a manipulated numpy array (annotated image) as an image, using python?

I have loaded an image, converted it to an array and annotated it (56.01). Now I want to save it back as an image.
How can I do that?
With this code, the image is annotated. But I want to remove the axes and save it as an image.
from matplotlib import image
import matplotlib.pyplot as plt
ax=plt.gca()
# load image as pixel array
data = image.imread('yellow.jpg')
ax.annotate('56.05',xy=(1000, 500), xycoords='data')
# display the array of pixels as an image
plt.imshow(data)
plt.savefig('imagenet1.png', bbox_inches='tight', dpi = 1000)
plt.show()
ANNOTATED ARRAY
I WANT THIS, BUT THE ANNOTATION IS NOT HERE
You want to annotate after calling imshow, and hide the x and y axes. Alternatively you could plot things in whatever order you want as long as you provided them with a logical zorder parameter.
from matplotlib import image
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
# load image as pixel array
data = image.imread('yellow.jpg')
# display the array of pixels as an image
ax.imshow(data)
ax.annotate('56.05', xy=(1000, 500), xycoords='data')
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
fig.savefig('imagenet1.png', bbox_inches='tight', dpi=1000)
fig.show()

How can I resize and show a cropped image with patches using matplotlib?

When I run the following code it show a clipped image, however the image showed still has the original size of the image, I want that it shows only the size of the new cropped part. How can I scale it?
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.cbook as cbook
with cbook.get_sample_data('grace_hopper.png') as image_file:
image = plt.imread(image_file)
fig, ax = plt.subplots()
im = ax.imshow(image)
patch = patches.Circle((260, 200), radius=200, transform=ax.transData)
im.set_clip_path(patch)
ax.axis('off')
plt.show()
`

3D Dicom Visualisation in Python

I am new to 3D image processing . I would like to know how to view the dicom series in python. I tried using matplotlib and VTK. In matplot I am not able to view the volume like I view in matlab using volViewer. Regarding VTK I am not able to import VTKRAyCASt for viewing 3D. The version I am using is 8.2.0.
I am doing the processing using scipy.ndimages
Kindly suggest me some resources to my volume dicom files
You can try ipyvolume https://github.com/maartenbreddels/ipyvolume for interactive plotting, I found it quite useful.
Also, you can plot them with matplotlib by using marching cubes to obtain the surface mesh but it is quite slow though:
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import numpy as np
from skimage import measure
def plot_3d(image, threshold=-300):
p = image.transpose(2,1,0)
verts, faces, normals, values = measure.marching_cubes_lewiner(p, threshold)
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111, projection='3d')
mesh = Poly3DCollection(verts[faces], alpha=0.1)
face_color = [0.5, 0.5, 1]
mesh.set_facecolor(face_color)
ax.add_collection3d(mesh)
ax.set_xlim(0, p.shape[0])
ax.set_ylim(0, p.shape[1])
ax.set_zlim(0, p.shape[2])
plt.show()
The threshold of -300 HU is fine for visualizing chest CT scans but change it if you going to use MRI (check your intensity values distribution) or binary volumes (threshold =0).
There is some example of visualization:
With vtkplotter you should be able to do this easily:
from vtkplotter import *
volume = load(mydicomdir) #returns a vtkVolume object
show(volume, bg='white')
To install:
pip install vtkplotter

plt.imshow() not showing numpy matrix correctly

I'm having trouble drawing a rectangle on an image with OpenCV, and then displaying the image with matplotlib. This code in a Jupyter Notebook results in a black image being displayed, with no green rectangle:
import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image = np.zeros((720, 1280, 3))
cv2.rectangle(image, (100,100), (200,200), color=(0,255,0), thickness=2) # Green
plt.imshow(image)
I believe I can see the rectangle if I display the image with cv2.imshow(), but I don't know that OpenCV images can be displayed inline in Jupyter Notebooks like matplotlib images can.
EDIT: I think what's really going on is explained in this excerpt from the documentation:
The value for each component of MxNx3 and MxNx4 float arrays should be
in the range 0.0 to 1.0.
It can handle values between 0 and 255 if it's an integer array.
By default when you create a numpy array using np.zeros() or np.ones(), the default data type of the matrix is set to be float, or more precisely np.float64, And there seems to be some problem in matplotlib to render a matrix with float data type (As per convention the RGB values in an image are always integral, so we can't blame matplotlib for this.)
Now you have 2 options:
Create the numpy matrix with np.uint8 datatype
image = np.zeros((720, 1280, 3), dtype = np.uint8)
Convert the matrix in integral type before rendering it on plt.
image = np.astype(image, np.uint8)
Also you need to add plt.show() at the end.

Resources