Suppose I am taking an image from the webcam using opencv.
_, img = self.cap.read() # numpy.ndarray (480, 640, 3)
Then I create a QImage qimg using img:
qimg = QImage(
data=img,
width=img.shape[1],
height=img.shape[0],
bytesPerLine=img.strides[0],
format=QImage.Format_Indexed8)
But it gives an error saying that:
TypeError: 'data' is an unknown keyword argument
But said in this documentation, the constructor should have an argument named data.
I am using anaconda environment to run this project.
opencv version = 3.1.4
pyqt version = 5.9.2
numpy version = 1.15.0
What they are indicating is that the data is required as a parameter, not that the keyword is called data, the following method makes the conversion of a numpy/opencv image to QImage:
from PyQt5.QtGui import QImage, qRgb
import numpy as np
import cv2
gray_color_table = [qRgb(i, i, i) for i in range(256)]
def NumpyToQImage(im):
qim = QImage()
if im is None:
return qim
if im.dtype == np.uint8:
if len(im.shape) == 2:
qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_Indexed8)
qim.setColorTable(gray_color_table)
elif len(im.shape) == 3:
if im.shape[2] == 3:
qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_RGB888)
elif im.shape[2] == 4:
qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_ARGB32)
return qim
img = cv2.imread('/path/of/image')
qimg = NumpyToQImage(img)
assert(not qimg.isNull())
or you can use the qimage2ndarray library
When using the indexes to crop the image is only modifying the shape but not the data, the solution is to make a copy
img = cv2.imread('/path/of/image')
img = np.copy(img[200:500, 300:500, :]) # copy image
qimg = NumpyToQImage(img)
assert(not qimg.isNull())
I suspect it is erroring out with TypeError: 'data' is an unknown keyword argument because that is the first argument that it encounters.
The linked class reference is for PyQt4, for PyQt5 it links to C++ documentation at https://doc.qt.io/qt-5/qimage.html, but the similarities are clear.
PyQt4:
QImage.__init__ (self, bytes data, int width, int height, int bytesPerLine, Format format)
Constructs an image with the given width, height and format, that uses an existing memory buffer, data. The width and height must be specified in pixels. bytesPerLine specifies the number of bytes per line (stride).
PyQt5 (C++):
QImage(const uchar *data, int width, int height, int bytesPerLine, QImage::Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr)
Constructs an image with the given width, height and format, that uses an existing memory buffer, data. The width and height must be specified in pixels. bytesPerLine specifies the number of bytes per line (stride).
Per the examples at https://www.programcreek.com/python/example/106694/PyQt5.QtGui.QImage, you might try
qimg = QImage(img, img.shape[1], img.shape[0], img.strides[0], QImage.Format_Indexed8)
(without the data=, width=, etc)
Suppose I am taking an image from the webcam using opencv.
_, img = self.cap.read() # numpy.ndarray (480, 640, 3)
Then I create a QImage qimg using img:
qimg = QImage(
data=img,
width=img.shape[1],
height=img.shape[0],
bytesPerLine=img.strides[0],
format=QImage.Format_Indexed8)
But it gives an error saying that:
TypeError: 'data' is an unknown keyword argument
But said in this documentation, the constructor should have an argument named data.
I am using anaconda environment to run this project.
opencv version = 3.1.4
pyqt version = 5.9.2
numpy version = 1.15.0
What they are indicating is that the data is required as a parameter, not that the keyword is called data, the following method makes the conversion of a numpy/opencv image to QImage:
from PyQt5.QtGui import QImage, qRgb
import numpy as np
import cv2
gray_color_table = [qRgb(i, i, i) for i in range(256)]
def NumpyToQImage(im):
qim = QImage()
if im is None:
return qim
if im.dtype == np.uint8:
if len(im.shape) == 2:
qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_Indexed8)
qim.setColorTable(gray_color_table)
elif len(im.shape) == 3:
if im.shape[2] == 3:
qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_RGB888)
elif im.shape[2] == 4:
qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_ARGB32)
return qim
img = cv2.imread('/path/of/image')
qimg = NumpyToQImage(img)
assert(not qimg.isNull())
or you can use the qimage2ndarray library
When using the indexes to crop the image is only modifying the shape but not the data, the solution is to make a copy
img = cv2.imread('/path/of/image')
img = np.copy(img[200:500, 300:500, :]) # copy image
qimg = NumpyToQImage(img)
assert(not qimg.isNull())
I suspect it is erroring out with TypeError: 'data' is an unknown keyword argument because that is the first argument that it encounters.
The linked class reference is for PyQt4, for PyQt5 it links to C++ documentation at https://doc.qt.io/qt-5/qimage.html, but the similarities are clear.
PyQt4:
QImage.__init__ (self, bytes data, int width, int height, int bytesPerLine, Format format)
Constructs an image with the given width, height and format, that uses an existing memory buffer, data. The width and height must be specified in pixels. bytesPerLine specifies the number of bytes per line (stride).
PyQt5 (C++):
QImage(const uchar *data, int width, int height, int bytesPerLine, QImage::Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr)
Constructs an image with the given width, height and format, that uses an existing memory buffer, data. The width and height must be specified in pixels. bytesPerLine specifies the number of bytes per line (stride).
Per the examples at https://www.programcreek.com/python/example/106694/PyQt5.QtGui.QImage, you might try
qimg = QImage(img, img.shape[1], img.shape[0], img.strides[0], QImage.Format_Indexed8)
(without the data=, width=, etc)
import sys, Image, scipy, cv2, numpy
from scipy.misc import imread
from cv2 import cv
from SRM import SRM
def ndarrayToIplImage (source):
"""Conversion of ndarray to iplimage"""
image = cv.CreateImageHeader((source.shape[1], source.shape[0]), cv.IPL_DEPTH_8U, 3)
cv.SetData(image, source.tostring(), source.dtype.itemsize * 3 * source.shape[1])
return image
"""Main Program"""
filename = "snap.jpeg"
Q = 64
im = imread(filename)
name = filename[:-4]
img = Image.fromarray(im)
if img.size[0] > 200 or img.size[1] > 200:
ratio = img.size[0]/img.size[1]
size = int(ratio*200), 200
img = numpy.array(img.resize(size, Image.ANTIALIAS))
srm = SRM(img, Q)
srm.initialization()
srm.segmentation()
classes, map = srm.map()
"""Converting ndarray to PIL Image to iplimage"""
pil_img = Image.fromarray(map)
cv_img = cv.CreateImageHeader(pil_img.size, cv.IPL_DEPTH_8U, 3)
cv.SetData(cv_img, pil_img.tostring(), pil_img.size[0]*3)
print type(cv_img) ##prints <type 'cv2.cv.iplimage'>
"""Using ndarrayToIplImage function also gives the same error!"""
"""
cv_img if of type iplimage but still gives error while using cv.ShowImage()
or cv.SaveImage().
There is no error displayed. Just the console hangs...
"""
I am using the SRM (Statistical Region Merging) Package available at this page.
I have just changed the example program given in the package. I had to convert the type returned by the SRM package functions to iplimage. There is no error in using the package but somewhere in using opencv functions.
This is the image that is saved after the console closes after hanging.
It used cv.SaveImage().
I tried cv2.imwrite() and I got this as the result:
This is the image that should have been saved. I used scipy.misc.imsave('image.jpg', map) to save this.
Why do you use IplImage and PIL? SRM library read numpy array and you get a numpy array from cv2.imread(image), then if you need to resize yuor image you can use opencv function cv2.resize(...). Finally you can save an image with opencv with cv2.imwrite(...) your code should appear like this:
import sys, cv2, numpy
from SRM import SRM
"""Main Program"""
filename = "snap.jpeg"
Q = 64
img = cv2.imread(filename)
name = filename[:-4]
if img.shape[0] > 200 or img.shape[1] > 200:
ratio = img.shape[0] * 1. / img.shape[1]
size = (int(ratio * 200), 200)
img = cv2.resize(img, size, interpolation=cv2.INTER_LANCZOS4)
srm = SRM(img, Q)
srm.initialization()
srm.segmentation()
classes, srmMap = srm.map() # Map is a python function, use different variable name
srmMap = srmMap.astype('uint8') # or you can try other opencv supported type
# I suppose that srmMap is your image returned as numpy array
cv2.imwrite('name.jpeg', srmMap)
# or
cv2.imshow('image', srmMap)
cv2.waitKey(0)
I am trying to create an algorithm that blends the pixels of an image and I can bring the image as it was before, but I do not know do this.
I'm using python and pil, but I can use other libraries.
Exemple: to and back to
Thank you.
This should do it. There's no error handling, it doesn't follow pep8 standards, it uses slow PIL operations and it doesn't use an argument parsing library. I'm sure there are other bad things about it also.
It works by seeding python's random number generator with an invariant of the image under scrambling. The hash of the size is used. Since the size doesn't changed, a random sequence built on it will be the same for all images that share the same size. That sequence is used as a one-to-one mapping, therefore it's reversible.
The script may be invoked twice from a shell to create two images, "scrambled.png" and "unscrambled.png". "Qfhe3.png" is the source image.
python scramble.py scramble "./Qfhe3.png"
python scramble.py unscramble "./scrambled.png"
#scramble.py
from PIL import Image
import sys
import os
import random
def openImage():
return Image.open(sys.argv[2])
def operation():
return sys.argv[1]
def seed(img):
random.seed(hash(img.size))
def getPixels(img):
w, h = img.size
pxs = []
for x in range(w):
for y in range(h):
pxs.append(img.getpixel((x, y)))
return pxs
def scrambledIndex(pxs):
idx = list(range(len(pxs)))
random.shuffle(idx)
return idx
def scramblePixels(img):
seed(img)
pxs = getPixels(img)
idx = scrambledIndex(pxs)
out = []
for i in idx:
out.append(pxs[i])
return out
def unScramblePixels(img):
seed(img)
pxs = getPixels(img)
idx = scrambledIndex(pxs)
out = list(range(len(pxs)))
cur = 0
for i in idx:
out[i] = pxs[cur]
cur += 1
return out
def storePixels(name, size, pxs):
outImg = Image.new("RGB", size)
w, h = size
pxIter = iter(pxs)
for x in range(w):
for y in range(h):
outImg.putpixel((x, y), next(pxIter))
outImg.save(name)
def main():
img = openImage()
if operation() == "scramble":
pxs = scramblePixels(img)
storePixels("scrambled.png", img.size, pxs)
elif operation() == "unscramble":
pxs = unScramblePixels(img)
storePixels("unscrambled.png", img.size, pxs)
else:
sys.exit("Unsupported operation: " + operation())
if __name__ == "__main__":
main()
I want to take a screenshot via a python script and unobtrusively save it.
I'm only interested in the Linux solution, and should support any X based environment.
This works without having to use scrot or ImageMagick.
import gtk.gdk
w = gtk.gdk.get_default_root_window()
sz = w.get_size()
print "The size of the window is %d x %d" % sz
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
if (pb != None):
pb.save("screenshot.png","png")
print "Screenshot saved to screenshot.png."
else:
print "Unable to get the screenshot."
Borrowed from http://ubuntuforums.org/showpost.php?p=2681009&postcount=5
Just for completeness:
Xlib - But it's somewhat slow when capturing the whole screen:
from Xlib import display, X
import Image #PIL
W,H = 200,200
dsp = display.Display()
try:
root = dsp.screen().root
raw = root.get_image(0, 0, W,H, X.ZPixmap, 0xffffffff)
image = Image.fromstring("RGB", (W, H), raw.data, "raw", "BGRX")
image.show()
finally:
dsp.close()
One could try to trow some types in the bottleneck-files in PyXlib, and then compile it using Cython. That could increase the speed a bit.
Edit:
We can write the core of the function in C, and then use it in python from ctypes, here is something I hacked together:
#include <stdio.h>
#include <X11/X.h>
#include <X11/Xlib.h>
//Compile hint: gcc -shared -O3 -lX11 -fPIC -Wl,-soname,prtscn -o prtscn.so prtscn.c
void getScreen(const int, const int, const int, const int, unsigned char *);
void getScreen(const int xx,const int yy,const int W, const int H, /*out*/ unsigned char * data)
{
Display *display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
XImage *image = XGetImage(display,root, xx,yy, W,H, AllPlanes, ZPixmap);
unsigned long red_mask = image->red_mask;
unsigned long green_mask = image->green_mask;
unsigned long blue_mask = image->blue_mask;
int x, y;
int ii = 0;
for (y = 0; y < H; y++) {
for (x = 0; x < W; x++) {
unsigned long pixel = XGetPixel(image,x,y);
unsigned char blue = (pixel & blue_mask);
unsigned char green = (pixel & green_mask) >> 8;
unsigned char red = (pixel & red_mask) >> 16;
data[ii + 2] = blue;
data[ii + 1] = green;
data[ii + 0] = red;
ii += 3;
}
}
XDestroyImage(image);
XDestroyWindow(display, root);
XCloseDisplay(display);
}
And then the python-file:
import ctypes
import os
from PIL import Image
LibName = 'prtscn.so'
AbsLibPath = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + LibName
grab = ctypes.CDLL(AbsLibPath)
def grab_screen(x1,y1,x2,y2):
w, h = x2-x1, y2-y1
size = w * h
objlength = size * 3
grab.getScreen.argtypes = []
result = (ctypes.c_ubyte*objlength)()
grab.getScreen(x1,y1, w, h, result)
return Image.frombuffer('RGB', (w, h), result, 'raw', 'RGB', 0, 1)
if __name__ == '__main__':
im = grab_screen(0,0,1440,900)
im.show()
Compile all answers in one class.
Outputs PIL image.
#!/usr/bin/env python
# encoding: utf-8
"""
screengrab.py
Created by Alex Snet on 2011-10-10.
Copyright (c) 2011 CodeTeam. All rights reserved.
"""
import sys
import os
import Image
class screengrab:
def __init__(self):
try:
import gtk
except ImportError:
pass
else:
self.screen = self.getScreenByGtk
try:
import PyQt4
except ImportError:
pass
else:
self.screen = self.getScreenByQt
try:
import wx
except ImportError:
pass
else:
self.screen = self.getScreenByWx
try:
import ImageGrab
except ImportError:
pass
else:
self.screen = self.getScreenByPIL
def getScreenByGtk(self):
import gtk.gdk
w = gtk.gdk.get_default_root_window()
sz = w.get_size()
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
if pb is None:
return False
else:
width,height = pb.get_width(),pb.get_height()
return Image.fromstring("RGB",(width,height),pb.get_pixels() )
def getScreenByQt(self):
from PyQt4.QtGui import QPixmap, QApplication
from PyQt4.Qt import QBuffer, QIODevice
import StringIO
app = QApplication(sys.argv)
buffer = QBuffer()
buffer.open(QIODevice.ReadWrite)
QPixmap.grabWindow(QApplication.desktop().winId()).save(buffer, 'png')
strio = StringIO.StringIO()
strio.write(buffer.data())
buffer.close()
del app
strio.seek(0)
return Image.open(strio)
def getScreenByPIL(self):
import ImageGrab
img = ImageGrab.grab()
return img
def getScreenByWx(self):
import wx
wx.App() # Need to create an App instance before doing anything
screen = wx.ScreenDC()
size = screen.GetSize()
bmp = wx.EmptyBitmap(size[0], size[1])
mem = wx.MemoryDC(bmp)
mem.Blit(0, 0, size[0], size[1], screen, 0, 0)
del mem # Release bitmap
#bmp.SaveFile('screenshot.png', wx.BITMAP_TYPE_PNG)
myWxImage = wx.ImageFromBitmap( myBitmap )
PilImage = Image.new( 'RGB', (myWxImage.GetWidth(), myWxImage.GetHeight()) )
PilImage.fromstring( myWxImage.GetData() )
return PilImage
if __name__ == '__main__':
s = screengrab()
screen = s.screen()
screen.show()
This one works on X11, and perhaps on Windows too (someone, please check). Needs PyQt4:
import sys
from PyQt4.QtGui import QPixmap, QApplication
app = QApplication(sys.argv)
QPixmap.grabWindow(QApplication.desktop().winId()).save('test.png', 'png')
I have a wrapper project (pyscreenshot) for scrot, imagemagick, pyqt, wx and pygtk.
If you have one of them, you can use it.
All solutions are included from this discussion.
Install:
easy_install pyscreenshot
Example:
import pyscreenshot as ImageGrab
# fullscreen
im=ImageGrab.grab()
im.show()
# part of the screen
im=ImageGrab.grab(bbox=(10,10,500,500))
im.show()
# to file
ImageGrab.grab_to_file('im.png')
Cross platform solution using wxPython:
import wx
wx.App() # Need to create an App instance before doing anything
screen = wx.ScreenDC()
size = screen.GetSize()
bmp = wx.EmptyBitmap(size[0], size[1])
mem = wx.MemoryDC(bmp)
mem.Blit(0, 0, size[0], size[1], screen, 0, 0)
del mem # Release bitmap
bmp.SaveFile('screenshot.png', wx.BITMAP_TYPE_PNG)
import ImageGrab
img = ImageGrab.grab()
img.save('test.jpg','JPEG')
this requires Python Imaging Library
You can use this
import os
os.system("import -window root screen_shot.png")
I couldn't take screenshot in Linux with pyscreenshot or scrot because output of pyscreenshot was just a black screen png image file.
but thank god there was another very easy way for taking screenshot in Linux without installing anything. just put below code in your directory and run with python demo.py
import os
os.system("gnome-screenshot --file=this_directory.png")
also there is many available options for gnome-screenshot --help
Application Options:
-c, --clipboard Send the grab directly to the clipboard
-w, --window Grab a window instead of the entire screen
-a, --area Grab an area of the screen instead of the entire screen
-b, --include-border Include the window border with the screenshot
-B, --remove-border Remove the window border from the screenshot
-p, --include-pointer Include the pointer with the screenshot
-d, --delay=seconds Take screenshot after specified delay [in seconds]
-e, --border-effect=effect Effect to add to the border (shadow, border, vintage or none)
-i, --interactive Interactively set options
-f, --file=filename Save screenshot directly to this file
--version Print version information and exit
--display=DISPLAY X display to use
bit late but nevermind easy one is
import autopy
import time
time.sleep(2)
b = autopy.bitmap.capture_screen()
b.save("C:/Users/mak/Desktop/m.png")
There is a python package for this Autopy
The bitmap module can to screen grabbing (bitmap.capture_screen)
It is multiplateform (Windows, Linux, Osx).
for ubuntu this work for me, you can take a screenshot of select window with this:
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk
from gi.repository import GdkPixbuf
import numpy as np
from Xlib.display import Display
#define the window name
window_name = 'Spotify'
#define xid of your select 'window'
def locate_window(stack,window):
disp = Display()
NET_WM_NAME = disp.intern_atom('_NET_WM_NAME')
WM_NAME = disp.intern_atom('WM_NAME')
name= []
for i, w in enumerate(stack):
win_id =w.get_xid()
window_obj = disp.create_resource_object('window', win_id)
for atom in (NET_WM_NAME, WM_NAME):
window_name=window_obj.get_full_property(atom, 0)
name.append(window_name.value)
for l in range(len(stack)):
if(name[2*l]==window):
return stack[l]
window = Gdk.get_default_root_window()
screen = window.get_screen()
stack = screen.get_window_stack()
myselectwindow = locate_window(stack,window_name)
img_pixbuf = Gdk.pixbuf_get_from_window(myselectwindow,*myselectwindow.get_geometry())
to transform pixbuf into array
def pixbuf_to_array(p):
w,h,c,r=(p.get_width(), p.get_height(), p.get_n_channels(), p.get_rowstride())
assert p.get_colorspace() == GdkPixbuf.Colorspace.RGB
assert p.get_bits_per_sample() == 8
if p.get_has_alpha():
assert c == 4
else:
assert c == 3
assert r >= w * c
a=np.frombuffer(p.get_pixels(),dtype=np.uint8)
if a.shape[0] == w*c*h:
return a.reshape( (h, w, c) )
else:
b=np.zeros((h,w*c),'uint8')
for j in range(h):
b[j,:]=a[r*j:r*j+w*c]
return b.reshape( (h, w, c) )
beauty_print = pixbuf_to_array(img_pixbuf)
From this thread:
import os
os.system("import -window root temp.png")
It's an old question. I would like to answer it using new tools.
Works with python 3 (should work with python 2, but I haven't test it) and PyQt5.
Minimal working example. Copy it to the python shell and get the result.
from PyQt5.QtWidgets import QApplication
app = QApplication([])
screen = app.primaryScreen()
screenshot = screen.grabWindow(QApplication.desktop().winId())
screenshot.save('/tmp/screenshot.png')
Try it:
#!/usr/bin/python
import gtk.gdk
import time
import random
import socket
import fcntl
import struct
import getpass
import os
import paramiko
while 1:
# generate a random time between 120 and 300 sec
random_time = random.randrange(20,25)
# wait between 120 and 300 seconds (or between 2 and 5 minutes)
print "Next picture in: %.2f minutes" % (float(random_time) / 60)
time.sleep(random_time)
w = gtk.gdk.get_default_root_window()
sz = w.get_size()
print "The size of the window is %d x %d" % sz
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
ts = time.asctime( time.localtime(time.time()) )
date = time.strftime("%d-%m-%Y")
timer = time.strftime("%I:%M:%S%p")
filename = timer
filename += ".png"
if (pb != None):
username = getpass.getuser() #Get username
newpath = r'screenshots/'+username+'/'+date #screenshot save path
if not os.path.exists(newpath): os.makedirs(newpath)
saveas = os.path.join(newpath,filename)
print saveas
pb.save(saveas,"png")
else:
print "Unable to get the screenshot."