Is there a way to store circle coordinates and move them around in python turtle? - turtle-graphics

I know it's possible to store polygons in a dictionary since they have definitive coordinates, but is there a way to store the coordinates of a circle into a dictionary and move them around? My program consists of detecting whether a mouse click is within a circle and from there, gets the coordinate of that circle moving it to wherever the user desires with another mouse click (the get.poly function, instead of moving the current circle that I already drew, makes another copy). Below is an incomplete snippet of what I want to do:
def buttonclick(x, y): # detects mouseclick
return pen.goto(x, y)
def check(ctr, pt): # check whether the click is within the circle
if (pt[0] - ctr[0])** 2 + (pt[1] - ctr[1])**2 < 5**2:
return True
if check((0,5), mouseclick coordinates): # if true, move circle to next click
# pen = the circle thats detected
# move circle coordinates to next mouseclick
# break
I tried with the code provided by /u/cdlane as follows and here is what I meant by generating a new copy
pen.goto(0,0)
pen.pd()
pen.begin_poly()
pen.circle(radius)
pen.end_poly()
shape.addcomponent(pen.get_poly(), 'red', 'black')
screen.register_shape('1', shape)
pen = Turtle(shape = '1')
pen.pu()
Function does exactly what I need it to do but using an existing circle instead of generating a new copy.

Rather than fix your implementation, I'm going to suggest a different implementation to achieve what you describe.
The circles themselves will be turtles, and clicking on one will "select" it. Clicking anywhere on the screen after that will move it. However, we don't want turtle.onclick() active at the same time as screen.onclick() since they both will get invoked, causing complications. Below is my two turtle example:
from turtle import Screen, Turtle
from functools import partial
selected = None
def on_screen_click(x, y):
global selected
screen.onclick(None)
selected.goto(x, y)
outline, fill = selected.color()
selected.color(fill, outline)
selected = None
for turtle in screen.turtles():
turtle.onclick(partial(on_turtle_click, turtle))
def on_turtle_click(self, x, y):
global selected
for turtle in screen.turtles():
turtle.onclick(None)
selected = self
outline, fill = selected.color()
selected.color(fill, outline)
# (re)enable screen onclick handler after this function, not during
screen.ontimer(partial(screen.onclick, on_screen_click))
screen = Screen()
turtle_1 = Turtle()
turtle_1.shape('circle')
turtle_1.color('red', 'black')
turtle_1.penup()
turtle_2 = turtle_1.clone()
turtle_2.goto(100, 100)
for turtle in screen.turtles():
turtle.onclick(partial(on_turtle_click, turtle))
screen.mainloop()

Related

Python turtle after drawing , click mouse inside drawing, clear screen and redraw

I am working on using python turtle to draw a circle.when i draw the circle, mouse click inside circle erase, click anywhere in the turtle,redraw it and click again inside again erase. So the process like this :
black screen
1.Click mouse
2.Start drawing circle
3.finish
4.click inside circle
5.clear screen
6.click again anywehre in the screen redraw circle
7.click inside circle clear screen
Thanks
https://i.stack.imgur.com/LR8CH.png
import PositionService
import turtle
t=turtle.Turtle()
ts=tur
tle.Screen()
ts.bgpic("shape_window.png")
t.up()
def get_click(x,y):# get click (x,y)
#if counter == 0:
draw_circle(x,y,"green",80)# draw the circle
print("clicking at ({}, {})".format(x,y))
def draw_circle(x,y,color,rad): # draw the circle
t.goto(x,y)
t.down()
t.circle(80)
t.color("green")
t.up()
t.hideturtle()
#t.home()
def main():
#maybe use global _pen
ts.onclick(get_click) # clicker
#set_position( x,y)?
#is_visible(draw_square)
I think were from the same class. I was also struggling until I realized that they supplied a PositionService.py file. You are supposed to use the functions within that file to help.

Flow of Control Python OpenCv : Why cv2.setMouseCallback isn't inside loop?

