How to save multiple images generated using matplotlib & imshow in a folder - python

I'm working with matplotlib, specifically its imshow() operation. I have a multi-dimension array generated by random.rand function from NumPy.
data_array = np.random.rand(63, 4, 4, 3)
Now I want to generate images using the imshow() function from matplotlib using every 63 entries of this data array, and even this code below has generated the desired image I wanted.
plt.imshow(data_array[0]) #image constructed for the 1st element of the array
Now I wanted to save all the images produced using the imshow() from the array's entries and save those in a specific folder on my computer with a specific name. I tried with this code below.
def create_image(array):
return plt.imshow(array, interpolation='nearest', cmap='viridis')
count = 0
for i in data_array:
count += 63
image_machine = create_image(i)
image_machine.savefig('C:\Users\Asus\Save Images\close_'+str(count)+".png")
Using this code, I want to save each image produced using each entry of data_array using the imshow() function and save it to the specific folder 'C:\Users\Asus\Save Images' with a particular name encoding like 1st image will be saved as close_0.png
Please help me in this saving step, I'm stuck here.

You can do the following:
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
output_folder = "path/to/folder/"
data_array = np.random.rand(63, 4, 4, 3)
for index, array in enumerate(data_array):
fig = plt.figure()
plt.imshow(array, interpolation="nearest", cmap="viridis")
fig.savefig(Path(output_folder, f"close_{index}.png"))
plt.close()
I have added the plt.close otherwise you will end up with a lot of images simultaneously open.

Related

itk python: use filters e.g. to extract contour from blob in image

I'm trying to work with ITK in Python (instead of openCV as I'm mostly using 3D image data) but can't get the filters working.
I'll skip the exact error messages as they depend on what I'm trying. You can reproduce them with the example below based on the ITK documentation. I create a blob using a 2D Gaussian and then try to extract its contours.
The approximate_signed_distance_map_image_filter acts as expected but the contour_extractor2_d_image_filter crashes on me in various ways no matter what I do.
Any ideas on how to solve this?
Minimal (2D) example
import itk
import matplotlib.pyplot as plt
import numpy as np
fig, axs = plt.subplots(1,3)
print('creating blob from 2d gaussian histogram')
arr = np.random.multivariate_normal([0,0], [[1,0],[0,1]], 100000)
h = np.histogram2d(arr[:,0],arr[:,1], bins=[30,30])
axs[0].set_title('Blob')
axs[0].imshow(h[0], cmap='gray')
print('applying itk approximate_signed_distance_map_image_filter')
arr_image = itk.image_view_from_array(h[0])
asdm = itk.approximate_signed_distance_map_image_filter(arr_image, inside_value=1000, outside_value=0)
asdm_arr = itk.array_from_image(asdm)
axs[1].set_title('signed distance')
axs[1].imshow(asdm_arr)
print('applying itk contour_extractor2_d_image_filter')
ce2d = itk.contour_extractor2_d_image_filter(itk.output(asdm), contour_value=1000)
ce2d_arr = itk.array_from_image(ce2d)
# also not working
# ce2d = itk.ContourExtractor2DImageFilter.New()
# ce2d.SetInput(asdm);
# ce2d.SetContourValue(0);
# ce2d.Update()
# ce2d_arr = itk.array_from_image(ce2d.GetOutput())
axs[2].set_title('contour')
axs[2].imshow(ce2d_arr)
plt.show()

Changing the lognorm() base from base10 to base2 and saving the image

