Detecting Rightclick in TigerJython - jython

I want to detect a right-click in jython. Here I am using the gturtle module and I am trying to make the right-click fill shapes i drew.
from gturtle import*
def fillClick(x,y):
fill(x,y)
makeTurtle(?=fillClick)

Add a Listener.
Sample code:
from gturtle import*
def fillClick(x,y):
fill(x,y)
wn = turtle.Screen() # make the screen
wn.listen() # Set up listener
wn.onclick(fillClick, 3) # 3 - right click, 1 - left click for windows. if 3 doesn't work, do 2(depends on your device).
wn.mainloop()
Note, turtle plugs in the x, y by itself.
Edit: Note, you don't need "()" after fillClick function when using
wn.onclick(fillClick, 3).
Please comment if you have any questions.
Edit 2:
New sample code that represents what you want to do:
import turtle
def fillClick(x, y):
t = turtle.Turtle() # - make a turtle to "fill the place in"
t.shape("circle") # set shape to circle
t.color("black") # - set color to black
t.penup() # prevents a line following the turtle
turtle.tracer(0, 0) # - disables screen refreshing
t.goto(x, y)
turtle.update() # - update.
wn = turtle.Screen() # make the screen
wn.listen() # Set up listener
wn.onclick(fillClick, 3) # 3 - right click, 1 - left click for windows. if 3 doesn't work, do 2(depends on your device).
wn.mainloop()

Related

Python Outlier Removing

I want to remove blue dots over the green dots region.
I tried using the residual error method from the blue group, and also the z -Score method from Blue but was unable to remove it.
there is a correlation between x and y.
can anyone please share some ideas or links?
What if you create a new feature using both X and Y and then set the threshold values?
like:
# Make new feature
df['xy'] = df['x'] * df['y']
# Filter
df = df[~(df['xy'] < threshold_val & df['gender'] == 'Male')]

How to get a photo from tello drone using the sdk

The Tello sdk has the streamon and streamoff commands. These start and end the 720p video stream. Is there a way to get a 5 megapixel image through the sdk, like when you put the control app into photo mode? I'm guessing if such a way exists, it is not documented.
while there isn't a UDP command that you can send to the drone to switch, there is some python code that you could try in order to make it work. and to make something like that work easily without coding it over again putting it in a function and calling it like "takePhoto()" is the best solution I have. Here's some code:
# # simple ex_4: Tello_photo
# <\>
from djitellopy import tello
import cv2
me = tello.Tello()
me.connect()
print(me.get_battery())
def TakePhoto(me):
me.streamoff()
me.streamon()
img = me.get_frame_read().frame
# print(img)
# img = cv2.resize(img, (360, 240)) # optional
cv2.imshow("photo", img) # optional display photo
cv2.waitKey(0)
# # example condition, it can also just be called normally like "TakePhoto"
"""
if (1 + 1) == 2:
TakePhoto(me)
"""
# # another example, with an actual used if statement
"""
bat = me.get_battery()
if bat < 50:
TakePhoto(me)
else:
print("battery too low (for ex)")
"""
# # for now, we'll call it just like this for testing:
TakePhoto(me)
# </>
the code was tested on windows 10 - pycharm 2021.2 > python3.x >> opencv 4.5.1.48
I hope this helped and I hope it works for you.

Show done plot in a widget

