I use a program which can generate a picture. I saved it by
img.save("/usr/lib/python2.6/site-packages/openstackdashboard/static/dashboard/img/validate.jpeg")
return strs # strs is picture's data
Everything goes right when run it alone . But " IOError " occured when I call it by
from .auth_code import Create_Validate_Code
auth_code_str = Create_Validate_Code()
And horizon says " [Errno 13] Permission denied: '/usr/lib/python2.6/site-packages/openstack-dashboard/static/dashboard/img/validate.jpeg' ". Could someone help me ? Thanks a lot .
This is all code to create a picture
#!/usr/bin/env python
import random
import Image, ImageDraw, ImageFont, ImageFilter
_letter_cases = "1234567890"
_upper_cases = _letter_cases.upper()
_numbers = ''.join(map(str, range(3, 10)))
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
fontType="/usr/share/fonts/lohit-tamil/Lohit-Tamil.ttf"
def create_lines(draw,n_line,width,height):
line_num = random.randint(n_line[0],n_line[1])
for i in range(line_num):
begin = (random.randint(0, width), random.randint(0, height))
end = (random.randint(0, width), random.randint(0, height))
draw.line([begin, end], fill=(0, 0, 0))
def create_points(draw,point_chance,width,height):
chance = min(100, max(0, int(point_chance)))
for w in xrange(width):
for h in xrange(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=(0, 0, 0))
def create_strs(draw,chars,length,font_type, font_size,width,height,fg_color):
c_chars = random.sample(chars, length)
strs = ' %s ' % ' '.join(c_chars)
font = ImageFont.truetype(font_type, font_size)
font_width, font_height = font.getsize(strs)
draw.text(((width - font_width) / 3, (height - font_height) / 3),strs, font=font, fill=fg_color)
return ''.join(c_chars)
def Create_Validate_Code(size=(120, 30),
chars=init_chars,
img_type="GIF",
mode="RGB",
bg_color=(255, 255, 255),
fg_color=(0, 0, 255),
font_size=18,
font_type=fontType,
length=4,
draw_lines=True,
n_line=(1, 2),
draw_points=True,
point_chance = 2):
width, height = size
img = Image.new(mode, size, bg_color)
draw = ImageDraw.Draw(img)
if draw_lines:
create_lines(draw,n_line,width,height)
if draw_points:
create_points(draw,point_chance,width,height)
strs = create_strs(draw,chars,length,font_type, font_size,width,height,fg_color)
params = [1 - float(random.randint(1, 2)) / 100,
0,
0,
0,
1 - float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500
]
img = img.transform(size, Image.PERSPECTIVE, params)
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
img.save("/usr/lib/python2.6/site-packages/openstack-dashboard/static/dashboard/img/validate.jpeg")
return strs
The code to create and save the file is inside the function Create_Validate_Code. In your initial version, you never call that function anywhere. Therefore, it never tries to create and save the file, so it never fails.
When you add this:
from .auth_code import Create_Validate_Code
auth_code_str = Create_Validate_Code()
… now you're calling the function. So now it fails. It has nothing whatsoever to do with the third-party module you're using; you could do the same thing with just this:
Create_Validate_Code()
Meanwhile, the reason that creating the file fails is that you don't have write access to directories in the middle of your system's site-packages. This is by design. This is why operating systems have permissions in the first place—to stop some buggy or malicious code run as a normal user from screwing up programs and data needed by the entire system.
Create the file somewhere you do have access to, like some place in your home directory, or the temporary directory, or whatever's appropriate to whatever you're trying to do, and the problem will go away.
Have you tried running the final app as Administrator/root? That usually fixes any "Permission denied" errors while programming.
You shouldn't save data deep within your Python installation. It's really bad practice, which is why the OS is preventing you from doing it. Save the picture somewhere in your home folder.
Related
I want to resize an image using a function. I want to do it through a function because I want it to be modular. However, I am getting the following error:
Traceback (most recent call last):
File "/home/onur/Desktop/composite-testing.py", line 30, in <module>
brand_logo = random_resize(brand_logo)
File "/home/onur/Desktop/composite-testing.py", line 12, in random_resize
logo = logo.resize(width/resize_rand, height/resize_rand)
File "/usr/lib/python3/dist-packages/PIL/Image.py", line 1833, in resize
raise ValueError(
ValueError: Unknown resampling filter (183.0). Use Image.NEAREST (0), Image.LANCZOS (1), Image.BILINEAR (2), Image.BICUBIC (3), Image.BOX (4) or Image.HAMMING (5)`
This is my function. I want the resizing to be random but still maintain the scale:
def random_resize(logo):
resize_rand = random.randint(0, 3)
width, height = logo.size
logo = logo.resize(width/resize_rand, height/resize_rand)
return logo
And this is how I'm using it in the code:
for background in os.listdir(current_dir + '/composite-testing/'):
for logo_image in os.listdir(current_dir + '/logos/'):
epoch = str(math.ceil(time.time()))
if not os.path.exists(current_dir + '/result/'):
os.mkdir(current_dir + '/result/')
brand_logo = Image.open(current_dir + '/logos/' + logo_image, 'r').convert('RGBA')
logo_width, logo_height = brand_logo.size
brand_logo = random_rotate(brand_logo)
--> brand_logo = random_resize(brand_logo)
gameplay = Image.open(current_dir + '/composite-testing/' + background, 'r').convert('RGBA')
gameplay_width, gameplay_height = gameplay.size
logo_x = math.floor((gameplay_width / 2) - (logo_width / 2))
logo_y = math.floor((gameplay_height / 2) - (logo_height / 2))
text_img = Image.new('RGBA', (gameplay_width, gameplay_height), (0, 0, 0, 0))
text_img.paste(gameplay, (0, 0))
text_img.paste(brand_logo, (logo_x, logo_y), mask=brand_logo)
img_draw = ImageDraw.Draw(text_img)
img_draw.rectangle(((logo_x, logo_y), (logo_x + logo_width, logo_y + logo_height)), outline='Red')
text_img.save(current_dir + '/result/' + epoch + '.png', format="png")
You are using the resize() method the wrong way. The syntax is
resize(size, resample=0)
where size is a tuple (width, height). You are supplying the height as the second argument, the resampling filter. The improved version is
logo = logo.resize((width/resize_rand, height/resize_rand))
May I point out another risk of your code: random.randint(0, 3) will return a random number from 0 to 3 inclusive - so you are risking a division by zero error when you divide the width and height by it.
I'm trying to have a progress window which shows the progress, alongside having tasks happening in the background. Everything works as expected, except the window partially loads on to the screen (how much of it does depends on every run). Here is the relevant part of the code:
def loading(): #Displays loading progress while setting up the exam
global load, progress
load = Toplevel()
load.title("Loading")
load.attributes('-topmost', True)
load.overrideredirect(True)
lab = Label(load, text = ("Preparing Your Exam, Please Wait!\nPlease DO NOT Open any Other Window.\n"
+"Doing so may lead to immidiate Termination."))
lab.grid(row = 0, column = 1, padx = 20, pady = 20)
progress=Progressbar(load,orient=HORIZONTAL,length=200,mode='determinate')
progress.grid(row = 1, column = 1, padx = 20, pady = 20)
log = Label(load, image = logo)
log.image = logo
log.grid(row = 0, column = 0, rowspan = 2, padx = 20, pady = 20)
w_req, h_req = load.winfo_width(), load.winfo_height()
w_form = load.winfo_rootx() - load.winfo_x()
w = w_req + w_form*2
h = h_req + (load.winfo_rooty() - load.winfo_y()) + w_form
x = (load.winfo_screenwidth() // 2) - (w // 2)
y = (load.winfo_screenheight() // 2) - (h // 2)
load.geometry(f'{w_req}x{h_req}+{x}+{y}')
Here's what happens after calling loading:
loading()
conv_th = Thread(target = Convert).start()
The Convert function converts and processes images, I'm not sharing that because it might not be relevant.
I far as I think, it might be because it is not getting enough time to load completely, but I couldn't really figure out what could be causing the program to behave this way. Any help will be appreciated!
Update: This behavior is seen even if conv_th = Thread(target = Convert).start() is omitted, implying that there could be a problem within the loading() function.
So, I ended up solving the problem myself. I'm telling the reason that I think is most probable, please correct me if the reason that I give is incorrect or there is another solution for this.
This part of the code,
w_req, h_req = load.winfo_width(), load.winfo_height()
w_form = load.winfo_rootx() - load.winfo_x()
w = w_req + w_form*2
h = h_req + (load.winfo_rooty() - load.winfo_y()) + w_form
x = (load.winfo_screenwidth() // 2) - (w // 2)
y = (load.winfo_screenheight() // 2) - (h // 2)
was being executed too early, before the window could actually load itself up completely, and hence whatever amount of it got loaded before this, was taken as the dimensions and then the values were set.
Adding the command load.update_idletasks() before the above part of the code resolved the problem. Thanks #martineau, your comment was really helpful in figuring this out.
I've been struggling to come up with a script that allows me to take screenshots of my desktop more than once per every second. I'm using Win10.
PIL:
from PIL import ImageGrab
import time
while True:
im = ImageGrab.grab()
fname = "dropfolder/%s.png" %int(time.time())
im.save(fname,'PNG')
Results 1.01 seconds per image.
PyScreeze (https://github.com/asweigart/pyscreeze):
import pyscreeze
import time
while True:
fname = "dropfolder/%s.png" %int(time.time())
x = pyscreeze.screenshot(fname)
Results 1.00 seconds per image.
Win32:
import win32gui
import win32ui
import win32con
import time
w=1920 #res
h=1080 #res
while True:
wDC = win32gui.GetWindowDC(0)
dcObj=win32ui.CreateDCFromHandle(wDC)
cDC=dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, w, h)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0,0),(w, h) , dcObj, (0,0), win32con.SRCCOPY)
fname = "dropfolder/%s.png" %int(time.time())
dataBitMap.SaveBitmapFile(cDC, fname)
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(0, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
Results 1.01 seconds per image.
Then I stumbled into thread (Fastest way to take a screenshot with python on windows) where it was suggested that gtk would yield phenomenal results.
However using gtk:
import gtk
import time
img_width = gtk.gdk.screen_width()
img_height = gtk.gdk.screen_height()
while True:
screengrab = gtk.gdk.Pixbuf(
gtk.gdk.COLORSPACE_RGB,
False,
8,
img_width,
img_height
)
fname = "dropfolder/%s.png" %int(time.time())
screengrab.get_from_drawable(
gtk.gdk.get_default_root_window(),
gtk.gdk.colormap_get_system(),
0, 0, 0, 0,
img_width,
img_height
).save(fname, 'png')
Results 2.34 seconds per image.
It seems to me like I'm doing something wrong, because people have been getting great results with gtk.
Any advices how to speed up the process?
Thanks!
Your first solution should be giving you more than one picture per second. The problem though is that you will be overwriting any pictures that occur within the same second, i.e. they will all have the same filename. To get around this you could create filenames that include 10ths of a second as follows:
from PIL import ImageGrab
from datetime import datetime
while True:
im = ImageGrab.grab()
dt = datetime.now()
fname = "pic_{}.{}.png".format(dt.strftime("%H%M_%S"), dt.microsecond // 100000)
im.save(fname, 'png')
On my machine, this gave the following output:
pic_1143_24.5.png
pic_1143_24.9.png
pic_1143_25.3.png
pic_1143_25.7.png
pic_1143_26.0.png
pic_1143_26.4.png
pic_1143_26.8.png
pic_1143_27.2.png
In case anyone cares in 2022: You can try my newly created project DXcam: I think for raw speed it's the fastest out there (in python, and without going too deep into the rabbit hole). It's originally created for a deep learning pipeline for FPS games where the higher FPS you get the better. Plus I (am trying to) design it to be user-friendly:
For a screenshot just do
import dxcam
camera = dxcam.create()
frame = camera.grab() # full screen
frame = camera.grab(region=(left, top, right, bottom)) # region
For screen capturing:
camera.start(target_fps=60) # threaded
for i in range(1000):
image = camera.get_latest_frame() # Will block until new frame available
camera.stop()
I copied the part of the benchmarks section from the readme:
DXcam
python-mss
D3DShot
Average FPS
238.79
75.87
118.36
Std Dev
1.25
0.5447
0.3224
The benchmarks is conducted through 5 trials on my 240hz monitor with a constant 240hz rendering rate synced w/the monitor (using blurbuster ufo test).
You can read more about the details here: https://github.com/ra1nty/DXcam
This solution uses d3dshot.
def d3dgrab(rect=(0, 0, 0, 0), spath=r".\\pictures\\cache\\", sname="", title=""):
""" take a screenshot by rect. """
sname = sname if sname else time.strftime("%Y%m%d%H%M%S000.jpg", time.localtime())
while os.path.isfile("%s%s" % (spath, sname)):
sname = "%s%03d%s" % (sname[:-7], int(sname[-7:-4]) + 1, sname[-4:])
xlen = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
ylen = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
assert 0 <= rect[0] <= xlen and 0 <= rect[2] <= xlen, ValueError("Illegal value of X coordination in rect: %s" % rect)
assert 0 <= rect[1] <= ylen and 0 <= rect[3] <= ylen, ValueError("Illegal value of Y coordinatoin in rect: %s" % rect)
if title:
hdl = win32gui.FindWindow(None, title)
if hdl != win32gui.GetForegroundWindow():
win32gui.SetForegroundWindow(hdl)
rect = win32gui.GetWindowRect(hdl)
elif not sum(rect):
rect = (0, 0, xlen, ylen)
d = d3dshot.create(capture_output="numpy")
return d.screenshot_to_disk(directory=spath, file_name=sname, region=rect)
I think it can be helped
sname = sname if sname else time.strftime("%Y%m%d%H%M%S000.jpg", time.localtime())
while os.path.isfile("%s%s" % (spath, sname)):
sname = "%s%03d%s" % (sname[:-7], int(sname[-7:-4]) + 1, sname[-4:])
And it's fastest way to take screenshot I found.
I am currently experimenting with the pytest module to create unit tests for a project I'm working on. I'm trying to test the 'add_point' method which draws an ellipse based on a set of pixels. What I want to do is inspect 'draw' to ensure that the ellipse has been created successfully. Unfortunately I don't know how to go about this, so any help will be appreciated. Here's my code so far:
(A) TheSlicePreviewMaker.py
import os, Image, ImageDraw, ImageFont
from json_importer import json_importer
class SlicePreviewer(object):
def __init__(self):
self.screen_size = (470, 470)
self.background_colour = (86,0,255)
self.platform_fill_colour = (100, 100, 100)
self.platform_outline_colour = (0, 0, 0)
self.platform_window = (0,0,469,469)
self.point_colour = (0,0,255)
self.config_object = json_importer("ConfigFile.txt")
self.image = None
def initialise_image(self):
self.image = Image.new('RGB',self.screen_size,self.background_colour)
draw = ImageDraw.Draw(self.image)
draw.rectangle(self.platform_window,outline=self.platform_outline_colour,fill=self.platform_fill_colour)
del draw
def add_point(self, px, py):
x1 = px - 1
y1 = py - 1
x2 = px + 1
y2 = py + 1
draw = ImageDraw.Draw(self.image)
draw.ellipse((x1,y1,x2,y2),outline=self.point_colour,fill=self.point_colour)
return draw #del draw
def save_image(self, file_name):
self.image.save(file_name, "BMP")
(B) test_TheSlicePreviewMaker.py
from TheSlicePreviewMaker import SlicePreviewer
slice_preview = SlicePreviewer()
class TestSlicePreviewer:
def test_init(self):
'''check that the config file object has been created on init'''
assert slice_preview.config_object != None
def test_initialise_image(self):
'''verify if the image has been successfully initialised'''
assert slice_preview.image.mode == 'RGB'
def test_add_point(self):
'''has the point been drawn successfully?'''
draw = slice_preview.add_point(196,273)
assert something
import pytest
if __name__ == '__main__':
pytest.main("--capture=sys -v")
SN: I've run TheSlicePreviewMaker.py separately to check the bitmap file it produces, so I know that the code works. What I want to achieve is unit test this so that each time I don't have to go check the bitmap.
One approach is to manually inspect the generated image and if looks OK to you, save it next to the test and use a image diffing algorithm (for example ImageChops.difference) to obtain a threshold value that you can use to make sure future test runs are still drawing the same image.
For example:
# contents of conftest.py
from PIL import ImageChops, ImageDraw, Image
import pytest
import os
import py.path
import math
import operator
def rms_diff(im1, im2):
"""Calculate the root-mean-square difference between two images
Taken from: http://snipplr.com/view/757/compare-two-pil-images-in-python/
"""
h1 = im1.histogram()
h2 = im2.histogram()
def mean_sqr(a,b):
if not a:
a = 0.0
if not b:
b = 0.0
return (a-b)**2
return math.sqrt(reduce(operator.add, map(mean_sqr, h1, h2))/(im1.size[0]*im1.size[1]))
class ImageDiff:
"""Fixture used to make sure code that generates images continues to do so
by checking the difference of the genereated image against known good versions.
"""
def __init__(self, request):
self.directory = py.path.local(request.node.fspath.dirname) / request.node.fspath.purebasename
self.expected_name = (request.node.name + '.png')
self.expected_filename = self.directory / self.expected_name
def check(self, im, max_threshold=0.0):
__tracebackhide__ = True
local = py.path.local(os.getcwd()) / self.expected_name
if not self.expected_filename.check(file=1):
msg = '\nExpecting image at %s, but it does not exist.\n'
msg += '-> Generating here: %s'
im.save(str(local))
pytest.fail(msg % (self.expected_filename, local))
else:
expected = Image.open(str(self.expected_filename))
rms_value = rms_diff(im, expected)
if rms_value > max_threshold:
im.save(str(local))
msg = '\nrms_value %s > max_threshold of %s.\n'
msg += 'Obtained image saved at %s'
pytest.fail(msg % (rms_value, max_threshold, str(local)))
#pytest.fixture
def image_diff(request):
return ImageDiff(request)
Now you can use the image_diff fixture in your tests. For example:
def create_image():
""" dummy code that generates an image, simulating some actual code """
im = Image.new('RGB', (100, 100), (0, 0, 0))
draw = ImageDraw.Draw(im)
draw.ellipse((10, 10, 90, 90), outline=(0, 0, 255),
fill=(255, 255, 255))
return im
def test_generated_image(image_diff):
im = create_image()
image_diff.check(im)
The first time your run this test, it will fail with this output:
================================== FAILURES ===================================
____________________________ test_generated_image _____________________________
image_diff = <test_foo.ImageDiff instance at 0x029ED530>
def test_generated_image(image_diff):
im = create_image()
> image_diff.check(im)
E Failed:
E Expecting image at X:\temp\sandbox\img-diff\test_foo\test_generated_image.png, but it does not exist.
E -> Generating here: X:\temp\sandbox\img-diff\test_generated_image.png
You can then manually check the image and if everything is OK, move it to a directory with the same name as the test file, with the name of the test as the file name plus ".png" extension. From now one whenever the test runs, it will check that the image is similar within an acceptable amount.
Suppose you change the code and produce a slightly different image, the test will now fail like this:
================================== FAILURES ===================================
____________________________ test_generated_image _____________________________
image_diff = <test_foo.ImageDiff instance at 0x02A4B788>
def test_generated_image(image_diff):
im = create_image()
> image_diff.check(im)
E Failed:
E rms_value 2.52 > max_threshold of 0.0.
E Obtained image saved at X:\temp\sandbox\img-diff\test_generated_image.png
test_foo.py:63: Failed
========================== 1 failed in 0.03 seconds ===========================
The code needs some polishing but should be a good start. You can find a version of this code here.
Cheers,
I have been attempting to work an iCreate, roomba without a vacuum cleaner attached using Python 2.7.1 and have created working code. When I type each line in by hand it works perfectly, however when putting all the code in together it stalls and does not operate.
import Create
import VideoCapture
from PIL import Image, Imagechops
import os
robot = Create.Create(3)
camera = VideoCapture.Device(0, 1)
(rgb_red, rgb_green, rgb_blue) = (0, 0, 0)
red = Image.open("Red.jpeg")
(redr, redg, redb) = red.getpixel((0, 0))
blue = Image.open("Blue.jpeg")
(bluer, blueg, blueb) = blue.getpixel((0, 0))
green = Image.open("Green.jpeg")
(greenr, greeng, greenb) = green.getpixel((0, 0))
yellow = Image.open("Yellow.jpeg")
(yellowr, yellowg, yellowb) = yellow.getpixel((0, 0))
camera.getImage(0, 0, 'tl')
camera.saveSnapshot('CurrentPicture.jpeg', 0, 0, 'tl')
pic = Image.open("CurrentPicture.jpeg")
(rgb_red, rgb_green, rgb_blue) = pic.getpixel((0, 0))
os.remove("C:\Python27\CurrentPicture.jpeg")
while 0 == 0:
if((rgb_red - redr) < (rgb_green - greeng)) and ((rgb_red - redr) < (rgb_blue - blueb)):
robot.stop()
elif((rgb_blue - blueb) < (rgb_green - greeng)) and ((rgb_blue - blueb) < (rgb_red - redr)):
robot.turn(45, 40)
elif((rgb_green - greeng) < (rgb_red - redr)) and ((rgb_green - greeng) < (rgb_blue - blueb)):
robot.move(50, 50)
camera.saveSnapshot('CurrentPicture.jpeg', 0, 0, 'tl')
pic = Image.open("CurrentPicture.jpeg")
(rgb_red, rgb_green, rgb_blue) = pic.getpixel((0, 0))
os.remove("C:\Python27\CurrentPicture.jpeg")
Are there any issues with IDLE for running multiple lines and just not working, I am not terribly sure what I should be asking. It is just that nothing happens when I run that entire block together but line by line entering works.
-Any help is greatly appreciated.
Instead if pasting the code into IDLE, save it into a file, and run it like this:
python yourfile.py
while 0 == 0: You might want while True: instead.
red = Image.open("Red.jpeg")
(redr, redg, redb) = red.getpixel((0, 0)) is a very complex way of saying RED = (255, 0, 0)