WordCloud size not increasing despite a big Mask - python

I have been trying this since morning and breaking my head... nothing seems to increase the size of the output in Jupyter notes. Despite the mask being as big as 2100*1980. Please tell me where am going wrong
from PIL import Image
import numpy as np
from wordcloud import WordCloud
mask = np.array(Image.open('pentagon.jpg'))
wc = WordCloud(mask=mask, scale=5, background_color='white',collocations=False,
max_words=500, max_font_size=256)
wc.generate_from_frequencies(k)
wc.prefer_horizontal=0.7
plt.imshow(wc, interpolation="bilinear")
plt.axis('off')
plt.show()
and the output is here...so small. I even tried plt.figure and stuff but nothing is working in increasing the size of the output. Please suggest where am going wrong
Thanks

Related

how to remove grid lines on image in python?

I am using google colab for my project. I am getting grid lines on images even I am not writing them.
from matplotlib import pyplot as plt
%matplotlib inline
import cv2
img = cv2.imread('k15.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
for code like above, I am getting grid lines which is not the case when I run the same code in my python shell.
plt.imshow(myImage)
plt.grid(None) <---- this should remove that white grid
Apparently something in the background changes the style. I have no experience whatsoever with google colab ti judge whether this can be responsible for the observed difference in displayed image.
In any case it should be possible to manually turn the grid lines off on a per notebook basis.
%matplotlib inline
from matplotlib import pyplot as plt
plt.rcParams["axes.grid"] = False
# rest of code
If you don't mind using a different packet, you can pretty much do it easily with PIL or Pillow
from PIL import Image
img = Image.open('C:\...\k15.jpg')
img.show()
The above answer didn't work for me in an Jupyter Notebook.
Here is an alternative solution - after every imshow you need to disable the grid like this:
...
plt.imshow(image)
plt.grid(False)
...

Concatenated images are badly degraded

I am trying to display several pictures on my Jupyter notebook. However, the pixel is really rough like below.
The pixel of original picture is clear. How should I improve this issue ?
This is a certain point of process to have a classification whether the picture is dog or cat. I have a many pictures of dogs and cat in the folder located on same directory and just took them from there. The picture is I just tried to show on the Jupyter notebook with using matplotlib.
Thank you in advance.
To force the resolution of the matplotlib inline images:
import matplotlib as plt
dpi = 300 # Recommended to set between 150-300 for quality image preview
plt.rcParams['figure.dpi'] = dpi
I think it uses a very low setting around 80 dpi by default.
The image quality seems to be degraded in the example picture simply because you are trying to show a 64 pixel large image on 400 pixels or so on screen. Each original pixel thus comprises several pixels on screen.
It seems you do not necessarily want to use matplotlib at all if the aim is to simply show the image in its original size on screen.
%matplotlib inline
import numpy as np
from IPython import display
from PIL import Image
a = np.random.rand(64,64,3)
b = np.random.rand(64,64,3)
c = (np.concatenate((a,b), axis=1)*255).astype(np.uint8)
display.display(Image.fromarray(c))
To achieve a similar result with matplotlib, you need to crop the margin around the axes and make sure the figure size is exactly the size of the array to show.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
a = np.random.rand(64,64,3)
b = np.random.rand(64,64,3)
c = np.concatenate((a,b), axis=1)
fig, ax = plt.subplots(figsize=(c.shape[1]/100.,c.shape[0]/100.), dpi=100)
fig.subplots_adjust(0,0,1,1)
ax.axis("off")
_ = ax.imshow(c)

How to combine .tif stacks in python?

I'm trying to combine multiple .tif stacks (that already consist of 40 images each) into a single tiff stack. I would prefer to do this using python. What I tried so far is (Keep in mind I don't have a lot of experience writing code, so sorry if I'm missing something obvious):
import numpy as np
from skimage import io
im1 = io.imread('filename1.ome.tif')
for i in range(2,10):
im = io.imread('filename'+str(i)+'.ome.tif')
im1 = np.concatenate((im1,im))
io.imsave('filescombined.ome.tif', im1)
This does leave me with a .tif file, and according to:
print(im1.shape)
It is the correct shape, and from using im1.dtype I get that both are uint16. However, I can not open the resulting image in ImageJ (or any other viewer I've tried). The problem doesn't seem to come from data being lost with io.imread or io.imsave, because if I do:
image = io.imread('filename1.ome.tif')
io.imsave('testing.ome.tif', image)
The result can be opened. So I guess the problem has to stem from np.concatenate, but I have no idea what exactly the problem is, let alone how to fix it.
If you have any ideas on how to fix it, that would be very much appreciated!
Try the external.tifffile module of scikit image. It does not seem to encounter the problem you describe.
The following works for me on Windows 7 and Python 3.5. It correctly saves a stack of 180 images each 100x100 pixels that can be imported straight into ImageJ
from skimage.external import tifffile as tif
import numpy as np
stack1 = np.random.randint(255, size=(20, 100, 100))
for i in range(2,10):
stack = np.random.randint(255, size=(20, 100, 100))
stack1 = np.concatenate((stack1,stack))
tif.imsave('stack1.tif', stack1.astype('uint16'), bigtiff=True)
When you drag and drop the file into ImageJ the Bio-Formats Import Option will pop up (see below). Just select the View Stack as "Standard ImageJ" and data will be loaded.Screenshot of the ImageJ Bio-Format Import Option popup window

Python OpenCV drawing errors after manipulating array with numpy

I'm reading in an image with OpenCV, and trying to do something with it in numpy (rotate 90deg). Viewing the result with imshow from matplotlib, it all seems to be working just fine - image is rotated. I can't use drawing methods from OpenCV on the new image, however. In the following code (I'm running this in a sagemath cloud worksheet):
%python
import cv2
import matplotlib.pyplot as plt
import numpy as np
import os, sys
image = np.array( cv2.imread('imagename.png') )
plt.imshow(image,cmap='gray')
image = np.array(np.rot90(image,3) ) # put it right side up
plt.imshow(image,cmap='gray')
cv2.rectangle(image,(0,0),(100,100),(255,0,0),2)
plt.imshow(image,cmap='gray')
I get the following error on the cv2.rectangle() command:
TypeError: Layout of the output array img is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
The error goes away if I use np.array(np.rot90(image,4) ) instead (i.e. rotate it 360). So it appears that the change in dimensions is messing it up. Does OpenCV store the dimensions somewhere internally that I need to update or something?
EDIT: Adding image = image.copy() after rot90() solved the problem. See rayryeng's answer below.
This is apparently a bug in the Python OpenCV wrapper. If you look at this question here: np.rot90() corrupts an opencv image, apparently doing a rotation that doesn't result back in the original dimensions corrupts the image and the OP in that post experiences the same error you are having. FWIW, I also experienced the same bug.... no idea why.
A way around this is to make a copy of the image after you rotate, and then show the image. This I can't really explain, but it seems to work. Also, make sure you call plt.show() at the end of your code to show the image:
import cv2
import matplotlib.pyplot as plt
import numpy as np
import os, sys
image = np.array( cv2.imread('imagename.png') )
plt.imshow(image,cmap='gray')
image = np.array(np.rot90(image,3) ) # put it right side up
image = image.copy() # Change
plt.imshow(image,cmap='gray')
cv2.rectangle(image,(0,0),(100,100),(255,0,0),2)
plt.imshow(image,cmap='gray')
plt.show() # Show image
I faced the same problem with numpy 1.11.2 and opencv 3.3.0. Not sure why, but this did the job for me.
Before using cv2.rectangle, add the line below:
image1 = image1.transpose((1,0)).astype(np.uint8).copy()
Reference
Convert data type works for my problem.
The image is of type np.int64 before the convert.
image = image.astype(np.int32) # convert data type

Increase resolution with word-cloud and remove empty border

I am using word cloud with some txt files. How do I change this example if I wanted to 1) increase resolution and 2) remove empty border.
#!/usr/bin/env python2
"""
Minimal Example
===============
Generating a square wordcloud from the US constitution using default arguments.
"""
from os import path
import matplotlib.pyplot as plt
from wordcloud import WordCloud
d = path.dirname(__file__)
# Read the whole text.
text = open(path.join(d, 'constitution.txt')).read()
wordcloud = WordCloud().generate(text)
# Open a plot of the generated image.
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
You can't increase the resolution of the image in plt.show() since that is determined by your screen, but you can increase the size. This allows it to scale, zoom, etc. without blurring. To do this pass dimensions to WordCloud, e.g.
wordcloud = WordCloud(width=800, height=400).generate(text)
However, this just determines the size of the image created by WordCloud. When you display this using matplotlib it is scaled to the size of the plot canvas, which is (by default) around 800x600 and you again lose quality. To fix this you need to specify the size of the figure before you call imshow, e.g.
plt.figure( figsize=(20,10) )
plt.imshow(wordcloud)
By doing this I can successfully create a 2000x1000 high resolution word cloud.
For your second question (removing the border) first we could set the border to black, so it is less apparent, e.g.
plt.figure( figsize=(20,10), facecolor='k' )
You can also shrink the size of the border by using tight_layout, e.g.
plt.tight_layout(pad=0)
The final code:
# Read the whole text.
text = open(path.join(d, 'constitution.txt')).read()
wordcloud = WordCloud(width=1600, height=800).generate(text)
# Open a plot of the generated image.
plt.figure( figsize=(20,10), facecolor='k')
plt.imshow(wordcloud)
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()
By replacing the last two lines with the following you can get the final output shown below:
plt.savefig('wordcloud.png', facecolor='k', bbox_inches='tight')
If you are trying to use an image as a mask, make sure to use a big image to get better image quality.. I spent hours figuring this out.
Heres an example of a code snippet I used
mask = np.array(Image.open('path_to_your_image'))
image_colors = ImageColorGenerator(mask)
wordcloud = WordCloud(width=1600, height=800, background_color="rgba(255, 255, 255, 0)", mask=mask
,color_func = image_colors).generate_from_frequencies(x)
# Display the generated image:
plt.figure( figsize=(20,10) )
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
It is very simple, plt.tight_layout(pad=0) does the job, reduces the space in the background, removing the excess padding.
You can use the method to_svg and get a resolution however high you want.
with open("Output.svg", "w") as text_file:
text_file.write(wc.to_svg())
Try an example by appending these two lines to this file, and the result is gorgeous.
(Other answers have addressed the border problem, and also the example doe not have a border.)
In case you run into the issue of slower application while improving the resolution ie. in a web application, the WordCloud documentation advises that you utilize the scale parameter along with the canvas' width & height params to get a resolution & response time that works for your use case.
Blurry wordclouds - I've been wrestling with this. For my use, I found that too large a differential in the between the most frequent word occurrences and those with few occurrences left the lower-count words unreadable. When I scaled the more frequent counts to reduce the differential, all the lower-frequency words were much more readable.

Categories

Resources