I have build a GUI with Qt Designer and have a code which generates a 3D-Model using matplotlib. When I run this code it opens a new window which allows me to interact with that model.
I want to have this window inside a widget in my GUI. The idea is that I have 3 buttons with 3 different models. And after one gets clicked the chosen model will be displayed.
Basically, I dont know how to connect the plot to the widget.
I tried to promote the QWidget to a mplwidget following this guide:
https://www.youtube.com/watch?v=2C5VnE9wPhk
But it doesnt go indepth and I only found this video.
also, I dont know if that is an issue, I am using matplotlib.pyplot.
X = 2D-Array
Y = 2D-Array
Z = 2D-Array #(generetad using numpy.mehsgrid)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlabel('X-Achse')
ax.set_ylabel('Z-Achse')
ax.set_zlabel('Y-Achse')
ax.plot_surface(X, Z, Y, color='gray')
plt.show()
is how I get my window for my model
class MatplotlibWidget(QMainWindow):
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.pushButton_7.clicked.connect(self.sollmodell)
# self.ui.pushButton_8.clicked.connect(self.openFileDialogISTI)
# self.ui.pushButton_8.clicked.connect(self.openFileDialogSOLLA)
self.ui.setupUi(self)
self.show()
this is my GUI code. below there I have my method which is connected to the button. basically it will run the code above but nothing happens (not even a pop up window).
Expected: Model inside the Widget, able to change via mouseclick
Actual: blank widget with x and y axis going from 0 to 1 and shwowing nothing

Best way to interactively draw a line on a 2D matplotlib plot

I'm a novice using matplotlib as an embedded control in my PyQt4 application to display image data. I'd like to be able to allow the user to interactively draw a line on the image by clicking and dragging. I have it working but it is so slow as to be unusable, leading me to believe I'm not going about it the correct way. The only way I can get the line to appear is by forcing the canvas to redraw each time the mouse moves (I suspect this is the cause of the slowdown).
For example, on the mouse down event I store the current coordinates and add a Line2D object to the plot as follows:
def onMouseMove(self, event):
if self.drawingLine:
self.lineStartX = event.xdata
self.lineStopX = event.xdata
self.lineStartY = event.ydata
self.lineStopY = event.ydata
self.line = Line2D([self.lineStartX, self.lineStopX], [self.lineStartY, self.lineStopY], linewidth = 1.5, color = 'r')
self.axes.add_line(self.line)
Then, in my mouse move event I redraw the line as follows:
def onMouseMove(self, event):
if self.drawingLine:
self.lineStopX = event.xdata
self.lineStopY = event.ydata
# Adjust the line to the new endpoint:
self.line.set_data([self.lineStartX, self.lineStopX], [self.lineStartY, self.lineStopY])
# Force a redraw otherwise you don't see any changes:
self.fig.canvas.draw()
As I've stated this approach is unusably slow and hence probably wrong. Can somebody please clue me in to what the proper approach is here? Thank you all in advance.
First off, you will already gain a little by using
self.fig.canvas.draw_idle()
instead of draw(). This redraws the canvas only when it's not currently beeing repainted, saving you a lot of draws.
If this is not enough, you would need to use the technique of blitting. Now since you don't have a minimal example, I will not provide any complete solution for this here, but e.g. the answer to this question, why is plotting with Matplotlib so slow?, has an example of that.
The idea is to store the background, and only redraw the part that changes (here the line).
background = fig.canvas.copy_from_bbox(ax.bbox)
# then during mouse move
fig.canvas.restore_region(background)
line.set_data(...)
ax.draw_artist(line)
fig.canvas.blit(ax.bbox)
# only after mouse has stopped moving
fig.canvas.draw_idle()
This technique is also used internally by some matplotlib widgets, e.g. matplotlib.widgets.Cursor to let the lines follow the cursor quickly.
This brings me to the last point, which is: You don't need to reinvent the wheel. There is a matplotlib.widgets.RectangleSelector, which by defaut draws a rectangle for selection. But you may use its drawtype='line' argument, to change the selection to a line, together with the argument blit=True this should already give you what you need - you will just need to add the code to finally draw a line once the selection is finished.
Note that in the newest matplotlib version, there is even a matplotlib.widgets.PolygonSelector, which may directly be what you need.
matplotlib is built to be flexible and to work with multiple different backends. It is very slow at real-time plotting. The problem is that your mouse move events are very rapid. Anything trying to keep up with the mouse movement will probably be slow. You need to call the plot less often. You can do this by checking the time in your mouse move function and trying to limit the plotting calls to whatever works.
import time
def onMouseMove(self, event):
if self.drawingLine and time.time() - last_time > 0.03: # Change the 0.03 to change how often you plot.
last_time = time.time()
...
I highly suggest pyqtgraph. pyqtgraph has built in rate limiting signals that you can work with to do this.
Below is a basic example of how you can do this.
# Change the style to look like matplotlib
pyqtgraph.setConfigOption("background", QtGui.QColor.fromRgbF(230/255, 230/255, 234/255, 255/255))
pyqtgraph.setConfigOption("background", 'w')
pyqtgraph.setConfigOption("foreground", 'k')
pyqtgraph.setConfigOption("antialias", True)
# Create the widgets and plot items
glw = pyqtgraph.GraphicsLayoutWidget()
pg = glw.addPlot(0, 0)
class MyClass(object):
...
...
def onMouseMove(self, event):
if self.drawingLine:
scene_pos = event[0]
data_pos = pg.getViewBox().mapSceneToView(scene_pos)
x, y = data_pos.x(), data_pos.y()
self.lineStopX = x
self.lineStopY = y
# Adjust the line to the new endpoint:
if not self.line:
self.line = pg.plot(x=[], y=[])
self.line.setData(x=[self.lineStartX, self.lineStopX],
y=[self.lineStartY, self.lineStopY])
mouse_move_sig = pyqtgraph.SignalProxy(pg.scene().sigMouseMoved,
rateLimit=60, slot=onMouseMove)

