Python Pyautogui:使用bezier曲线移动鼠标
我试图在Pyautogui中以贝塞尔曲线运动方式移动鼠标,以模拟更多的人体运动,如图所示: pyautogui中有一些吐温/缓和功能,但它们都不代表bezier曲线类型的移动。我创建了一个小脚本来计算它在最终到达目的地之前将到达的随机位置 默认“机器人”线性路径: 不幸的是,每到一个目的地,鼠标都会暂时停止Python Pyautogui:使用bezier曲线移动鼠标,python,random,pyautogui,Python,Random,Pyautogui,我试图在Pyautogui中以贝塞尔曲线运动方式移动鼠标,以模拟更多的人体运动,如图所示: pyautogui中有一些吐温/缓和功能,但它们都不代表bezier曲线类型的移动。我创建了一个小脚本来计算它在最终到达目的地之前将到达的随机位置 默认“机器人”线性路径: 不幸的是,每到一个目的地,鼠标都会暂时停止 import pyautogui import time import random print "Randomized Mouse Started." destx = 444; des
import pyautogui
import time
import random
print "Randomized Mouse Started."
destx = 444;
desty = 631;
x, y = pyautogui.position() # Current Position
moves = random.randint(2,4)
pixelsx = destx-x
pixelsy = desty-y
if moves >= 4:
moves = random.randint(2,4)
avgpixelsx = pixelsx/moves
avgpixelsy = pixelsy/moves
print "Pixels to be moved X: ", pixelsx," Y: ",pixelsy, "Number of mouse movements: ", moves, "Avg Move X: ", avgpixelsx, " Y: ", avgpixelsy
while moves > 0:
offsetx = (avgpixelsx+random.randint(-8, random.randint(5,10)));
offsety = (avgpixelsy+random.randint(-8, random.randint(5,10)));
print x + offsetx, y + offsety, moves
pyautogui.moveTo(x + offsetx, y + offsety, duration=0.2)
moves = moves-1
avgpixelsx = pixelsx / moves
avgpixelsy = pixelsy / moves
信息:
- 视窗10
- Python 2.7
- 愿意使用其他库,必要时使用Python版本
关于如何实现这一点,你有什么想法吗?你只需要知道,
移动鼠标((300300))
会让你的鼠标到达(300300),然后永远不会改变。看看这个工具,它只调用WIN32 api鼠标事件
。阅读一些关于它的内容,你会发现没有“启动和停止”位置。我不知道怎么画贝塞尔曲线
while True:
pos = (random.randrange(*x_bound),random.randrange(*y_bound))
move_mouse(pos)
time.sleep(1.0/steps_per_second)
看,这就是动画的秘密。你所需要做的就是使用
scipy,numpy
和任何可以简单移动鼠标光标的东西编写一个pos=draw\u bezier\u curve(t)
:
import pyautogui
import random
import numpy as np
import time
from scipy import interpolate
import math
def point_dist(x1,y1,x2,y2):
return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
cp = random.randint(3, 5) # Number of control points. Must be at least 2.
x1, y1 = pyautogui.position() # Starting position
# Distribute control points between start and destination evenly.
x = np.linspace(x1, x2, num=cp, dtype='int')
y = np.linspace(y1, y2, num=cp, dtype='int')
# Randomise inner points a bit (+-RND at most).
RND = 10
xr = [random.randint(-RND, RND) for k in range(cp)]
yr = [random.randint(-RND, RND) for k in range(cp)]
xr[0] = yr[0] = xr[-1] = yr[-1] = 0
x += xr
y += yr
# Approximate using Bezier spline.
degree = 3 if cp > 3 else cp - 1 # Degree of b-spline. 3 is recommended.
# Must be less than number of control points.
tck, u = interpolate.splprep([x, y], k=degree)
# Move upto a certain number of points
u = np.linspace(0, 1, num=2+int(point_dist(x1,y1,x2,y2)/50.0))
points = interpolate.splev(u, tck)
# Move mouse.
duration = 0.1
timeout = duration / len(points[0])
point_list=zip(*(i.astype(int) for i in points))
for point in point_list:
pyautogui.moveTo(*point)
time.sleep(timeout)
您可以通过设置以下内容来删除pyautogui
中的任何内置延迟:
# Any duration less than this is rounded to 0.0 to instantly move the mouse.
pyautogui.MINIMUM_DURATION = 0 # Default: 0.1
# Minimal number of seconds to sleep between mouse moves.
pyautogui.MINIMUM_SLEEP = 0 # Default: 0.05
# The number of seconds to pause after EVERY public function call.
pyautogui.PAUSE = 0 # Default: 0.1
注意:上面的示例不需要任何这些设置,因为它不使用publicmoveTo
方法。对于一个简单的解决方案,您可以尝试使用numpy
和bezier
库:
我想写点东西用鼠标画出来。运行上述代码将使鼠标沿着与下面相同的路径移动。红点位于定义曲线的每个控制点处
请注意,如果要像我在GIMP中所做的那样单击并拖动,则必须在脚本末尾的循环之前和之后添加pyautogui.mouseDown()
:
您可以在此处查看
bezier
文档:谢谢您的提示。。这也是我想要的。:)如果有一个库或其他东西可以将所有贝塞尔运动记录到一个数组中,这将是完美的。删除了控制中的Unicode“C”,并添加了更多的目标点,并为其提供了最小数量的内部点(非零等),效果非常好!谢谢修复了python2的非ascii问题。如何更改鼠标速度?移动鼠标大约需要20秒的时间。更改持续时间不会产生任何影响。for循环迭代1920次。我怀疑每次迭代都会以100ms的持续时间移动鼠标,而不是“超时”中指定的时间(这要低得多:~0.0001秒)。我该怎么解决这个问题?这里还可以。如果您使用publicpyautogui
方法来移动鼠标,那么您需要删除公共函数调用之间的内置延迟。大概pyautogui
不是最好的工具。我之所以使用它,只是因为它是被问这个问题的人使用的。@DJV您有推荐的库吗?我喜欢这个剧本。它一直工作得很好,但过了一段时间,它似乎确实变慢了。你能解释一下你的代码吗?我也在做类似的事情
import pyautogui
import bezier
import numpy as np
# Disable pyautogui pauses (from DJV's answer)
pyautogui.MINIMUM_DURATION = 0
pyautogui.MINIMUM_SLEEP = 0
pyautogui.PAUSE = 0
# We'll wait 5 seconds to prepare the starting position
start_delay = 5
print("Drawing curve from mouse in {} seconds.".format(start_delay))
pyautogui.sleep(start_delay)
# For this example we'll use four control points, including start and end coordinates
start = pyautogui.position()
end = start[0]+600, start[1]+200
# Two intermediate control points that may be adjusted to modify the curve.
control1 = start[0]+125, start[1]+100
control2 = start[0]+375, start[1]+50
# Format points to use with bezier
control_points = np.array([start, control1, control2, end])
points = np.array([control_points[:,0], control_points[:,1]]) # Split x and y coordinates
# You can set the degree of the curve here, should be less than # of control points
degree = 3
# Create the bezier curve
curve = bezier.Curve(points, degree)
# You can also create it with using Curve.from_nodes(), which sets degree to len(control_points)-1
# curve = bezier.Curve.from_nodes(points)
curve_steps = 50 # How many points the curve should be split into. Each is a separate pyautogui.moveTo() execution
delay = 1/curve_steps # Time between movements. 1/curve_steps = 1 second for entire curve
# Move the mouse
for i in range(1, curve_steps+1):
# The evaluate method takes a float from [0.0, 1.0] and returns the coordinates at that point in the curve
# Another way of thinking about it is that i/steps gets the coordinates at (100*i/steps) percent into the curve
x, y = curve.evaluate(i/curve_steps)
pyautogui.moveTo(x, y) # Move to point in curve
pyautogui.sleep(delay) # Wait delay