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
Related
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))
I am creating a painter software and want the user to be able to save their image after they have finished creating it, so I tried pygame.image.save(pygame.display.get_surface(), "/home/user/screenshot.png"). I made a quick drawing and pressed the key I set which would save the image. I look at the image, and it's only saved the blank display surface, not the pygame.draw.rect()s of the actual drawing. I looked at the following links: How to capture pygame screen? https://gamedev.stackexchange.com/questions/118372/how-can-i-take-a-screenshot-of-a-certain-part-of-the-screen-in-pygame Can python get the screen shot of a specific window? and much more. How would I take a screenshot of the entire display screen along with the drawing? This is my mainloop:
running = True
while running:
updateWindow() # Updates window
clearWindow() # Clears window
checkEvents() # Checks events
redrawItems() # Redraws your drawing
pygame.event.pump()
pygame.display.quit()
pygame.quit()
Try pygame.Surface.copy on the display surface. See docs here.
So if display is your screen, then:
screencopy = display.copy()
should get you a copy of the display image in screencopy. Remember because of double buffering it will give you a copy of what you would see on the screen if you did an display.update() right then, which might be different that what is showing on the screen if you have done things that have not yet been pushed to the screen yet by an update().
You can do this using pygame.image.save(Surface, filename), which you can read more about
here
Below is a simple function that will save a portion of the display as an image.
def Capture(display,name,pos,size): # (pygame Surface, String, tuple, tuple)
image = pygame.Surface(size) # Create image surface
image.blit(display,(0,0),(pos,size)) # Blit portion of the display to the image
pygame.image.save(image,name) # Save the image to the disk**
What this function does is created a pygame surface named image. Then the area (pos,size) is blitted to image at its origin. Finally, pygame.image.save(Surface, filename) will be called and save image to the disk.
For example, if we want to save a 100x100 image named "Capture.png" at the pos 50x50 on the display, name would equal "Capture.png", pos would equal (50,50), and size would equal (100,100), and the function call would look as such:
Capture(display,"Capture.png",(50,50),(100,100))
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 am just setting up some functions for my game but my script fails to load the image
#used variables
# x, y for alien location
# nPc for the aliens image
#
#
#
#
#
#
#
#
#
#
#set up
import pygame, sys, random, time, math
from pygame.locals import *
pygame.init()
nPc = '/home/claude/Dropbox/Bowtie/Prisim/Images/Alien_Races/Standered/alien_1.png'
nPc = pygame.image.load(nPc).convert_alpha()
def loc_alien():
x = random.randint(0, 400)
y = randaom.randint(0, 400)
def spawn_alien(x, y):
screen.blit(nPc, (x, y))
when I run this I wont nothing to happen as I am not using the functions yet, but when I do run it I get this error
Traceback (most recent call last):
File "/home/claude/Dropbox/Bowtie/Prisim/Scripts/aliens.py", line 26, in <module>
nPc = pygame.image.load(nPc).convert_alpha()
error: No video mode has been set
anyone know what I'm doing wrong?
I believe that you need to call:
screen = pygame.display.set_mode((800, 600)) # change to the real resolution
this call will actually return the surface that you want to blit on. Below is the documentation from the linked resource.
pygame.display.set_mode()
Initialize a window or screen for display
set_mode(resolution=(0,0), flags=0, depth=0) -> Surface
This function will create a display Surface. The arguments passed in
are requests for a display type. The actual created display will be
the best possible match supported by the system.
The resolution argument is a pair of numbers representing the width
and height. The flags argument is a collection of additional options.
The depth argument represents the number of bits to use for color.
The Surface that gets returned can be drawn to like a regular Surface
but changes will eventually be seen on the monitor.
If no resolution is passed or is set to (0, 0) and pygame uses SDL
version 1.2.10 or above, the created Surface will have the same size
as the current screen resolution. If only the width or height are set
to 0, the Surface will have the same width or height as the screen
resolution. Using a SDL version prior to 1.2.10 will raise an
exception.
It is usually best to not pass the depth argument. It will default to
the best and fastest color depth for the system. If your game requires
a specific color format you can control the depth with this argument.
Pygame will emulate an unavailable color depth which can be slow.
When requesting fullscreen display modes, sometimes an exact match for
the requested resolution cannot be made. In these situations pygame
will select the closest compatible match. The returned surface will
still always match the requested resolution.
The flags argument controls which type of display you want. There are
several to choose from, and you can even combine multiple types using
the bitwise or operator, (the pipe “|” character). If you pass 0 or no
flags argument it will default to a software driven window. Here are
the display flags you will want to choose from:
pygame.FULLSCREEN create a fullscreen display
pygame.DOUBLEBUF recommended for HWSURFACE or OPENGL
pygame.HWSURFACE hardware accelerated, only in FULLSCREEN
pygame.OPENGL create an OpenGL renderable display
pygame.RESIZABLE display window should be sizeable
pygame.NOFRAME display window will have no border or controls
For example:
# Open a window on the screen
screen_width=700
screen_height=400
screen=pygame.display.set_mode([screen_width,screen_height])
Do not forgot to create your surface before creating variables with images in it
like this:
win = pygame.display.set_mode((576, 1024))
background_day = pygame.image.load("background-day.png").convert()
not like this:
background_day = pygame.image.load("background-day.png").convert()
win = pygame.display.set_mode((576, 1024))