I am confused with the flow of control in the following program. The purpose of the code is to draw a rectangle in the live video stream from the webcam.
Working Principal: First click will be initializing coordinates of the starting corner of the rectangle and mark it with a bold circle. Second click will be completing the rectangle.
Now my Question is: Why is cv2.setMouseCallback('Test',draw_rectangle) statement isn't inside the loop?
The code is working perfectly fine but I am unable to understand the flow of control. Please help me out.
import cv2
import os
os.environ["OPENCV_VIDEOIO_PRIORITY_MSMF"] = "0"
#CALLBACK FUNCTION RECTANGLE
def draw_rectangle(event,x,y,flags,param): #Param is the just the additional paramter which u can receive
global pt1, pt2, topLeft_Clicked, botRight_Clicked
if event ==cv2.EVENT_LBUTTONDOWN:
#Reset if rectangle is drawing i.e both var are true
if topLeft_Clicked and botRight_Clicked:
pt1=(0,0)
pt2=(0,0)
topLeft_Clicked=False
botRight_Clicked=False
if topLeft_Clicked == False:
pt1=(x,y)
topLeft_Clicked=True
elif botRight_Clicked == False:
pt2=(x,y)
botRight_Clicked=True
#GLOBAL VARIABLES
pt1=(0,0)
pt2=(0,0)
topLeft_Clicked= False
botRight_Clicked= False
#COnnect to the Callback
cap=cv2.VideoCapture(0)
cv2.namedWindow('Test')
cv2.setMouseCallback('Test',draw_rectangle)
while True:
ret,frame=cap.read()
#Drawing Based on Global Variables
if topLeft_Clicked: # If topleft is true
cv2.circle(frame,center=pt1,radius=5,color=(0,0,255),thickness=-1)
if topLeft_Clicked and botRight_Clicked:
cv2.rectangle(frame,pt1,pt2,(0,0,255),3)
cv2.imshow('Test',frame)
if(cv2.waitKey(1) & 0xFF==ord('q')):
break
cap.release()
cv2.destroyAllWindows()
Callback functions are called on events. Unlike a regular function, you don't need to make a function call every time you want it to run.
The line cv2.setMouseCallback('Test',draw_rectangle) will set the function draw_rectangle as a response to any event received from mouse on the OpenCV window "Test". Once the callback is set, inside your while loop you will catch all your mouse events on your "Test" window.
Callback is the function that is called every time you move the mouse over the display window. It is independent from the flow in main, i.e., it is in a new thread waiting for changes in mouse input.
The reason why you use loop in main is because you want to update the image you display. After calling imshow, you need to call waitKey for impact on rendering.
cv2.setMouseCallback('Test',draw_rectangle) this function is actually an event handler, which is setting the call for draw_rectangle function on every left mouse click. The rest of the code inside the while loop are for all the dynamic operations and at last cv2.imshow is to render that in the image.
One token of gift for better handling of opencv closeWindows, closing only currently used window only:
def showImage(imageName, image):
img = image.copy()
cv2.imshow(imageName, img)
while(1):
pressedKey = cv2.waitKey(0) & 0xFF
if(pressedKey == ord('q')):
cv2.destroyWindow(imageName)
break
else:
cv2.putText(img, "\press q to exit", (10,10), cv2.FONT_HERSHEY_SIMPLEX, 0.45, color=(255,0,0))
cv2.imshow(imageName, img)

How to determine if an object stopped moving or left the frame

