open cv python drawing with the mouse - python

I keep getting an invalid syntax error with this. So, how can I resolve this and where can I find related documentation in the future.
import cv2
import numpy as np
drawing = False # true if mouse is pressed
mode = True # if True, draw rectangle. Press 'm' to toggle to curve
ix,iy = -1,-1
class DessinerLigne:
def dessinerLigne(self):
# Create a black image
self.img=np.zeros((512,512,3),np.uint8)
def draw_circle(event,x,y,flags,param):
global ix,iy,drawing,mode
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
if mode == True:
cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
else:
cv2.circle(img,(x,y),5,(0,0,255),-1)
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
if mode == True:
cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
else:
cv2.circle(img,(x,y),5,(0,0,255),-
img = np.zeros((512,512,3), np.uint8)
cv2.imshow("Image", self.img)
# If q is pressed then exit program
self.k=cv2.waitKey(0)
if self.k==ord('q'):
cv2.destroyAllWindows()
if __name__=="__main__":
DL=DessinerLigne()
DL.dessinerLigne()

There clearly are multiple issues with this script. Ones that need immediate attention are:
There's an indentation error in the definition of dessinerLigne class.
Change:
class DessinerLigne:
def dessinerLigne(self):
# Create a black image
self.img=np.zeros((512,512,3),np.uint8)
to:
class DessinerLigne:
def dessinerLigne(self):
# Create a black image
self.img=np.zeros((512,512,3),np.uint8)
and the indentation error should be fixed.
There's an incomplete line of code in line 32.
Is line 33 a part of the method draw_circle()? If so, it has be properly indented. Add 4 whitespaces in front of it.
You seem to have pasted the code from somewhere. During this process, it is very likely that some invisible control characters that might break the syntax may have arrived. Use an editor that has 'show invisible' features to resolve this issue.

Related

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

Python function works fine except when imported

I've tried to distill this to the essentials. This code works fine.
from evdev import InputDevice, ecodes
dev = InputDevice('/dev/input/event2') # this is the joystick event file
button = {304: 'A', 305: 'B', 307: 'X', 308: 'Y' } # Xbox360 button mappings
exit = False
def joystick(dev):
try:
for event in list(dev.read()):
if button[event.code] == 'A' and event.value == 1:
print('Button A pressed.')
if button[event.code] == 'X' and event.value == 1:
print('Button X pressed.')
return True
except: pass
return False
while exit == False:
exit = joystick(dev)
However, if I move the joystick function to a separate file (including the proper evdev import) and import it the code breaks (function "joystick" will always return false, not recognizing joystick events).
Any ideas why? I know the software/hardware interface can be tricky but this is ridiculous.
Found the bug. When I moved the joystick function outside of the file I neglected to port the button dictionary with it. The try statement masked the error I normally would have gotten by omitting the dictionary.

Python ImageGrab Not Working With Input

In my program, I'm taking a screenshot of a part of my screen, which works. But when I add anything in front of calling the function it's in, it no longer gets past the ImageGrab part.
This works:
def takePictures():
print("3")
if __name__ == '__main__':
print("1")
im = ImageGrab.grab(bbox=(760, 250, 1160, 680)) # X1,Y1,X2,Y2
print("2")
im.save('ALL.png')
#im.show()
takePictures()
This doesn't:
def takePictures():
print("3")
if __name__ == '__main__':
print("1")
im = ImageGrab.grab(bbox=(760, 250, 1160, 680)) # X1,Y1,X2,Y2
#^^^ Doesnt get past this line
print("2")
im.save('ALL.png')
#im.show()
if input() == "":
takePictures()
I've also tried it with inputs from keys on a different window and it's the same.
Your program will pause at
if input() == "":
takePictures()
until you activate the python executing window and hit the enter key.
If you want to take screen shots, you can use, say
time.sleep(10)
giving yourself 10 seconds to activate the window you want to take a screen shot of.

Python curses menu not working [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Trying to get a really basic curses menu to work. I've been following a tutorial but I've kinda split off to doing my own thing. I tried to touch on everything with comments. I just want to figure out how to get the selections to work.
import sys
import curses
import time
def menu(window, dims):
window.nodelay(0) # not sure what this does, lol
window.clear() # clear window
selection = -1 # the menu code is from the tutorial
option = 0 # so most of this is foreign to me
while selection < 0: # loop
graphics = [0]*2 # point to list
graphics[option] = curses.A_REVERSE # set graphic, reverse BKGND color
window.border() # border
window.addstr(1, dims[1]/2-2, "Menu")
window.addstr(3, dims[1]/2-2, "Play", graphics[0])
window.addstr(4, dims[1]/2-2, "Exit", graphics[1])
window.refresh() # refresh the window
action = window.getch() # get input
if action == curses.KEY_UP: # if key is up
option = (option - 1) # go up?
elif action == curses.KEY_DOWN: # key is down
option = (option + 1) # go down?
elif action == ord('\n'): # if RETURN
selection = option # make selection
window.clear() # clear all
if selection == 0: # if is 0, do nothing right now.
return # it's not changing selection
elif selection == 1: # so waiting for that to add here
return
def main(): # main function // ran first
window = curses.initscr() # making new window
dims = window.getmaxyx() # getting window dimensions
if not curses.has_colors(): # color test
curses.endwin() # color test
print "no colors" # color test
sys.exit() # color test
else: # color test
curses.start_color() # color test
curses.noecho() # don't echo the keys on the screen
curses.cbreak() # don't wait enter for input
curses.curs_set(0) # don't show cursor
main_loop(window, dims) # go into main loop
def main_loop(window, dims):
while menu(window, dims):
pass
window.clear()
window.addstr(dims[0]/2, (dims[1]-4)/2, "Exiting...")
window.refresh()
time.sleep(1)
curses.noecho()
curses.cbreak()
curses.curs_set(1)
curses.endwin()
if __name__ == '__main__':
main()
I was missing window.keypad(1) to actually activate the input.
I added it just before the main_loop().

TypeError: argument 1 must be pygame.Surface, not builtin_function_or_method (python 3.2.3)

Okay, so I'm using pygame to create a program, however, when I try to create my rectangle tool, it seems to always display TypeError: argument 1 must be pygame.Surface, not builtin_function_or_method. I'm not sure why, because I asked a peer about it, and it worked perfectly fine, with the same code.
from pygame import *
from random import *
screen = display.set_mode((1152,864))
start = 0,0
color = (0,0,0)
canvasRect = Rect(150,160,850,700)
recttoolRect = Rect(20,350,40,40)
draw.rect(screen,(255,255,255),canvasRect)
running = True
while running:
finish = False
for e in event.get():
if e.type == QUIT:
running = False
if e.type == MOUSEBUTTONDOWN:
if e.button == 1:
start=e.pos
copy = screen.copy
mb = mouse.get_pressed()
mx,my = mouse.get_pos()
draw.rect(screen,(255,255,255),recttoolRect)
if mb[0] == 1 and recttoolRect.collidepoint(mx,my):
tool = rect
if mb[0] == 1 and canvasRect.collidepoint(mx,my) and tool == rect:
screen.set_clip(canvasRect)
screen.blit(copy,(0,0))
draw.rect(screen,(colour),(start[0],start[1],mx-start[0],my-start[1]))
display.flip()
quit()
Without the full traceback it is hard to tell, but I'm guessing you've forgotton some parentheses behind a function call somewhere. E.g. if rect is a function, you probably have to write rect(), not rect.

Categories

Resources