I have a script that plots out a heat map using matplotlib. Range of X-axis value = (-180 to +180) and Y-axis value =(0 to 180). The 2D heatmap colours areas in Rainbow according to the number of points occurring in a specified area in the x-y graph (defined by the 'bins' - see code below). In this case, x = values_Rot and y = values_Tilt (see below for code).
As of now, this script colours the 2D-heatmap on a log_base10 scale. However, the range of my data is small and I am thinking of changing the base from 10 to base 2.
Is there a way to colour the heatmap by changing the base from 10 to 2 in this code?
Also, I find that the image which has popped up after running this script clearly shows the heatmap. However, when I see the PNG image that has been saved, I see it is a blank image (pure white image) with nothing on it. Is there a way to save the figure - am I missing something while importing?
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
values_Rot = []
values_Tilt = []
values_Psi = []
for line in data:
try:
values_Rot.append(float(line.split()[rot_number]))
values_Tilt.append(float(line.split()[tilt_number]))
values_Psi.append(float(line.split()[psi_number]))
except:
print ('This line didnt work, it may just be a blank space. The line is:' + line)
# Change the values here if you want to plot something else, such as psi.
# You can also change how the data is binned here.
plt.hist2d(values_Rot, values_Tilt, norm=mpl.colors.LogNorm(), bins=100,)
plt.set_cmap('jet')
plt.colorbar()
plt.show()
plt.savefig('name_of_output.png')

Get matrix image of numpy array values - Grid with pixel values inside (not colors)

I searched online and couldn't find anything about this that does what I want.
I would like to save a numpy array as an image but instead of having a colorful image, I want a black and white representation of the pixel values in their corresponding grid location.
For example:
import numpy as np
x = np.array([[1,2],[3,4]])
print(x)
# [[1 2]
# [3 4]]
I would like to save this as an image (.PNG) that looks like the following:
My current code creates a grid and places the numbers inside but it is very difficult to adjust everything to make it presentable in a research paper.
So rather than posting my overly complex code, I was wondering if there is a built in function to handle this in a few lines of code.
I would use LaTeX to generate the tables, since they look fancy and you can either generate an image or directly put them in your document. I used the following code to achieve this:
#!/usr/bin/env
import numpy as np
import os
x = np.array([[1,2],[3,4]])
def generateLatexTable(x):
start = [r'\documentclass[preview]{standalone}', r'\begin{document}', r'\begin{tabular}{%s}' % ('{1}{0}{1}'.format('|'.join(['r'] * x.shape[1]), '|')), r'\hline']
tab = [' & '.join(['%d' % val for val in row]) + r' \\ \hline' for row in x]
end = [r'\end{tabular}', r'\end{document}']
text = '\n'.join(start + tab + end)
return text
with open('table.tex', 'w') as f:
f.write(generateLatexTable(x))
os.system("pdflatex table.tex")
Here, the document class preview is used which returns an image resized to the content of the document, i.e. just the table. Only a tabular environment is used to present the data. There are horizontal and vertical bars between the cells, but it is very easy to change this. In the variable tab the data is processed for each row and converted into a string. Note that you have to specify the output format at this position. I set it to %d so everything is converted to integers.
If you want to use the table directly in a latex source, you have to remove documentclass and \begin{document} as well as \end{document} in the variables of start and end. Finally, everything is put together in a latex-source which is then stored to disk as table.tex. If you just want the image in the end, the resulting file is compiled to table.pdf.
Here is what the output looks like. But like I said, it is very easy to change the looks since it is LaTeX :)
Here is another example with a large matrix (14 x 14), filled with random numbers ranging from 0 to 100:
You can use the table function of matplot to plot the simple table. Furthermore, you can save the plot as PNG.
Below is the simple code for your requirements:
import numpy as np
import matplotlib.pyplot as plt
x = np.array([[1,2],[3,4]])
plt.figure()
plt.table(cellText=x,cellLoc='center',loc='center')
plt.axis('off')
plt.savefig('table.png')
Size of the plot or image can be adjusted by changing figsize parameters in the line : plt.figure(figsize=(x,y))
For better appearance, it can be modified as below:
import numpy as np
import matplotlib.pyplot as plt
x = np.array([[1,2],[3,4]])
fig = plt.figure(figsize=(2,2))
plt.axis('off')
plt.axis('tight')
plt.table(cellText=x,cellLoc='center',loc='center')
#plt.subplots_adjust(hspace=0.5)
fig.tight_layout()
plt.savefig('table.png')
May be this will help:
from matplotlib import pyplot as plt
import numpy as np
w = 10
h = 10
img = np.random.randint(255, size=(w, h))
plt.figure(figsize=(5,8))
plt.imshow(img, interpolation='nearest')
plt.axis('off')
cellTextimg = []
for j in range(0,h):
cellTextimg.append(img[j,:])
the_table = plt.table(cellText= cellTextimg, loc='bottom')