Every tutorial, sample or blog I have read show various ways to track a moving object in a frame, as long as it is moving. This has become ubiquitous.
What I have been trying to figure out is how to determine if the object stopped moving or actually left the frame. When using background separation, when an object stops moving it becomes part of the foreground and as such "disappears". It "reappears" when it moves again. As far as I can tell the same behavior exists when an object leaves the frame, it just "disappears". For example the following code fragment demonstrates this:
**BackgroundSubtractorMOG2 _fgDetector = new BackgroundSubtractorMOG2();
CvBlobDetector _blobDetector = new CvBlobDetector();
CvTracks _tracker = new CvTracks();
CvBlobs _blobs = new CvBlobs();**
private int FindAndTrack()
{
CvInvoke.GaussianBlur(_analyzeMat, _smoothedFrame, new System.Drawing.Size(3, 3), 1);
#region use the BG/FG detector to find the forground mask
_fgDetector.Apply(_smoothedFrame, _foregroundMask);
#endregion use the BG/FG detector to find the forground mask
_blobDetector.Detect(_foregroundMask.ToImage<Gray, byte>(), _blobs);
_blobs.FilterByArea(_minimumAreaValue, int.MaxValue);
_tracker.Update(_blobs, 0.01 * _scaleValue, 1, 5);
return _tracker.Count;
}
I am no longer sure that background separation may be the answer.
What would give a definitive indication of a object leaving the frame?
Thanks,
Doug
Place tracker.update as condition for if loop if condition fails your object of interest has left the frame.
If you want to detect if object has moved or not then compare x & y values of bounding box of object with previous x & y values of bounding box if values are same than object has stopped moving else it has moved

colour detection bot

I want to create a script to automatically click on a moving target on a game.
To do this I want to check colours on the screen to determine where my target is and then click him, repeating this if he moves.
I'm not skilled at programming and there might be an easier solution to what I have proposed below:
1/Split the screen into equal tiles - size of tile should represent the in game object.
2/Loop through each pixel of each tile and create a histogram of the pixel colours.
3/If the most common recorded colour matches what we need, we MIGHT have the correct tile. Save the coords and click the object to complete task
4/Every 0.5 seconds check colour to determine if the object has moved, if it hasnt, keep clicking, if it has repeat steps 1, 2 and 3.
The step I am unsure of how to do technically is step 1. What data structure would I need for a tile? Would a 2D array suffice? Store the value of each colour in this array and then determine if it is the object. Also in pseudo how would I split the screen up into tiles to be searched? The tile issue is my main problem.
EDIT for rayryeng 2:
I will be using Python for this task. This is not my game, I just want to create a macro to automatically perform a task for me in the game. I have no code yet, I am looking more for the ideas behind making this work than actual code.
3rd edit and final code:
#!/usr/bin/python
import win32gui, win32api
#function to take in coords and return colour
def colour_return(x,y):
colours = win32gui.GetPixel(win32gui.GetDC(win32gui.GetActiveWindow()), x,y)
return colours
def click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
#variable declaration
x = 1
y = 1
pixel_value = []
colour_found = 0
while x < 1600:
pixel_value = colour_return(x,y)
if pixel_value == 1844766:
click(x,y)
x=x+1
#print x
print y
if x == 1600:
y=y+1
x=1
#print tile
pixel_value = 0
This is the final code that I have produced. It works but it is incredibly slow. It takes 30 seconds seconds to search all 1600 pixels of y=1. I guess it is my method that is not working. Instead of using histograms and tiles I am now just searching for a colour and clicking the coordinates when it matches. What is the fastest method to use when searching an entire screen for a certain colour? I've seen colour detection bots that manage to keep up every second with a moving character.

corona drag and drop an object on container or reference

I am developing a game and one level is solving a jumbled up word. The letters are images like tiles and I am trying to either click a letter and this will move to the first of the allocated spots to solve the word or to actually drag the tile to the spot. Can anyone help me implement this?
To drag an object see this tutorial:
http://www.coronalabs.com/blog/2011/09/24/tutorial-how-to-drag-objects/
If you just want to tap them and have them move to where you want them, then something like this might work for you:
local function moveTile(event)
-- put your code here to move the tile
-- figure out the X, Y where the tile needs to move to
-- either just set the X, Y on the tile or use a transition.to() call
-- to animate it.
local thisTile = event.target
thisTile.x = destinationX -- you have to figure out what destinationX is.
thisTile.y = destinationY -- figure this out too
return true
end
Then on each tile after you create it, simply add this line to make it tappable:
tile:addEventListener("tap", moveTile)

Resources