draw grid lines over an image in matplotlib

How can I draw regular grid lines over a tiff image?
I want to draw regular square grids for each interval (say 100 by 100 pixels) over the image and save that with the drawings. I also need to overlay each grid id as '1','2',...at the middle of each grid box.
You will need the python imaging library (PIL) installed. (See here https://pypi.python.org/pypi/PIL). See these answers for examples of ways to install PIL: answer 1, answer 2
Right, with that installed, the following code should do what you ask for:
import matplotlib.pyplot as plt
import matplotlib.ticker as plticker
try:
from PIL import Image
except ImportError:
import Image
# Open image file
image = Image.open('myImage.tiff')
my_dpi=300.
# Set up figure
fig=plt.figure(figsize=(float(image.size[0])/my_dpi,float(image.size[1])/my_dpi),dpi=my_dpi)
ax=fig.add_subplot(111)
# Remove whitespace from around the image
fig.subplots_adjust(left=0,right=1,bottom=0,top=1)
# Set the gridding interval: here we use the major tick interval
myInterval=100.
loc = plticker.MultipleLocator(base=myInterval)
ax.xaxis.set_major_locator(loc)
ax.yaxis.set_major_locator(loc)
# Add the grid
ax.grid(which='major', axis='both', linestyle='-')
# Add the image
ax.imshow(image)
# Find number of gridsquares in x and y direction
nx=abs(int(float(ax.get_xlim()[1]-ax.get_xlim()[0])/float(myInterval)))
ny=abs(int(float(ax.get_ylim()[1]-ax.get_ylim()[0])/float(myInterval)))
# Add some labels to the gridsquares
for j in range(ny):
y=myInterval/2+j*myInterval
for i in range(nx):
x=myInterval/2.+float(i)*myInterval
ax.text(x,y,'{:d}'.format(i+j*nx),color='w',ha='center',va='center')
# Save the figure
fig.savefig('myImageGrid.tiff',dpi=my_dpi)
Which, if used on the grace_hopper.png example file, produces the following output:
This can be done effectively in two lines by looping over the image data at your grid intervals. Using the canonical image from the SIPI database as an example
import pylab as plt
# Load the image
img = plt.imread("lena512color.tiff")
# Grid lines at these intervals (in pixels)
# dx and dy can be different
dx, dy = 100,100
# Custom (rgb) grid color
grid_color = [0,0,0]
# Modify the image to include the grid
img[:,::dy,:] = grid_color
img[::dx,:,:] = grid_color
# Show the result
plt.imshow(img)
plt.show()
The answer by #tom may be more robust as it works with the matplotlib library. I'll leave this example up for its simplicity.
Let me just leave it here
def draw_grid(image, line_space=20):
H, W = image.shape
image[0:H:line_space] = 1
image[:, 0:W:line_space] = 1