How to concatenate three or more images vertically?

I try to concatenate three images vertically and I need some assistance with the code/function. So far I imported one image and cropped 3 smaller images with the same size. Now I want to concatenate them in one image that will be long, but narrow. However, I can't find an appropriate function or even if I find one I get an error message when I apply it to my code.
I already tried to make a collection from my three pictures and then use the function skimage.io.concatenate_images(sf_collection), but this results in a 4-dimensional picture that cannot be visualized.
sf_collection = (img1,img2,img3)
concat_page = skimage.io.concatenate_images(sf_collection)
My expected output is the three images to be concatenated vertically in one image (very long and narrow).
Ive never used skimage.io.concatenate, but I think you are looking for np.concatenate. It defaults to axis=0, but you can specify axis=1 for a horizontal stack. This also assumes you have already loaded the images into their array from.
from scipy.misc import face
import numpy as np
import matplotlib.pyplot as plt
face1 = face()
face2 = face()
face3 = face()
merge = np.concatenate((face1,face2,face3))
plt.gray()
plt.imshow(merge)
which returns:
If you look at the skimage.io.concatenate_images docs, it's using np.concatenate too. It seems like that function provides a data structure to hold collections of images, but not merge into a single image.
Like this:
import numpy as np
h, w = 100, 400
yellow = np.zeros((h,w,3),dtype=np.uint8) + np.array([255,255,0],dtype=np.uint8)
red = np.zeros((h,w,3),dtype=np.uint8) + np.array([255,0,0],dtype=np.uint8)
blue = np.zeros((h,w,3),dtype=np.uint8) + np.array([0,0,255],dtype=np.uint8)
# Stack vertically
result = np.vstack((yellow,red,blue))
Use the following to stack side-by-side (horizontally):
result = np.hstack((yellow,red,blue))

Image of Mnist data Python - Error when displaying the image

I'm working with the Mnist data set, in order to learn about Machine learning, and as for now I'm trying to display the first digit in the Mnist data set as an image, and I have encountered a problem.
I have a matrix with the dimensions 784x10000, where each column is a digit in the data set. I have created the matrix myself, because the Mnist data set came in the form of a text file, which in itself caused me quite a lot of problems, but that's a question for itself.
The MN_train matrix below, is my large 784x10000 matrix. So what I'm trying to do below, is to fill up a 28x28 matrix, in order to display my image.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
grey = np.zeros(shape=(28,28))
k = 0
for l in range(28):
for p in range(28):
grey[p,l]=MN_train[k,0]
k = k + 1
print grey
plt.show(grey)
But when I try to display the image, I get the following error:
The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Followed by a image plot that does not look like the number five, as I would expect.
Is there something I have overlooked, or does this tell me that my manipulation of the text file, in order to construct the MN_train matrix, has resulted in an error?
The error you get is because you supply the array to show. show accepts only a single boolean argument hold=True or False.
In order to create an image plot, you need to use imshow.
plt.imshow(grey)
plt.show() # <- no argument here
Also note that the loop is rather inefficient. You may just reshape the input column array.
The complete code would then look like
import numpy as np
import matplotlib.pyplot as plt
MN_train = np.loadtxt( ... )
grey = MN_train[:,0].reshape((28,28))
plt.imshow(grey)
plt.show()

Categories