i've got a problem in python :
import pyautogui as a
while True:
pixel = a.locateOnScreen("example.png")
if pixel == None: continue
pixel = a.center(pixel)
data = [pixel.x , pixel.y]
a.moveTo(data[0],data[1])
in this code it finds the picture and move the mouse on it but its to slow because every time loop start from beginning it loads the file and it makes it too slow.
i want it to work lively.
i tried:
import pyautogui as a
from IPython.display import Image
f = Image("example.png")
while True:
pixel = a.locateOnScreen(f)
pixel = a.center(pixel)
data = [pixel.x , pixel.y]
a.moveTo(data[0],data[1])
but it says image don't have attribute named mode
I want to place pointer on the center of picture
You use IPython.display.Image object, but that is the wrong one. Use PIL.Image instead:
import pyautogui as a
from PIL import Image
f = Image.open("example.png")
while True:
pixel = a.locateOnScreen(f)
pixel = a.center(pixel)
data = [pixel.x , pixel.y]
a.moveTo(data[0],data[1])
I confirmed this works with pyautogui version 0.9.53
That said, I don't think that the loading of the image is your performance bottleneck here, but rather the search algorithm itself. Pyautogui's documentation states that locateOnScreen can take some time. You can try to search a smaller region on the screen. Citing:
These “locate” functions are fairly expensive; they can take a full
second to run. The best way to speed them up is to pass a region
argument (a 4-integer tuple of (left, top, width, height)) to only
search a smaller region of the screen instead of the full screen:
import pyautogui
pyautogui.locateOnScreen('someButton.png', region=(0,0, 300, 400))
Related
I want to capture Excel on the second monitor. Win32gui.I used GetwindRect, but the coordinates don't seem to be accurate.
second monitor image
import time
import win32gui
import pyscreenshot as ImageGrab
def shot(hwnd):
x1,y1,x2,y2 = win32gui.GetWindowRect(hwnd)
saveas='screenshot.png'
img = ImageGrab.grab(bbox=(x1,y1,x2,y2))
img.save(saveas)
if __name__ == '__main__':
while True:
time.sleep(1)
classname = win32gui.GetClassName(win32gui.GetForegroundWindow())
print(classname)
if classname == 'XLMAIN':
hwnd = win32gui.FindWindow(classname, None)
if hwnd:
shot(hwnd)
break
To get the window coordinates on the second monitor, you need to handle the coordinates.
To position an object on a multiple monitor system
Determine the appropriate monitor.
Get the coordinates to the monitor.
Position the object using the coordinates.
To get the coordinates for the monitor, use GetMonitorInfo, which
provides both the work area and the entire monitor rectangle.
rcMonitor: A RECT structure that specifies the display monitor
rectangle, expressed in virtual-screen coordinates. Note that if the
monitor is not the primary display monitor, some of the rectangle's
coordinates may be negative values.
In other words, use GetMonitorInfo to obtain the virtual screen coordinates of the second monitor, and then add and subtract the excel coordinates obtained by GetWindowRect.
Code sample for reference(C++): Positioning Objects on a Multiple Display Setup
I am new to Blender and I’m having a bit of a tough time understanding its key concepts. I am using Blender 2.82 and working with Python scripting. My project consists of using Python to do the following:
Move object slightly.
Take picture with camera 1, camera 2, camera 3, and camera 4.
Repeat.
I had a script that did that. However, I wanted to save the position of my object (a sphere) every time I changed it during the loop in an animation, so I could later see what I did. When trying to insert keyframes for animation in my loop, it seems as if my sphere didn’t move. Below is my code. When I remove the lines that include frame_set and keyframe_insert, my sphere moves as I can see from my rendered images. I think I am confusing some kind of concept… Any help would be appreciated. The goal of this is to produce the images I would obtain from four cameras placed around an object, that is moving, so as to simulate a mocap system.
Why does inserting a keyframe change all of the images being rendered?
import bpy, bgl, blf,sys
import numpy as np
from bpy import data, ops, props, types, context
cameraNames=''
# Loop all command line arguments and try to find "cameras=east" or similar
for arg in sys.argv:
words=arg.split('=')
if ( words[0] == 'cameras'):
cameraNames = words[1]
sceneKey = bpy.data.scenes.keys()[0]
# Loop all objects and try to find Cameras
bpy.data.scenes[sceneKey].render.image_settings.file_format = 'JPEG'
bpy.data.scenes[sceneKey].cycles.max_bounces=12
bpy.data.scenes[sceneKey].render.tile_x=8
bpy.data.scenes[sceneKey].render.tile_y=8
bpy.data.scenes[sceneKey].cycles.samples = 16
bpy.data.scenes[sceneKey].cycles.caustics_reflective = False
bpy.data.scenes[sceneKey].cycles.caustics_refractive = False
bpy.data.objects['Sphere'].location=[1,1,1]
frame_num=0
for i in range(0,2): #nframes
bpy.context.scene.frame_set(frame_num)
for obj in bpy.data.objects:
# Find cameras that match cameraNames
if ( obj.type =='CAMERA') and ( cameraNames == '' or obj.name.find(cameraNames) != -1) :
# Set Scenes camera and output filename
bpy.data.scenes[sceneKey].camera = obj
bpy.data.scenes[sceneKey].render.filepath = '//'+obj.name+"_"+str(i)
# Render Scene and store the scene
bpy.ops.render.render( write_still=True )
bpy.data.objects['Sphere'].keyframe_insert(data_path="location",index=-1)
frame_num+=1
bpy.data.objects['Sphere'].location=[2,2,1]
I have no knowledge of python, but you can try to do key frame animation manually and make a script which will render the pictures after a set of key frames(whenever the object has moved to a new location)
It is not too hard (I'm talking about only the animation), just press the circle button near the play animation button on the timeline. This will turn on auto key framing and you just have to go to the desired key frame and move the object according to your need.
I've spent the past hour researching this simple topic, but all of the answers I've come across have been very complex and, as a noob to Python, I've been unable to incorporate any of them into my program.
I am trying to make an AI play a browser version of the Piano Tiles Game. As of now, I'm simply trying to take a capture of the games window (a small portion of my computer screen), and then check that games window with a .png of the game's start button. From there I will go on to CLICK that start button, but that's a problem for another time.
How can I check to see if a Image contains a .png file?
Here is my current code:
from PIL import ImageGrab as ig, ImageOps as io, Image
import pyautogui
import bbox
def grabStart(window):
#The start button
start = Image.open("res/StartButton.PNG")
start = io.grayscale(start)
#This is the part I need to figure out. The following is just pseudocode
if window.contains(start): #I know that this doesn't actually work. Just pseudocode
#I'd like to return the location of 'start' in one of the following forms
return either: (x1, y1, x2, y2), (x1, y1, width, height), (a coordinate within 'start'))
def grabGame():
#The coordinates of the entire game window
x1 = 2222
y1 = 320
x2 = 2850
y2 = 1105
#The entire screen of the game
window = ig.grab(bbox = (x1, y1, x2, y2))
window = io.grayscale(window)
return window
grabStart(grabGame())
Try using pyautogui.locate(). Function takes in input two parameter's, the first is the image which needs to be found, the second one is the image in which the smaller image needs to be found. This method only works for images, so if you want to run this for a live window, you might consider another option. Secondly pyautogui is just a wrapper over PIL so if you run into efficiency issues, you might wanna translate the locate() into its PIL equivalent for performance.
Here's a way of doing it. I just leave the program running and open/close and move a preview of the button around the screen seeing if it spots the button and reports the coordinates correctly.
#!/usr/bin/env python3
from PIL import ImageGrab as ig, Image
import pyautogui as ag
def checkButton(button, window):
try:
location = ag.locate(button, window, confidence=0.8)
print(f'location: {location[0]},{location[1]},{location[2]},{location[3]}')
except:
print('Not found')
# Load button just once at startup
button = Image.open("button.png")
# Loop, looking for button
while True:
window = ig.grab()
checkButton(button, window)
I can create an animated GIF like this:
from wand.image import Image
with Image() as im:
while i_need_to_add_more_frames():
im.sequence.append(Image(blob=get_frame_data(), format='png'))
with im.sequence[-1] as frame:
frame.delay = calculate_how_long_this_frame_should_be_visible()
im.type = 'optimize'
im.format = 'gif'
do_something_with(im.make_blob())
However, an image created like this loops indefinitely. This time, I want it to loop once, and then stop. I know that I could use convert's -loop parameter if I were using the commandline interface. However, I was unable to find how to do this using the Wand API.
What method should I call, or what field should I set, to make the generated GIF loop exactly once?
You'll need to use ctypes to bind the wand library to the correct C-API method.
Luckily this is straightforward.
import ctypes
from wand.image import Image
from wand.api import library
# Tell Python about the C-API method.
library.MagickSetImageIterations.argtypes = (ctypes.c_void_p, ctypes.c_size_t)
with Image() as im:
while i_need_to_add_more_frames():
im.sequence.append(Image(blob=get_frame_data(), format='png'))
with im.sequence[-1] as frame:
frame.delay = calculate_how_long_this_frame_should_be_visible()
im.type = 'optimize'
im.format = 'gif'
# Set the total iterations of the animation.
library.MagickSetImageIterations(im.wand, 1)
do_something_with(im.make_blob())
I am familiar with programming but not with python or linux. I am programming in python on a raspberry pi trying to create a security camera. Here is my code to test my current problem:
#!/usr/bin/python
import pygame, sys
from pygame.locals import *
from datetime import datetime
import pygame.camera
import time
pygame.init()
pygame.camera.init()
width = 640
height = 480
pic_root = "/root/cam/"
cam = pygame.camera.Camera("/dev/video0",(width,height),"RGB")
cam.start()
while True:
raw_input("press enter")
image = cam.get_image()
filename = datetime.now().strftime("%Y_%m_%d_%H_%M_%S") +'.jpg'
filepath = pic_root+filename
pygame.image.save(image, filepath)
So when I press enter, an image is taken from the webcam and saved. But the image is always two images behind. No matter how long in between saving images, the first two are always very dim as if the webcam has just started up, then the rest are always two images late.
So if I took 5 images, one with one finger up, then next with two fingers, etc, I would end up with two dark images and then the first three images. 1,2 and 3 fingers. It is as if the images are being stored somewhere then when I try to save a live images it pulls up an old one.
Am I missing something here? What's the issue?
First, I'm not familiar with Pygame (but I do a lot of snapshot capturing with OpenCV -- here's one of my projects: http://vmlaker.github.io/wabbit.)
I changed your code so that on every iteration, you 1) start, 2) take snapshot, and 3) stop the camera. This works a little better, in that it is only one image behind (instead of two.) It's still pretty weird how the old image sticks around from the previous run... I haven't figured out how to flush the camera. Notice I also changed pic_root, and instead of the infinite loop I'm using 3 iterations only:
from datetime import datetime
import pygame
import pygame.camera
pygame.init()
pygame.camera.init()
width = 640
height = 480
pic_root = './'
cam = pygame.camera.Camera("/dev/video0",(width,height),"RGB")
#cam.start()
for ii in range(3):
raw_input("press enter")
cam.start()
image = cam.get_image()
cam.stop()
filename = datetime.now().strftime("%Y_%m_%d_%H_%M_%S") +'.jpg'
filepath = pic_root+filename
pygame.image.save(image, filepath)
The OP's comment helped, but I actually have to pull the picture three times with get_image() before saving.
I also have a wakeup function which I call after a long standby time to wake the camera. Mine has the behavior to be black after a long time.
I guess, all this weird stuff has something to do with a buffer. But the multiple call did the trick for me.