I have a red pixeled image and i wanted another image to be blitted at the red pixel, so I did this code:
import sys, pygame
pygame.init()
from pygame.locals import *
import time
#the function with get at
def colorscan(rect):
red = ( 255 , 0 , 0 , 255 )
for x in range(rect[0],rect[0]+rect[2]+1):
for y in range(rect[1],rect[1]+rect[3]+1):
print(x,y)
if tuple(screen.get_at((x,y)))==red:
print(x,y,"done")
return (x,y)
def load(path):
x = pygame.image.load(path)
return x
beam = load("menu/beam.png")
w_plat = load("menu/w_plat.png")
videoinfo = pygame.display.Info()
fullscreen = pygame.FULLSCREEN
screen = pygame.display.set_mode((videoinfo.current_w,videoinfo.current_h), fullscreen, 32)
time = pygame.time.Clock()
#main loop
while True:
beamrect = screen.blit(beam,(0,0))
xtl,ytl=beamrect.topleft
w_pos=colorscan( (xtl,ytl,35,+35) )
screen.blit(w_plat, w_pos)
my code is too large so i just wrote here what's important. Anyways, when i run it I get this error:
Traceback (most recent call last):
File "C:\Users\André Luiz\Desktop\Equilibrium\Equilibrium.py", line 171, in
screen.blit(w_plat, w_pos)
TypeError: invalid destination position for blit
after checking, printing w_pos returned "None", but I'm sure the red pixel has been ""scanned"".
I think what happens is that either your for loops are broken
for x in range(rect[0],rect[0]+rect[2]+1):
for y in range(rect[1],rect[1]+rect[3]+1):
by not executing, or the if statement is not executed because its conditions are not met:
if tuple(screen.get_at((x,y)))==red: (eg: not executed if != red)
because it's the only location you return a value. Otherwise when a function is not specified a return value, it returns None.
colorscan() has no default return value, this is why you get a None.
Related
I cant blit images in normal speed if the images in array.
#brife review
In my code i defined 10 images as a variable(x1-x10)
those 100 images relevant for specific class (object.draw_function()), and will be bliting in main loop according specific condtions.
in the object.draw_function() all the images are saved in lst "images_lst" = [img1,img2,img3,,,,img10]
and bliting from that array according rulles.
i noticed that if the len of the array is higher then 4,5 , the loop FPS is slower. and i dont understand why ? the loading images is outside the loop.
Code example:
#loading images
img1 = pygame.image.load(r'images\game_background1\img1.jpg')
img2 = pygame.image.load(r'images\game_background1\img2.jpg')
img3 = pygame.image.load(r'images\game_background1\img3.jpg')
'
'
'
img10= pygame.image.load(r'images\game_background1\img10.png')
#define font and space size
space_width,space_height = pysical_tm_img.get_width(),pysical_tm_img.get_height()
font0_0 = pygame.font.SysFont(pygame.font.get_fonts()[0],12)
font0_02 = pygame.font.SysFont(pygame.font.get_fonts()[0],17)
# define class
class EXAMPLE():
def __init__(self,x,y,text,power,energy,range):
self.rect = pygame.Rect(x,y,100,10)
self.text = text
self.power = power
self.energy = energy
self.range = range
def draw_func(self,surface):
img_lst = [img1,text1,img2,text2,img3,text3......img10,text10]
for i,img in enumerate(img_lst):
if i % 2 == 0 :
img_rect = img.get_rect(center=(self.rect.x +20 + (i *space_width*2),self.rect.top + space_height))
surface.blit(img,img_rect)
else:
img_rect = img.get_rect(center=(self.rect.x +20 + space_width + ((i-1) *space_width*2),self.rect.top + space_height))
surface.blit(img,img_rect)
#main loop
while True:
if somthing:
object1 = EXAMPLE(10,10,"abc",100,50,10)
object1.draw_func(screen)
elif somthing else:
object3 = EXAMPLE(10,10,"abc",100,50,10)
object3.draw_func(screen)
pygame.display.update()
clock.tick(60)
I dont understand whats wrong and why i cant append more images to my images list without reducing runtime.
Another question that not much relevant to this code but rellevant to runtime. if this code without the main loop is in file number 1 and in this file i import pygame and init the font only.
pygame.font.init()
and in file num 2 where the main loop is running i import pygame and init pygame
pygame.init()
is it reduce my proggram runtime?
Ensure that the image Surface has the same format as the display Surface. Use convert() (or convert_alpha()) to create a Surface that has the same pixel format. This improves performance when the image is blit on the display, because the formats are compatible and blit does not need to perform an implicit transformation.
e.g.:
img1 = pygame.image.load(r'images\game_background1\img1.jpg').convert()
I am new here and also in python (^_^')
I have a question about my code.
This is an infinite loop, when my code finds a red pixel in a saved screenshot send me a message, it works if there is a red pixel, but if I try to test another red pixel or delete the last red pixel detected and then re-use it, my code stops working with this error:
Warning (from warnings module):
File "C:\Users\Desktop\DCN.py", line 126
comparison_dcn = check_dcn == control_dcn
DeprecationWarning: elementwise comparison failed; this will raise an error in the future.
Traceback (most recent call last):
File "C:\Users\Desktop\DCN.py", line 127, in <module>
equal_dcn= comparison_dcn.all()
AttributeError: 'bool' object has no attribute 'all'
My idea was to create a numpy array to save the coordinates (x,y) and check if already exist inside this array, it must not detect it to me two times...
I tried to figure out the problem, but it is too early for my python experience....
I hope my english is understandable XD
Can someone kindly help me with my code and explain my issue?
#libaries
import mss
import mss.tools
from PIL import image
import psutil
import time
import cv2
import numpy as np
#global variables
loop = 1
check_dcn = np.column_stack((0,0))
counter_dcn = 0
while loop == 1 :
#detect red pixel
def detect_color(rgb, filename):
img = Image.open(filename)
img = img.convert('RGBA')
data = img.getdata()
for item in data:
if item[0] == rgb[0] and item[1] == rgb[1] and item[2] == rgb[2]:
return True
return False
with mss.mss() as sct:
# The screen part to capture
monitor = {"top": 190, "left": 0, "width": 1920, "height": 840}
output = "example.png".format(**monitor)
# Grab the data
sct_img = sct.grab(monitor)
# Save to the picture file
mss.tools.to_png(sct_img.rgb, sct_img.size, output=output)
print (detect_color((255,102,102), 'example.png')) #dcn red pixel
#dcn alarm detected
if detect_color((255,102,102), 'example.png'):
pixel_img = cv2.imread('example.png')
pop = [102,102,255] #BGR order
X,Y = np.where(np.all(pixel_img == pop, axis = 2)) #coordinates
control_dcn = np.column_stack((X,Y)) #assign coordinates
print(control_dcn) #test
if counter_dcn == 0:
counter_dcn = 1
check_dcn = control_dcn
print("first round dcn") #test
print(check_dcn) #test
###looking for solution here to empty comparison_dcn
comparison_dcn = check_dcn == control_dcn
equal_dcn= comparison_dcn.all()
if equal_dcn:
print("red pixel alread reported,waiting 20 seconds") #test
time.sleep(20)
else:
check_dcn = np.column_stack(X,Y)
print("red pixel added,waiting 5 seconds") #test
print(check_dcn) #test
time.sleep(5)
else:
print("Nothing, waiting 10 seconds")
time.sleep(10)
I have been trying to understand the error reported when I run an example supplied with some hardware i purchased.
I have tried googling around but every answer I get is a bit beyond my comprehension. I think what is going wrong is that the script, or one of the imported scripts is written for Python 2 and i am trying to run it in python 3.
When I try and run it in Python 2 i get a whole host of other problems so I have been trying to make it work with 3.
The hardware I purchased is the Enviro+ sensor suite for the raspberry pi sold by Pimoroni
Hardware Link
Github Library
Pimoroni Tutorial
#!/usr/bin/env python
import time
import colorsys
import os
import sys
import ST7735
import ltr559
from bme280 import BME280
from pms5003 import PMS5003
from enviroplus import gas
from subprocess import PIPE, Popen
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
print("""all-in-one.py - Displays readings from all of Enviro plus' sensors
Press Ctrl+C to exit!
""")
# BME280 temperature/pressure/humidity sensor
bme280 = BME280()
# PMS5003 particulate sensor
pms5003 = PMS5003()
# Create ST7735 LCD display class
st7735 = ST7735.ST7735(
port=0,
cs=1,
dc=9,
backlight=12,
rotation=270,
spi_speed_hz=10000000
)
# Initialize display
st7735.begin()
WIDTH = st7735.width
HEIGHT = st7735.height
# Set up canvas and font
img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))
draw = ImageDraw.Draw(img)
path = os.path.dirname(os.path.realpath(__file__))
font = ImageFont.truetype(path + "/fonts/Asap/Asap-Bold.ttf", 20)
message = ""
# The position of the top bar
top_pos = 25
# Displays data and text on the 0.96" LCD
def display_text(variable, data, unit):
# Maintain length of list
values[variable] = values[variable][1:] + [data]
# Scale the values for the variable between 0 and 1
colours = [(v - min(values[variable]) + 1) / (max(values[variable])
- min(values[variable]) + 1) for v in values[variable]]
# Format the variable name and value
message = "{}: {:.1f} {}".format(variable[:4], data, unit)
print(message)
draw.rectangle((0, 0, WIDTH, HEIGHT), (255, 255, 255))
for i in range(len(colours)):
# Convert the values to colours from red to blue
colour = (1.0 - colours[i]) * 0.6
r, g, b = [int(x * 255.0) for x in colorsys.hsv_to_rgb(colour,
1.0, 1.0)]
# Draw a 1-pixel wide rectangle of colour
draw.rectangle((i, top_pos, i+1, HEIGHT), (r, g, b))
# Draw a line graph in black
line_y = HEIGHT - (top_pos + (colours[i] * (HEIGHT - top_pos)))\
+ top_pos
draw.rectangle((i, line_y, i+1, line_y+1), (0, 0, 0))
# Write the text at the top in black
draw.text((0, 0), message, font=font, fill=(0, 0, 0))
st7735.display(img)
# Get the temperature of the CPU for compensation
def get_cpu_temperature():
process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE)
output, _error = process.communicate()
return float(output[output.index('=') + 1:output.rindex("'")])
# Tuning factor for compensation. Decrease this number to adjust the
# temperature down, and increase to adjust up
factor = 0.8
cpu_temps = [0] * 5
delay = 0.5 # Debounce the proximity tap
mode = 0 # The starting mode
last_page = 0
light = 1
# Create a values dict to store the data
variables = ["temperature",
"pressure",
"humidity",
"light",
"oxidised",
"reduced",
"nh3",
"pm1",
"pm25",
"pm10"]
values = {}
for v in variables:
values[v] = [1] * WIDTH
# The main loop
try:
while True:
proximity = ltr559.get_proximity()
# If the proximity crosses the threshold, toggle the mode
if proximity > 1500 and time.time() - last_page > delay:
mode += 1
mode %= len(variables)
last_page = time.time()
# One mode for each variable
if mode == 0:
variable = "temperature"
unit = "C"
cpu_temp = get_cpu_temperature()
# Smooth out with some averaging to decrease jitter
cpu_temps = cpu_temps[1:] + [cpu_temp]
avg_cpu_temp = sum(cpu_temps) / float(len(cpu_temps))
raw_temp = bme280.get_temperature()
data = raw_temp - ((avg_cpu_temp - raw_temp) / factor)
display_text(variable, data, unit)
if mode == 1:
variable = "pressure"
unit = "hPa"
data = bme280.get_pressure()
display_text(variable, data, unit)
if mode == 2:
variable = "humidity"
unit = "%"
data = bme280.get_humidity()
display_text(variable, data, unit)
if mode == 3:
variable = "light"
unit = "Lux"
if proximity < 10:
data = ltr559.get_lux()
else:
data = 1
display_text(variable, data, unit)
if mode == 4:
variable = "oxidised"
unit = "kO"
data = gas.read_all()
data = data.oxidising / 1000
display_text(variable, data, unit)
if mode == 5:
variable = "reduced"
unit = "kO"
data = gas.read_all()
data = data.reducing / 1000
display_text(variable, data, unit)
if mode == 6:
variable = "nh3"
unit = "kO"
data = gas.read_all()
data = data.nh3 / 1000
display_text(variable, data, unit)
if mode == 7:
variable = "pm1"
unit = "ug/m3"
data = pms5003.read()
data = data.pm_ug_per_m3(1.0)
display_text(variable, data, unit)
if mode == 8:
variable = "pm25"
unit = "ug/m3"
data = pms5003.read()
data = data.pm_ug_per_m3(2.5)
display_text(variable, data, unit)
if mode == 9:
variable = "pm10"
unit = "ug/m3"
data = pms5003.read()
data = data.pm_ug_per_m3(10)
display_text(variable, data, unit)
# Exit cleanly
except KeyboardInterrupt:
sys.exit(0)
When I try and run the code i get the following results:
Traceback (most recent call last):
File "all-in-one.py", line 135, in <module>
cpu_temp = get_cpu_temperature()
File "all-in-one.py", line 89, in get_cpu_temperature
return float(output[output.index('=') + 1:output.rindex("'")])
TypeError: argument should be integer or bytes-like object, not 'str'
Please forgive me if I have not filled this help request out correctly - i am very new to forums (I hardly ever post in them, although i read them a lot for help), and i am also very new to Python and Linux.
Any help and support from the community would be massively appreciated - thank you in advance...
SW
According to Python 3 whitepages on subprocess.communicate(), the type of output and _error can be either strings (what you want) OR bytes. If you were getting strings back, you wouldn't have this problem, but the TypeError message you're getting is exactly what you get when you try to call index() on a bytes object with a string argument.
Demonstrably:
>>> output = "temperature = '88 C'".encode('utf-8') #this is of type bytes
>>> output
b"temperature = '88 C'"
>>> output.index('=')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument should be integer or bytes-like object, not 'str'
>>> output.index(ord('='))
12
So you should replace output.index('=') with output.index(ord('=')) and output.rindex("'") with output.rindex(ord("'")).
EDIT
I realized this much later, but you can circumvent using ord() by prepending your search string with a b.
output.index(b'=')
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'm new to python and I'm getting an invalid syntax(see error below)I'm suck with this error....help? I am writing code to build a house in 4 clicks. A lot of the code below is my trying different things so just ignore it(or give me suggestions with what I should do) It's the p2 error that has me stumped.
<using graphics.py>
import graphics
from graphics import*
def house():
win=GraphWin(800,500)
win.setCoords(0.0,0.0,4.0,4.0)#reset coordinates
Text(Point(2.0,3.5),"click spot to designate 2 corners of house").draw(win)
p1=win.getMouse()
p1.draw(win)
side1=(Point(p1.getX(),(p1.getY()))
p2=win.getMouse()<----------------------------ERROR with the p2
p2.draw(win)
side2=(Point(p2.getX(),(p2.getY()))
rect = Rectangle(side1,side2)
rect.draw(win)
#door- p3=center top edge of door
msg2 = Text(Point(2.0,0.5),"click to designate top of door")
msg2.draw(win)
p3=win.getMouse()
p3.draw(win)
#golden:)
Line(Point(p3.getX(),(p3.getY())),(Point(p2.getX()),(p2.getY()))).draw(win)
"""
p3 = dwidth.getCenter()
rectWidth = (p2.getX()) - (p1.getX())
#doorWidth = door.setWidth(distance/5.0)#width 1/5 of house
dwidth= eval((rectWidth) / (5))
dheight=((getP3(),(getP2()))#height = from top corners to bottom of the frame
#door = Rectangle((dwidth) * (dheight))"""
#door.draw(win)
"""#Window
message3 = Text(Point(2.0, 1.0),"click to designate center of square window").draw(win)
p4=win.getMouse()
p4.draw(win)
c=door.getCenter()
dx=p4.getX()-c.getX()
dy=p4.getY()-c.getY()
window = Rectangle(Point(dx,dx),Point(dy,dy))
window.draw(win)
#window side = half of door with
#roof top = half way btwn l and r edges
#house height = half height of house frame
#win.getMouse()
#win.close
"""
#window one forth of the door
#window = Rectangle(p4)
#window.setWidth(doorwidth/ 4.0)
#window.draw(win)
house()
>>> ================================ RESTART ================================
>>>
Traceback (most recent call last):
File "E:\ICS 140\ass 8.py", line 57, in <module>
house()
File "E:\ICS 140\ass 8.py", line 28, in house
Line(Point(p3.getX()),(p3.getY()),(Point(p2.getX()),(p2.getY()))).draw(win)
TypeError: __init__() missing 1 required positional argument: 'y'
>>>
The error happens because a Point needs an x and a y argument, but you are only passing an x in the line where you try to create a Rectangle.
Not exactly sure what your code is trying to do, but hopefully this will help get you started in the right direction:
from graphics import *
def house():
win=GraphWin(800,500)
win.setCoords(0.0,0.0,3.0,4.0)#reset coordinates
Text(Point(1.5,3.5),"click spot to designate 2 corners of house").draw(win)
p1 = win.getMouse()
p1.draw(win)
p2 = win.getMouse()
p2.draw(win)
rectangle = Rectangle(p1, p2)
rectangle.setWidth(3)
rectangle.draw(win)
win.getMouse()
win.close()
house()