I have a plot of spatial data that I display with imshow().
I need to be able to overlay the crystal lattice that produced the data. I have a png
file of the lattice that loads as a black and white image.The parts of this image I want to
overlay are the black lines that are the lattice and not see the white background between the lines.
I'm thinking that I need to set the alphas for each background ( white ) pixel to transparent (0 ? ).
I'm so new to this that I don't really know how to ask this question.
EDIT:
import matplotlib.pyplot as plt
import numpy as np
lattice = plt.imread('path')
im = plt.imshow(data[0,:,:],vmin=v_min,vmax=v_max,extent=(0,32,0,32),interpolation='nearest',cmap='jet')
im2 = plt.imshow(lattice,extent=(0,32,0,32),cmap='gray')
#thinking of making a mask for the white background
mask = np.ma.masked_where( lattice < 1,lattice ) #confusion here b/c even tho theimage is gray scale in8, 0-255, the numpy array lattice 0-1.0 floats...?
With out your data, I can't test this, but something like
import matplotlib.pyplot as plt
import numpy as np
import copy
my_cmap = copy.copy(plt.cm.get_cmap('gray')) # get a copy of the gray color map
my_cmap.set_bad(alpha=0) # set how the colormap handles 'bad' values
lattice = plt.imread('path')
im = plt.imshow(data[0,:,:],vmin=v_min,vmax=v_max,extent=(0,32,0,32),interpolation='nearest',cmap='jet')
lattice[lattice< thresh] = np.nan # insert 'bad' values into your lattice (the white)
im2 = plt.imshow(lattice,extent=(0,32,0,32),cmap=my_cmap)
Alternately, you can hand imshow a NxMx4 np.array of RBGA values, that way you don't have to muck with the color map
im2 = np.zeros(lattice.shape + (4,))
im2[:, :, 3] = lattice # assuming lattice is already a bool array
imshow(im2)
The easy way is to simply use your image as a background rather than an overlay. Other than that you will need to use PIL or Python Image Magic bindings to convert the selected colour to transparent.
Don't forget you will probably also need to resize either your plot or your image so that they match in size.
Update:
If you follow the tutorial here with your image and then plot your data over it you should get what you need, note that the tutorial uses PIL so you will need that installed as well.
Related
I want to write a script to create an image from a connection matrix. Basically, wherever there is a '1' in the matrix, I want that area to be shaded in the image. For eg -
I created this image using Photoshop. But I have a large dataset so I will have to automate the process. It would be really helpful if anyone could point me in the right direction.
EDIT
The image that I am getting after using the script is this. This is due to the fact that the matrix is large (19 x 19). Is there any way I can increase the visibility of this image so the black and white boxes appear more clear?
I would suggest usage of opencv combined with numpy in this case.
Create two-dimensional numpy.array of dtype='uint8' with 0 for black and 255 for white. For example, to get 2x2 array with white left upper, white right lower, black left lower and black right upper, you could use code:
myarray = numpy.array([[255,0],[0,255]],dtype='uint8')
Then you could save that array as image with opencv2 in this way:
cv2.imwrite('image.bmp',myarray)
In which every cell of array is represented by single pixel, however if you want to upscale (so for example every cell is represented by 5x5 square) then you might use numpy.kron function, with following one line:
myarray = numpy.kron(myarray, numpy.ones((5,5)))
before writing image
May be you can try this!
import matplotlib.cm as cm
# Display matrix
plt.imshow(np.random.choice([0, 1], size=100).reshape((10, 10)),cmap=cm.binary)
With a Seaborn heatmap:
import seaborn as sns
np.random.seed(3)
sns.set()
data = np.random.choice([0, 1], size=(16,16), p=[3./4, 1./4])
ax = sns.heatmap(data, square=True, xticklabels=False, yticklabels=False, cbar=False, linewidths=.8, linecolor='lightgray', cmap='gray_r')
Note the reverse colormap gray_r to have black for 1's and white for 0's.
I have found the following link: Python colour to greyscale
I would however like to do the opposite. Is this possible with Pyython (preferably with PIL, but other options are welcome as well like matplotlib)?
I need to read in a greyscale png image, which I would like to convert to a rainbow scale (preferably desaturated rainbow, but not necessary). The images originally come from c-code that generates numbers between 0 and 256 and converts those to grey tones. I would like to map those values now linearly to a colour-map (but I currently only have access to the png-image, not the c-code any more). So is there a way to map white to blue, and black to red, with all colours of the rainbow in between?
The mapping from color to grey is not invertable. So you need to indeed define some colormapping like the matplotlib colormaps do.
import matplotlib.pyplot as plt
# generate gray scale image
import scipy.misc
face = scipy.misc.face()
plt.imsave("face.png", face.mean(2), cmap="gray")
# read in image
im = plt.imread("face.png")
# plot image in color
plt.imshow(im.mean(2), cmap="jet_r")
#save image in color
plt.imsave("color.png", im.mean(2), cmap="jet_r")
plt.show()
I'm new to numpy's masked array data-structure, and I want to use it to work with segmented color images.
When I use matplotlib's plt.imshow( masked_gray_image, "gray") to display a masked gray image, the invalid regions will be displayed transparent, which is what I want.
However, when I do the same for color images it doesn't seem to work.
Interestingly the data-point cursor won't show the rgb values [r,g,b] but empty [], but still the color values are displayed instead of transparent.
Am I doing something wrong or is this not yet provided in matplotlib imshow?
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import face
img_col = face() #example image from scipy
img_gray = np.dot(img_col[...,:3], [0.299, 0.587, 0.114]) #convert to gray
threshold = 25
mask2D = img_gray < threshold # some exemplary mask
mask3D = np.atleast_3d(mask2D)*np.ones_like(img_col) # expand to 3D with broadcasting...
# using numpy's masked array to specify where data is valid
m_img_gray = np.ma.masked_where( mask2D, img_gray)
m_img_col = np.ma.masked_where( mask3D, img_col)
fig,axes=plt.subplots(1,4,num=2,clear=True)
axes[0].imshow(mask2D.astype(np.float32)) # plot mask
axes[0].set_title("simple mask")
axes[1].imshow(m_img_gray,"gray") #plot gray verison => works
axes[1].set_title("(works)\n masked gray")
axes[2].imshow(m_img_col) #plot color version, => does not work
axes[2].set_title("(doesn't work)\n masked color")
# manually adding mask as alpha channel to show what I want
axes[3].imshow( np.append( m_img_col.data, 255*(1-(0 < np.sum(m_img_col.mask ,axis=2,keepdims=True) ).astype(np.uint8) ),axis=2) )
axes[3].set_title("(desired) \n alpha channel set manually")
Here is an example image:
[update]:
some minor changes to code and images for better clarity...
I do not know if this is a feature not provided by matplotlib yet, but you can
just set all values to 255 where your mask is True:
m_img_col.data[m_img_col.mask]=255
In this way the invalid regions will be displayed as transparent
I'm trying to fill holes in the below image.
When I use SciPy's binary_fill_holes(), I am generally successful, with the exception of objects that touch the image's border.
Are there any existing Python functions that can fill holes in objects that touch the border? I tried adding a white border around the image, but that just resulted in the entire image being filled.
This assumes that there is more background than other stuff. It basically does a connected component analysis on the image. Extract the largest component (assumed to be the background), and sets everything else to white.
import numpy as np
import matplotlib.pyplot as plt
import skimage.morphology, skimage.data
img = skimage.data.imread('j1ESv.png', 1)
labels = skimage.morphology.label(img)
labelCount = np.bincount(labels.ravel())
background = np.argmax(labelCount)
img[labels != background] = 255
plt.imshow(img, cmap=plt.cm.gray)
plt.show()
Is there a way to cut out non rectangular areas of an image with Python PIL?
e.g. in this picture I want to exclude all black areas as well as towers, rooftops and poles.
http://img153.imageshack.us/img153/5330/skybig.jpg
I guess the ImagePath Module can do that, but furthermore, how can I read data of e.g. a svg file and convert it into a path?
Any help will be appreciated.
(My sub question is presumably the easier task: how to cut at least a circle of an image?)
If I understood correctly, you want to make some areas transparent within the image. And these areas are random shaped. Easiest way (that I can think of) is to create a mask and put it to the alpha channel of the image. Below is a code that shows how to do this.
If your question was "How to create a polygon mask" I will redirect you to:
SciPy Create 2D Polygon Mask
and look the accepted answer.
br,
Juha
import numpy
import Image
# read image as RGB and add alpha (transparency)
im = Image.open("lena.png").convert("RGBA")
# convert to numpy (for convenience)
imArray = numpy.asarray(im)
# create mask (zeros + circle with ones)
center = (200,200)
radius = 100
mask = numpy.zeros((imArray.shape[0],imArray.shape[1]))
for i in range(imArray.shape[0]):
for j in range(imArray.shape[1]):
if (i-center[0])**2 + (j-center[0])**2 < radius**2:
mask[i,j] = 1
# assemble new image (uint8: 0-255)
newImArray = numpy.empty(imArray.shape,dtype='uint8')
# colors (three first columns, RGB)
newImArray[:,:,:3] = imArray[:,:,:3]
# transparency (4th column)
newImArray[:,:,3] = mask*255
# back to Image from numpy
newIm = Image.fromarray(newImArray, "RGBA")
newIm.save("lena3.png")
Edit
Actually, I could not resist... the polygon mask solution was so elegant (replace the above circle with this):
# create mask
polygon = [(100,100), (200,100), (150,150)]
maskIm = Image.new('L', (imArray.shape[0], imArray.shape[1]), 0)
ImageDraw.Draw(maskIm).polygon(polygon, outline=1, fill=1)
mask = numpy.array(maskIm)
Edit2
Now when I think of it. If you have a black and white svg, you can load your svg directly as mask (assuming white is your mask). I have no sample svg images, so I cannot test this. I am not sure if PIL can open svg images.