I have created an array thusly:
import numpy as np
data = np.zeros( (512,512,3), dtype=np.uint8)
data[256,256] = [255,0,0]
What I want this to do is display a single red dot in the center of a 512x512 image. (At least to begin with... I think I can figure out the rest from there)
The following should work:
from matplotlib import pyplot as plt
plt.imshow(data, interpolation='nearest')
plt.show()
If you are using Jupyter notebook/lab, use this inline command before importing matplotlib:
%matplotlib inline
A more featureful way is to install ipyml pip install ipympl and use
%matplotlib widget
see an example.
You could use PIL to create (and display) an image:
from PIL import Image
import numpy as np
w, h = 512, 512
data = np.zeros((h, w, 3), dtype=np.uint8)
data[0:256, 0:256] = [255, 0, 0] # red patch in upper left
img = Image.fromarray(data, 'RGB')
img.save('my.png')
img.show()
Note: both these APIs have been first deprecated, then removed.
Shortest path is to use scipy, like this:
# Note: deprecated in v0.19.0 and removed in v1.3.0
from scipy.misc import toimage
toimage(data).show()
This requires PIL or Pillow to be installed as well.
A similar approach also requiring PIL or Pillow but which may invoke a different viewer is:
# Note: deprecated in v1.0.0 and removed in v1.8.0
from scipy.misc import imshow
imshow(data)
How to show images stored in numpy array with example (works in Jupyter notebook)
I know there are simpler answers but this one will give you understanding of how images are actually drawn from a numpy array.
Load example
from sklearn.datasets import load_digits
digits = load_digits()
digits.images.shape #this will give you (1797, 8, 8). 1797 images, each 8 x 8 in size
Display array of one image
digits.images[0]
array([[ 0., 0., 5., 13., 9., 1., 0., 0.],
[ 0., 0., 13., 15., 10., 15., 5., 0.],
[ 0., 3., 15., 2., 0., 11., 8., 0.],
[ 0., 4., 12., 0., 0., 8., 8., 0.],
[ 0., 5., 8., 0., 0., 9., 8., 0.],
[ 0., 4., 11., 0., 1., 12., 7., 0.],
[ 0., 2., 14., 5., 10., 12., 0., 0.],
[ 0., 0., 6., 13., 10., 0., 0., 0.]])
Create empty 10 x 10 subplots for visualizing 100 images
import matplotlib.pyplot as plt
fig, axes = plt.subplots(10,10, figsize=(8,8))
Plotting 100 images
for i,ax in enumerate(axes.flat):
ax.imshow(digits.images[i])
Result:
What does axes.flat do?
It creates a numpy enumerator so you can iterate over axis in order to draw objects on them.
Example:
import numpy as np
x = np.arange(6).reshape(2,3)
x.flat
for item in (x.flat):
print (item, end=' ')
import numpy as np
from keras.preprocessing.image import array_to_img
img = np.zeros([525,525,3], np.uint8)
b=array_to_img(img)
b
Using pillow's fromarray, for example:
from PIL import Image
from numpy import *
im = array(Image.open('image.jpg'))
Image.fromarray(im).show()
Using pygame, you can open a window, get the surface as an array of pixels, and manipulate as you want from there. You'll need to copy your numpy array into the surface array, however, which will be much slower than doing actual graphics operations on the pygame surfaces themselves.
The Python Imaging Library can display images using Numpy arrays. Take a look at this page for sample code:
Convert Between Numerical Arrays and PIL Image Objects
EDIT: As the note on the bottom of that page says, you should check the latest release notes which make this much simpler:
http://effbot.org/zone/pil-changes-116.htm
Supplement for doing so with matplotlib. I found it handy doing computer vision tasks. Let's say you got data with dtype = int32
from matplotlib import pyplot as plot
import numpy as np
fig = plot.figure()
ax = fig.add_subplot(1, 1, 1)
# make sure your data is in H W C, otherwise you can change it by
# data = data.transpose((_, _, _))
data = np.zeros((512,512,3), dtype=np.int32)
data[256,256] = [255,0,0]
ax.imshow(data.astype(np.uint8))
For example your image is in an array names 'image'
All you do is
plt.imshow(image)
plt.show
This will display an array in the form of an image
Also, dont forget to import PLT
this could be a possible code solution:
from skimage import io
import numpy as np
data=np.random.randn(5,2)
io.imshow(data)
Related
I have some datasets which are too big and I want to plot these datasets with matplotlib's imshow() function.
I need to plot the datasets concatenated with matplotlib, but since the datasets are quite large, when I try to concatenate it causes my computer to overheat (I use the NumPy library to concatenate). Is it possible for me to read these datasets one by one and put them next to the previous plot, as I have given below as a gif? Since I read all datasets one by one, it will not cause heating.
Let's assume this input:
array = np.diag(np.ones(3))
arrays = [array,array*2,array*3]
[array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]]),
array([[2., 0., 0.],
[0., 2., 0.],
[0., 0., 2.]]),
array([[3., 0., 0.],
[0., 3., 0.],
[0., 0., 3.]])]
looking like:
plt.imshow(np.concatenate(arrays, axis=1))
Now we want to plot block by block. For this we loop over the blocks and use the extent option of imshow
ax = plt.subplot()
vmin = min(a.min() for a in arrays) ## if you know the values in advance you
vmax = max(a.max() for a in arrays) ## can input them instead of calculating
for i,a in enumerate(arrays):
h,w = a.shape
ax.imshow(a, vmin=vmin, vmax=vmax,
extent=[(w*i)-0.5, (w*(i+1))-0.5, h-0.5, -0.5])
ax.set_xlim(-0.5, (w*(i+1))-0.5)
You need to know in advance the min/max values of your whole dataset and specify it to imshow with the vmin/vmax parameters, otherwise each dataset will be scaled independently.
Now, if the arrays have different widths (arrays = [array,(array*2)[:, :2],array*3]), you can use the following:
ax = plt.subplot()
vmin = min(a.min() for a in arrays)
vmax = max(a.max() for a in arrays)
W = 0
for i,a in enumerate(arrays):
h,w = a.shape
ax.imshow(a, vmin=vmin, vmax=vmax,
extent=[W-0.5, (W+w)-0.5, h-0.5, -0.5])
W+=w
ax.set_xlim(-0.5, W-0.5)
To parse
s="1,2,3,4_5,6,7,8"
as [[1,2,3,4],[5,6,7,8]]
I am currently using
import numpy as np
a=np.array([list(map(int,r.split(","))) for r in s.split("_")])
Is there a more pythonic or one-shot inbuilt way of doing this or am I on the right track here?
Python newbie.
Using list-comprehensions:
s="1,2,3,4_5,6,7,8"
a = np.array([[int(x) for x in r.split(',')] for r in s.split('_')])
You can use np.genfromtxt:
from io import StringIO
import numpy as np
s="1,2,3,4_5,6,7,8"
np.genfromtxt(StringIO(s.replace("_", "\n")), delimiter=",")
array([[1., 2., 3., 4.],
[5., 6., 7., 8.]])
In Tensorflow: I have a set of arrays, x0,x1,x2 and x3 that are generated in my program and each array has N elements. I also have a zeros-initialized 3D tensor of dimensions (N,2,2).
I want to make each of the array as the element of my 3D tensor (with the N elements in the third direction), M[:,0,0] =x0, M[:,0,1] =x1, M[:,1,0] =x2 and M[:,1,1] =x3, and I want to do that with for loops.
In Matlab which I am more familiar with it is possible to do that by simply:
M(1,1,:)=x0
M(2,2,:)=x3
M(1,2,:)=x1
M(2,1,:)=x2
Is there a way that I can pass arrays in a for loop as the third dimension of my tensor in tensor flow, for example:
for i in range(2):
M[:,i,i]=x
where x is an array?
I don't think it would work that way. You could do:
import tensorflow as tf
import numpy as np
x0,x1,x2,x3 = [ np.random.randint(0,10,3) for _ in range(4)]
tf_X = tf.stack( [ tf.stack([x0,x1]),
tf.stack([x2,x3]) ])
EDIT: It might change with Tensorflow2 though. Otherwise, you could use pytorch:
import torch
import numpy as np
X = torch.ones([3,4])
v = np.arange(4)
X[0,:] = torch.from_numpy(v)
Result:
In [20]: X
Out[20]:
tensor([[0., 1., 2., 3.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
I really hope this is not a duplicate and this is probably a very stupid question. Sorry ;)
Problem:
I have a greyscale image with values/classes 1 and 2 and I want to convert/map this to a color image where 1 equals yellow and 2 equals blue.
import numpy as np
import cv2
result=cv2.imread("image.png", cv2.IMREAD_GRAYSCALE)
result[result==2]=[15,100,100]
result[result==1]=[130,255,255]
But this is failing with the error ValueError: NumPy boolean array indexing assignment cannot assign 3 input values to the 1995594 output values where the mask is true
I think I very close to the solution, but I don't get it.
Thanks in Advance for your help!
result is a Numpy array and is typed, its type being an integer and you try to assign to an integer slot a triple of integers… no good.
What you want to do is creating an empty color image, with the same dimensions of result, and assigning to the last axis the requested triples.
I have not installed cv2 but you can look at the following code to have an idea on how to proceed.
Equivalent to what you have done, the same error
In [36]: import numpy as np
In [37]: a = np.random.randint(0,2,(2,4))
In [38]: a
Out[38]:
array([[1, 0, 0, 0],
[0, 1, 0, 1]])
In [39]: a[a==1] = (1,2,3)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-39-24af4c8dbf5a> in <module>
----> 1 a[a==1] = (1,1)
ValueError: NumPy boolean array indexing assignment cannot assign 2 input values to the 3 output values where the mask is true
Now, allocate a 3D array and apply indexing to it, assigning by default to the last axis
In [40]: b = np.zeros((2,4,3))
In [41]: b[a==1] = (1,2,3)
In [42]: b
Out[42]:
array([[[1., 2., 3.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[1., 2., 3.],
[0., 0., 0.],
[1., 2., 3.]]])
We have two inner matrices (corresponding to the two rows of a), in each matrix four rows (corresponding to the four columns of a) and finally the columns are the RGB triples that you need.
I don't know exactly how the data is arranged in a cv2 image but I think you have to do minor adjustements, if any at all.
Thanks to #gboffi i got an answer. I guess I was hoping that there is a more pythonic way of doing this, but ok.
# Load in Image File
img=cv2.imread("imgfile", cv2.IMREAD_GRAYSCALE)
# Create new array with the shape of the original image
color=np.zeros((img.shape[0],result.shape[1],3))
# Note that opencv needs BGR and values from 0..1
color[result==1]=(0.84,117/225,2/225)
color[result==2]=(78/225,173/225,240/225)
I'm trying to use the scipy kmeans algorithm.
So I have this really simple example:
from numpy import array
from scipy.cluster.vq import vq, kmeans, whiten
features = array([[3,4],[3,5],[4,2],[4,2]])
book = array((features[0],features[2]))
final = kmeans(features,book)
and the result is
final
(array([[3, 4],
[4, 2]]), 0.25)
What I don't understand is, for me the centroids coordinate should be the barycentre of all the points belongings to the cluster, so in this exemple
[3,9/2] and [4,2]
can anyone explain me the result the scipy algorithm is giving?
It looks like it is preserving the data type that you are giving it (int). Try:
features = array([[3., 4.], [3., 5.], [4., 2.], [4., 2.]])