how to make the program find an image with pyautogui? - python

In the code below as you can see i'm trying to find an image in the screen with a .png(that i didn't add because i don't think it's the problem) but it doesn't find anything
import pyautogui as pt
from time import sleep
class Clicker:
def __init__(self, target_png, speed):
self.target_png = target_png
self.speed = speed
pt.FAILSAFE = True
def nav_to_image(self):
try:
position = pt.locateOnScreen(self.target_png, confidence=.8)
pt.moveTo(position[0] + 15, position[1] + 15, duration=self.speed)
pt.doubleClick()
except:
print('No img found')
return 0
if __name__=='__main__':
sleep(1)
clicker = Clicker('accetta.png', speed=.001)
end = 0
while True:
sleep(1)
if clicker.nav_to_image() == 00:
end += 1
if end > 5:
break

I see that you confidence is set to 80%. It's a little tricky when you're not looking for the exact match. Have you tested the code with an image that doesn't require confidence to work?
Sometimes there is a difference in the hue. Try locateOnScreen(image, grayscale=False) and see if that makes a difference.
It would help if you included both the image you're trying to find and a copy of the screenshot in order to reproduce the error.

Related

CCXT solving connection errors

I'm getting the following error when I run my code:
I'm guessing the root of this error is when I execute the fetch_ticker() function.
I have two python scripts: main.py and functions.py (includes all the functions)
I've read somewhere else that strategically adding a time.sleep(0.01) can solve the issue.
Would it be wise to add time.sleep(0.01) before any line that requests something through BinanceUS API?
For example,
if now.hour == 0 and now.minute == 0 and (0 <= now.second < 10):
time.sleep(0.01)
target = calc_target(binanceUS, symbol)
time.sleep(0.01)
balance = binanceUS.fetch_balance()
time.sleep(0.01)
usd = balance['total']['USD']
op_mode = True
time.sleep(10)
Though I'm not sure if this will solve the issue...or I also thought about creating an error-handling code for all the functions that I use, but I'm not sure how I would go about it when the function includes one or more if-statements. For example,
def enter_position(exchange, symbol, cur_price, target, amount, position):
try_cnt = 3
while try_cnt > 0:
if cur_price > target:
try:
position['type'] = 'long'
position['amount'] = amount
exchange.create_market_buy_order(symbol=symbol, amount=amount)
except Exception as e:
print("Connection error, trying again...")
try_cnt -= 1
time.sleep(1)
else:
exchange.create_market_buy_order(symbol=symbol, amount=amount)
Not sure if this will work, though.
I'm very confused about how to go around this error. In fact, I'm not even sure what the error means. Would any of the two solutions look plausible?

how to make locateCenterOnScreen more accurate -PYTHON-, -WINDOWS-

