I have implemented pyqtgraph inside QGraphicsView in PyQt5. When I display the image the following way, it is stretched out and expands in the same aspect ratio as the screen. How do I fix this?
image = pg.ImageItem(asarray(Image.open('pic.png')) )
self.graphicsView.addItem(image)
image.rotate(270)
EDIT: found out how to rotate image, so I updated question with the solution. Now I am just trying to scale it properly.
You probably want something like:
import pyqtgraph as pg
from PIL import Image
from numpy import asarray
app = pg.mkQApp()
# Set up a window with ViewBox inside
gv = pg.GraphicsView()
vb = pg.ViewBox()
gv.setCentralItem(vb)
gv.show()
# configure view for images
vb.setAspectLocked()
vb.invertY()
# display image
img_data = asarray(Image.open('/home/luke/tmp/graph.png'))
image = pg.ImageItem(img_data, axisOrder='row-major')
vb.addItem(image)
The important pieces here that set the image scaling/orientation are:
using ImageItem(axisOrder='row-major') because image files are stored in row-major order
vb.invertY() because image files have the +y axis pointing downward
and vb.setAspectLocked() to keep the pixels square
I used np.rot90() instead, it's much faster and cythonable
image = pg.ImageItem(np.rot90(np.asarray(Image.open('pic.png'))))
Related
I am rendering Mandelbrot fractal on a pygame surface from a numpy array.
When I generate a 10k px * 10k px image and save it using pylab in a 10 * 10 inch image with a 1000dpi I get a 10k pixels image which render pretty well when windows build in photo app display it with zoom ajustment.
In pygame, the image looks pretty ugly although it is displayed with the same size :
I'm using this code :
pygame.init()
display = pygame.display.set_mode((1000, 1000))
surf = pygame.surfarray.make_surface(gimage)
surf = pygame.transform.rotate(surf, 90)
surf = pygame.transform.scale(surf, (1000, 1000))
How would one set pygame image size and ajust DPI ?
scale() is "fast scale operation" and doesn't use resampling.
There is also smoothscale() which uses different algorythm.
Maybe it will give you better result.
You can also use PIL/Pillow to resize() with different methods of resampling.
You can also try to use CV2 to resize().
Yesterday there was question how to use CV2 with PyGame
I would like to make simple graphs for my web page in python/django, but I do not know, which library (and how) to use.
I DO NOT WANT CHARTS, I SEEK A WAY TO CREATE IMAGE FROM PRIMITIVES LIKE RECTANGLES.
Each such graph is probabely generated and used only one time, as next time the values would differ.
I can simply compute the positions of all rectangles, lines or texts in it, so I would like something lightweight to just create pictre from that, which I would return as img/png (or so) mime style
like <img src="http://my.web.www/my/page/graph" > where the parameters to show would be decidied by session and database.
I can compute all the sizes beforehand, so I would like something simple like
img=Image(PNG,598,89) # style, x, y
img.add_text('1.3.', 10,10)
img.add_rectagle(20,10, 70,20, CYAN, BLACK)
....
return img.render()
Can you direct me, how to do it?
Thanks beforehand
navit nailed it :)
# from django.utils.httpwrappers import HttpResponse
from PIL import Image, ImageDraw
import os,sys
im = Image.new('RGB',(598,89),'white')
draw = ImageDraw.Draw(im)
draw.rectangle((0,0,im.size[0]-1,im.size[1]-1), outline='blue')
draw.rectangle((25,10,590,20), fill='white', outline='black')
draw.rectangle((25,10,70,20), fill='rgb(255,0,0)', outline='black')
draw.rectangle((70,10,90,20), fill='green', outline='black')
draw.text((1,10),'1.3.',fill='black')
del draw
# write to stdout
im.save(sys.stdout, "PNG")
# draw.flush()
# response = HttpResponse(mimetype="image/png")
# image.save(response, "PNG")
# return response
You should check Pillow out. Here is a sample how it works:
from PIL import Image, ImageDraw
im = Image.open("lena.pgm")
draw = ImageDraw.Draw(im)
draw.line((0, 0) + im.size, fill=128)
draw.line((0, im.size[1], im.size[0], 0), fill=128)
del draw
# write to stdout
im.save(sys.stdout, "PNG")
Serving a file from Pillow to your client should be straightforward. Let me know if you have a question.
edit: found these examples to get you started.
http://matplotlib.org/ permits to generate plenty of great graphs. You should be able to save it as an image and integrate it to your webpage
What about plotly? Never used in a project, but by reading the examples it seems very powerful and easy to use. It has a static image export (as most graphic libraries probably have).
I'm using pi3d to display an ImageSprite on the screen the texture of which comes form an image I'm loading.
displayTexture = pi3d.Texture("display/display.jpg", blend=True, mipmap=True)
displaySlide = pi3d.ImageSprite(texture=displayTexture, shader=shader, w=800, h=600)
This texture image is actually something I'm creating in-program. It's an openCV2 image and therefore just a numpy array. At the moment I'm saving it just to load it again as a texture, but is there a way to just constantly update the texture of the sprite with the changing numpy array values?
I looked into the openCV OpenGL support but from what I could see it only supports Windows at this stage and is therefore not suitable for this use.
Edit: Should have mentioned I'm happy for a lower level solution too. I'm currently trying to use .toString() on the image array and use the resulting byte list with glTexImage2D to produce a texture but no dice so far.
Yes you can pass a PIL.Image to pi3d.Texture and it will create a new Texture using that. There is a bit of work involved there so it will impact on frame rate if it's a big Texture. Also you need to update the pointer in the Buffer that holds the Texture array so the new Texture gets used.
There is a method to load a numpy array to a PIL.Image (Image.fromarray()) so this would be an easy route. However it's a bit convoluted as pi3d already converts the PIL.Image into a numpy array see https://github.com/tipam/pi3d/blob/master/pi3d/Texture.py#L163
The following works ok as a short-cut into the workings of pi3d.Texture but it's a bit of a hack calling the 'private' function _load_opengl. I might look at making a more robust method of doing this (i.e. for mapping videos to 3D objects etc)
#!/usr/bin/python
from __future__ import absolute_import, division, print_function, unicode_literals
import demo
import pi3d
import random
import numpy as np
from PIL import Image, ImageDraw
DISPLAY = pi3d.Display.create(x=150, y=150)
shader = pi3d.Shader("uv_flat")
im = Image.open("textures/PATRN.PNG")
#draw = ImageDraw.Draw(im) # there are various PIL libraries you could use
nparr = np.array(im)
tex = pi3d.Texture(im) # can pass PIL.Image rather than path as string
sprite = pi3d.ImageSprite(tex, shader, w=10.0, h=10.0)
mykeys = pi3d.Keyboard()
while DISPLAY.loop_running():
#draw.line((random.randint(0,im.size[0]),
# random.randint(0,im.size[1]),
# random.randint(0,im.size[0]),
# random.randint(0,im.size[1])), fill=128) # draw random lines
#nparr = np.array(im)
nparr += np.random.randint(-2, 2, nparr.shape) # random noise
tex.image = nparr
tex._load_opengl()
sprite.draw()
if mykeys.read() == 27:
mykeys.close()
DISPLAY.destroy()
break
PS I can't remember what version of pi3d the switch to numpy textures happened but it's quite recent so you probably have to upgrade
EDIT:
The switch from Texture.image being a bytes object to numpy array was v1.14 posted on 18Mar15
To clarify the steps to use a numpy array to initialise and refresh a changing image:
...
im = Image.fromarray(cv2im) # cv2im is a numpy array
tex = pi3d.Texture(im) # create Texture from PIL image
sprite = pi3d.ImageSprite(tex, shader, w=10.0, h=10.0)
...
tex.image = cv2im # set Texture.image to modified numpy array
tex._load_opengl() # re-run OpenGLESv2 routines
I am doing some image editing with the PIL libary. The point is, that I don't want to save the image each time on my HDD to view it in Explorer. Is there a small module that simply enables me to set up a window and display the image?
From near the beginning of the PIL Tutorial:
Once you have an instance of the Image class, you can use the methods
defined by this class to process and manipulate the image. For
example, let's display the image we just loaded:
>>> im.show()
Update:
Nowadays the Image.show() method is formally documented in the Pillow fork of PIL along with an explanation of how it's implemented on different OSs.
I tested this and it works fine for me:
from PIL import Image
im = Image.open('image.jpg')
im.show()
You can use pyplot to show images:
from PIL import Image
import matplotlib.pyplot as plt
im = Image.open('image.jpg')
plt.imshow(im)
plt.show() # image will not be displayed without this
If you find that PIL has problems on some platforms, using a native image viewer may help.
img.save("tmp.png") #Save the image to a PNG file called tmp.png.
For MacOS:
import os
os.system("open tmp.png") #Will open in Preview.
For most GNU/Linux systems with X.Org and a desktop environment:
import os
os.system("xdg-open tmp.png")
For Windows:
import os
os.system("powershell -c tmp.png")
Maybe you can use matplotlib for this, you can also plot normal images with it. If you call show() the image pops up in a window. Take a look at this:
http://matplotlib.org/users/image_tutorial.html
You can display an image in your own window using Tkinter, w/o depending on image viewers installed in your system:
import Tkinter as tk
from PIL import Image, ImageTk # Place this at the end (to avoid any conflicts/errors)
window = tk.Tk()
#window.geometry("500x500") # (optional)
imagefile = {path_to_your_image_file}
img = ImageTk.PhotoImage(Image.open(imagefile))
lbl = tk.Label(window, image = img).pack()
window.mainloop()
For Python 3, replace import Tkinter as tk with import tkinter as tk.
Yes, PIL.Image.Image.show() easy and convenient.
But if you want to put the image together, and do some comparing, then I will suggest you use the matplotlib. Below is an example,
import PIL
import PIL.IcoImagePlugin
import PIL.Image
import matplotlib.pyplot as plt
with PIL.Image.open("favicon.ico") as pil_img:
pil_img: PIL.IcoImagePlugin.IcoImageFile # You can omit. It helps IDE know what the object is, and then it will hint at the method very correctly.
out_img = pil_img.resize((48, 48), PIL.Image.ANTIALIAS)
plt.figure(figsize=(2, 1)) # 2 row and 1 column.
plt.subplots_adjust(hspace=1) # or you can try: plt.tight_layout()
plt.rc(('xtick', 'ytick'), color=(1, 1, 1, 0)) # set xtick, ytick to transparent
plt.subplot(2, 1, 1), plt.imshow(pil_img)
plt.subplot(2, 1, 2), plt.imshow(out_img)
plt.show()
This is what worked for me:
roses = list(data_dir.glob('roses/*'))
abc = PIL.Image.open(str(roses[0]))
PIL.Image._show(abc)
I am looking for a way to create a border in python.Is there any library in Python which we can import to create a border.
Note that I do not want to use any image masks to create this effect (e.g. I don't want to use any image editing package like GIMP to create a border image mask) .
Here is what I am looking for:
import fooImageBorders
import Image
foo = Image.open("someImage.jpg")
foo2 = fooImageBorders.bevel(foo, color = black)
...I can write my own methods to add borders .. but if there is already something like this out there with a comprehensive set of border options, I would like to make use of it.
I looked at PIL documentation and couldn't find a way to do this. I have windows xp and there doesn't seem to be a way to install PythonMagick either for Python 2.6 if you don't have cygwin.
Look at the ImageOps module within the PIL.
import Image
import ImageOps
x = Image.open('test.png')
y = ImageOps.expand(x,border=5,fill='red')
y.save('test2.png')
You can use the PythonMagick module. the documentation for this module is here (Magic ++ documentation)
Example: To add a red 2 pixel border to an image, you need following code.
from PythonMagick import Image
i = Image('example.jpg') # reades image and creates an image instance
i.borderColor("#ff0000") # sets border paint color to red
i.border("2x2") # paints a 2 pixel border
i.write("out.jpg")
# writes the image to a file
foo2 = foo.copy()
draw = ImageDraw.Draw(foo2)
for i in range(width):
draw.rectangle([i, i, foo2.size[0]-i-1, foo2.size[1]-i-1], outline = color)
foo2 will have a width-pixel border of color.
If you want different colored borders on each side, you can replace .rectangle with repeated .line calls.
If you want the border not to cover any part of the existing image, use this instead of foo.copy().
foo2 = Image.new(foo.mode, (foo.size[0] + 2*width, foo.size[1] + 2*width))
foo2.paste(foo, (width, width))