Hello my goal is to be able to make my bot click the thing of my choosing on any screen size because I think that is the main issue. Ive tried to decrease the confidence level but it just ends up clicking something else with the same general color. ive tested it with an EXACT image and it clicks the correct spot so its not like the coordinates are off or anything its just the image recognition.
These are the images to go by
(X1, NextLesson, Arrow)
from pyautogui import *
import pyautogui
import time
import keyboard
import random
def NextLesson():
keepGoing = True
while keepGoing == True:
counter = 0
nl_coordinates = pyautogui.locateOnScreen('images/nextLesson.png', confidence=0.4)
print(nl_coordinates) # This will print out where it is
if nl_coordinates:
print(f"I can see it at {nl_coordinates}")
pyautogui.click(nl_coordinates)
keepGoing = False
else:
print("I cannot see it.")
def Arrow():
keepGoing = True
while keepGoing == True:
counter = 0
arrow_coordinates = pyautogui.locateOnScreen('images/arrow.png', confidence=0.4)
print(arrow_coordinates) # This will print out where it is
if arrow_coordinates:
print(f"I can see it at {arrow_coordinates}")
pyautogui.click(arrow_coordinates)
keepGoing = False
else:
print("I cannot see it.")
def X1():
keepGoing = True
while keepGoing == True:
counter = 0
x1_coordinates = pyautogui.locateOnScreen('images/x1.png', confidence=0.4)
print(x1_coordinates) # This will print out where it is
if x1_coordinates:
print(f"I can see it at {x1_coordinates}")
pyautogui.click(x1_coordinates)
keepGoing = False
else:
print("I cannot see it.")
while True:
counter = 0
counter2 = 0
true = True
time.sleep(2)
X1()#
time.sleep(8)
NextLesson()#
time.sleep(10)
Arrow()#
print("calibration complete ")
time.sleep(5)
cords = pyautogui.position()
while counter != 1800:
time.sleep(60)
pyautogui.click(cords) #clicking where ouse is at
print("clicked")
counter += 60
print(counter)
if counter == 1800:
time.sleep(5) #stops code for 5 secs
X1() #clicks mouse to x button
print("clicked x")
time.sleep(5) #stops code for 5 secs
NextLesson() #clicks mouse to the assignment button
print("clicked assignemnt")
time.sleep(15) #stops code for 2 secs
Arrow() #clicks mouse to the second assignment button
print("clicked 2nd assignment button ")
time.sleep(5) #waits 5secs to put cursor at position
cords = pyautogui.position() #grabs position
print("grabbed position")
We can use opencv-python to perform multiscale template matching. The idea is to scale the template image and attempt to locate the resized template in the screenshot. The code below (adapted from here) loops over 50 scaling parameters in the range [0.25,2] and selects the one the that provides the best match. You might want to decrease the range or number of scaling parameters for efficiency. It is also better to save the correct scaling parameter and reuse it for multiple images.
import cv2
import pyscreeze
import numpy as np
import imutils
import pyautogui
def template_match_with_scaling(image,gs=True,confidence=0.8):
"""
Locate an image and return a pyscreeze box surrounding it.
Template matching is done by default in grayscale (gs=True)
Detect image if normalized correlation coefficient is > confidence (0.8 is default)
"""
templateim = pyscreeze._load_cv2(image,grayscale=gs) # template image
(tH, tW) = templateim.shape[:2]
screenim_color = pyautogui.screenshot() # screenshot of image
screenim_color = cv2.cvtColor(np.array(screenim_color),cv2.COLOR_RGB2BGR)
if gs is True:
screenim = cv2.cvtColor(np.array(screenim_color),cv2.COLOR_BGR2GRAY)
else:
screenim = screenim_color
#try different scaling parameters and see which one matches best
found = None #bookeeping variable for the maximum correlation coefficient, position and scale
scalingrange = np.linspace(0.25,2,num=50)
for scale in scalingrange:
resizedtemplate = imutils.resize(templateim, width = int(templateim.shape[1]*scale) ) # resizing with imutils maintains the aspect ratio
r = float(resizedtemplate.shape[1])/templateim.shape[1] # recompute scaling factor
result = cv2.matchTemplate(screenim, resizedtemplate, cv2.TM_CCOEFF_NORMED) # template matching using the correlation coefficient
(_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) #returns a 4-tuple which includes the minimum correlation value, the maximum correlation value, the (x, y)-coordinate of the minimum value, and the (x, y)-coordinate of the maximum value
if found is None or maxVal > found[0]:
found = (maxVal, maxLoc, r)
(maxVal, maxLoc, r) = found
if maxVal > confidence:
box = pyscreeze.Box(int(maxLoc[0]), int(maxLoc[1]), int(tW*r), int(tH*r) )
return box
else:
return None
def locate_center_with_scaling(image,gs=True):
loc = template_match_with_scaling(image,gs=gs)
if loc:
return pyautogui.center(loc)
else:
raise Exception("Image not found")
#sample usage
coords = locate_center_with_scaling('images/arrow.png')
The answer I found is taking a more accurate photo of what I need like trying to remove the background as much greyscale=ture and adding more confidence

In Python how would one wait a specific time while waiting for an image to possibly occur?

More specifically, I have a Sikuli code that works fine for the most part. However, during my 5400 second wait sometimes I have a network connection error that pops a button on the screen I need to click that occurs at no specific time during those 5400 seconds. Also, if that network button occurs and I click it I need to start the code over from the beginning.
I assume I can do a nested While loop waiting for that network connection button to pop up and if it doesn't occur continue with the code but how would I write that? Here's the code currently:
while True:
exists("start.png", 10*60)
click(Pattern("start.png").targetOffset(-1,0))
wait("enter.png", 5)
click(Pattern("enter.png").targetOffset(2,30), 5)
wait(5400)
type(Key.ESC)
exists("leave.png", 5)
click(Pattern("leave.png").targetOffset(-11,0))
#the following if statements could or could not occur and could come in no specific order. This part of the code could be incorrect
if exists("close1.png", 5):
click(Pattern("close1.png").targetOffset(0,1))
elif exists("close2.png", 20):
click("close2.png")
elif exists("close3.png", 20):
click("close3.png")
wait(5)
A suggestion from RaiMan from SikuliX (not tested ;-)
"""
#the following if statements could or could not occur and could come in no specific order.
#This part of the code could be incorrect
if exists("close1.png", 5):
click(Pattern("close1.png").targetOffset(0,1))
elif exists("close2.png", 20):
click("close2.png")
elif exists("close3.png", 20):
click("close3.png")
"""
netError = False
def handler(event):
global netError
netError = True
click(event.getMatch())
onAppear("close1.png", handler)
onAppear("close2.png", handler)
onAppear("close3.png", handler)
while True:
netError = False
observeInBackground(FOREVER)
#exists("start.png", 10*60)
#click(Pattern("start.png").targetOffset(-1,0))
click(wait("start.png", 1))
#wait("enter.png", 5)
#click(Pattern("enter.png").targetOffset(2,30), 5)
click(wait(Pattern("enter.png").targetOffset(2,30), 5)
towait = 5400
while not netError and toWait > 0:
wait(1)
towait -= 1
if netError:
stopObserver()
continue
type(Key.ESC)
#exists("leave.png", 5)
#click(Pattern("leave.png").targetOffset(-11,0))
click(wait(Pattern("leave.png").targetOffset(-11,0), 5)
stopObserver()
wait(5)
Here is some alternative without observer events. I personally find it simpler to work in this way :-).
I used your original code and just replaced wait(5400) with a time based loop that checks for images that might occur.
import time
while True:
exists("start.png", 10*60)
click(Pattern("start.png").targetOffset(-1,0))
wait("enter.png", 5)
click(Pattern("enter.png").targetOffset(2,30), 5)
t0 = time.time()
while (time.time()-t0 < 5400):
#the following if statements could or could not occur and could come in no specific order. This part of the code could be incorrect
if exists("close1.png", 5):
click(Pattern("close1.png").targetOffset(0,1))
elif exists("close2.png", 20):
click("close2.png")
elif exists("close3.png", 20):
click("close3.png")
type(Key.ESC)
exists("leave.png", 5)
click(Pattern("leave.png").targetOffset(-11,0))
wait(5)

What are valid appJar stretch function arguments

So far I've been attempting to create a 2 factor authentication script in python. It works very well now and I wanted to create a gui since this will be running nearly 24/7 on a raspberry pi.
TLDR; I don't understand what the docs mean by "stretch. Pass a string describing if rows/columns should stretch, to fill the entire GUI. "
#!/usr/bin/env python
import pyotp
import os
import sys
import math
import time
from appJar import gui
udstart = 1
app = gui("2FA Keys","480x320")
def count(n):
while n >= 0:
time.sleep(1)
n -= 1
if n == 0:
return 1
#Keygenertor function pass the base32 code
def keyGen(secret):
secretcalc = pyotp.TOTP(secret)
code = secretcalc.now()
Lcode = list(code)
Lcode.insert(3, " ")
Ocode = ''.join(Lcode)
return Ocode
#INIT CODES GO HERE
CoinbaseCode = keyGen("3JCAJVDGIW4KHUHL")
SiaCoinCode = keyGen("PFFO3KKKRQL6ACU5")
app.stretch(columns)
app.setFont(50)
app.addLabel("l2", "Sia Coin: " + SiaCoinCode, 0,0,0,0)
app.setLabelbg("l2", "blue")
app.addLabel("l1", "Coinbase: " + CoinbaseCode, 1,0,0,0) #Coinbase 2FA
app.setLabelBg("l1", "red")
while True:
if udstart == 1:
break
else:
time.sleep(30)
break
def update():
#UPDATE CODES GO HERE
CoinbaseCode = keyGen("3JCAJVDGIW4KHUHL") #Coinbase
SiaCoinCode = keyGen("PFFO3KKKRQL6ACU5")
app.setLabel("l2", "Sia Coin: " + SiaCoinCode)
app.setLabelBg("l2", "blue")
app.setLabel("l1", "Coinbase: " + CoinbaseCode)
app.setLabelBg("l1", "red")
#profit???
udstart = 0
app.registerEvent(update)
app.go()
I have no idea what to pass it.
If you look at the appJar source code on GitHub, you can identify what you should pass for stretch:
Looking at how strech is used:
def setStretch(self, exp):
self.setExpand(exp)
...
stretch = property(getStretch, setStretch)
Looking at the source for the setExpand we see the possible values for strech:
def setExpand(self, exp):
if exp.lower() == "none":
self.containerStack[-1]['expand'] = "NONE"
elif exp.lower() == "row":
self.containerStack[-1]['expand'] = "ROW"
elif exp.lower() == "column":
self.containerStack[-1]['expand'] = "COLUMN"
else:
self.containerStack[-1]['expand'] = "ALL"
As a result, the possible strings are (case insensitive) "None", "Row", "Column", or anything else (which will result in "ALL").
It's also documented here: http://appjar.info/pythonWidgetLayout/#set-stretch-sticky
none, row, column, both

I have an error in python with tkinter and need help(school project)

I have to create a little text adventure for school in python.
To detect keyboard inputs I decided to use tkinter and disable the window.
All is working fine but if I try to calculate with a variable after a key was pressed, I get the following error...This is the error message
This is the script I am using(I don't have much experience with python...)
import os
import sys
import tkinter
menueeintraege = ["Start", "Steuerung", "Credits", "Beenden"]
index = 0
def menueaufbauen():
os.system("cls")
print("Menue")
print("")
print("")
for i in range(4):
if i == index:
print(menueeintraege[i] + "<")
else:
print(menueeintraege[i])
menueaufbauen()
def startgame():
os.system("game.py");
def steuerung():
os.system("cls")
print("Steuerung")
print("")
print("Norden = Pfeiltaste Hoch")
print("Sueden = Pfeiltaste Runter")
print("Osten = Pfeiltaste Rechts")
print("Westen = Pfeiltaste Links")
print("Bestaetigen = Enter")
def credits():
os.system("cls")
print("Credits")
print("")
print("Jannik Nickel")
print("Thomas Kraus")
print("")
def exitgame():
sys.exit()
def menueauswahl(taste):
print(taste)
if taste == "Up":
if index > 0:
index -= 1
print(index)
elif taste == "Down":
if index < 3:
index += 1
menueaufbau()
def tasteneingabe(event):
tastenname = event.keysym
menueauswahl(tastenname)
fenster = tkinter.Tk()
fenster.bind_all('<Key>', tasteneingabe)
fenster.withdraw()
fenster.mainloop()
I think the mistake have to be in the last part of the script, I hope someone here knows a solution because it's really important for school.
Thanks for any help
(I'm using Visual Studio 2015)
Okay so I caught a couple of errors. The first is that you are referencing a global variable (index) inside of a function. To do that, you need to tell python that you are using a global variable.
def menueauswahl(taste):
global index
print(taste)
And also you need to change the function name in line 61 to menuaufbauen().

Categories

Resources