как дать значение Dynami c для выделения области в библиотеке изображений в python - PullRequest
2 голосов
/ 20 марта 2020

Используя этот скрипт, я пытаюсь сделать снимок экрана моего рабочего стола в определенной области (используя Tkinter gui)

Но с помощью этого кода я могу сделать только снимок экрана области исправления (фрейма) рабочего стола. Так что я хочу сделать, это попытаться установить значение (bbox of imagegrab) Dynami c.

И под Dynami c я имею в виду, что он должен захватывать только область экрана, которая выбрана (выделено) моим курсором мыши в любом месте на экране и может быть любого размера.

import tkinter as tk
from tkinter import *
from PIL import Image, ImageGrab 
root = tk.Tk()
def area_sel():    
     # using the grab method 
     img = ImageGrab.grab(bbox = (400,500,400,500)) #i want these values to be dynamic
     img.show() 

sel_btn = tk.Button(root, text='select area', width=20, command=area_sel)
sel_btn.pack()

root.mainloop()

пример изображения area

вот что я пытаюсь чтобы сделать это взять координаты из вашего кода, а затем записать эту конкретную область экрана.

def recording_screen():

    global recording
    recording = True

    while recording:
        sel=area_sel()    
        img = ImageGrab.grab(bbox=(Click_x, Click_y, Release_x, Release_y))
        frame = np.array(img)
        out.write(frame)

Ответы [ 2 ]

3 голосов
/ 20 марта 2020

Вы можете использовать Pillow, чтобы делать то, что вы хотите:

import tkinter as tk
from PIL import Image, ImageTk, ImageGrab, ImageEnhance

root = tk.Tk()
root.resizable(0, 0)

def show_image(image):
    win = tk.Toplevel()
    win.image = ImageTk.PhotoImage(image)
    tk.Label(win, image=win.image).pack()
    win.grab_set()
    win.wait_window(win)

def area_sel():
    x1 = y1 = x2 = y2 = 0
    roi_image = None

    def on_mouse_down(event):
        nonlocal x1, y1
        x1, y1 = event.x, event.y
        canvas.create_rectangle(x1, y1, x1, y1, outline='red', tag='roi')

    def on_mouse_move(event):
        nonlocal roi_image, x2, y2
        x2, y2 = event.x, event.y
        canvas.delete('roi-image') # remove old overlay image
        roi_image = image.crop((x1, y1, x2, y2)) # get the image of selected region
        canvas.image = ImageTk.PhotoImage(roi_image)
        canvas.create_image(x1, y1, image=canvas.image, tag=('roi-image'), anchor='nw')
        canvas.coords('roi', x1, y1, x2, y2)
        # make sure the select rectangle is on top of the overlay image
        canvas.lift('roi') 

    root.withdraw()  # hide the root window
    image = ImageGrab.grab()  # grab the fullscreen as select region background
    bgimage = ImageEnhance.Brightness(image).enhance(0.3)  # darken the capture image
    # create a fullscreen window to perform the select region action
    win = tk.Toplevel()
    win.attributes('-fullscreen', 1)
    win.attributes('-topmost', 1)
    canvas = tk.Canvas(win, highlightthickness=0)
    canvas.pack(fill='both', expand=1)
    tkimage = ImageTk.PhotoImage(bgimage)
    canvas.create_image(0, 0, image=tkimage, anchor='nw', tag='images')
    # bind the mouse events for selecting region
    win.bind('<ButtonPress-1>', on_mouse_down)
    win.bind('<B1-Motion>', on_mouse_move)
    win.bind('<ButtonRelease-1>', lambda e: win.destroy())
    # use Esc key to abort the capture
    win.bind('<Escape>', lambda e: win.destroy())
    # make the capture window modal
    win.focus_force()
    win.grab_set()
    win.wait_window(win)
    root.deiconify()  # restore root window
    # show the capture image
    if roi_image:
        show_image(roi_image)

tk.Button(root, text='select area', width=30, command=area_sel).pack()

root.mainloop()

Во время выбора региона:

enter image description here

Показать захват изображения после выбора региона:

enter image description here

2 голосов
/ 20 марта 2020

Использование pynput - это способ сделать это (возможно, использовать только tkinter можно, но я не знаю). Вам нужно знать только положение нажатой кнопки мыши и отпускание кнопки мыши:

Подробнее о модуль pynput

import tkinter as tk
# from tkinter import *
from PIL import Image, ImageGrab,ImageTk
from pynput import mouse
from pynput.keyboard import Key, Listener


def getPostion():
    def on_click(x, y, button, pressed):
        global Click_x, Click_y, Release_x, Release_y, STOP
        if pressed:
            Click_x = x
            Click_y = y
        else:
            Keyboardlistener.stop()
            Release_x = x
            Release_y = y
            STOP = False
            return False

    def on_release(key):
        global STOP
        if key == Key.esc:
            Mouselistener.stop()
            STOP = True
            return False

    with mouse.Listener(on_click=on_click) as Mouselistener, Listener(on_release=on_release) as Keyboardlistener:
        Mouselistener.join()
        Keyboardlistener.join()


root = tk.Tk()
def area_sel():
    global Click_x, Click_y, Release_x, Release_y, STOP
    Click_x, Click_y, Release_x, Release_y= 0,0,0,0
    # using the grab method
    top = tk.Toplevel() # create a toplevel
    top.wm_attributes('-alpha',0.3)
    top.state('zoomed') # make window fullscreen
    top.overrideredirect(1)

    # background = ImageTk.PhotoImage(image=ImageGrab.grab()) # get a screenshot
    fullCanvas = tk.Canvas(top) # make a fullscreen canvas
    # fullCanvas.create_image(xx,xx)  # create a screenshot image in this canvas.


    fullCanvas.pack()
    top.update()
    getPostion()
    if Click_x and Click_y and Release_x and Release_y:
        if STOP:
            return False
        top.withdraw()
        img = ImageGrab.grab(bbox = (Click_x, Click_y, Release_x, Release_y))
        img.show()


STOP = False
sel_btn = tk.Button(root, text='select area', width=20, command=area_sel)
sel_btn.pack()

root.mainloop()

редактировать сейчас, это полный инструмент, который может сделать снимок, не нужно использовать pynput полный код:

import tkinter as tk
# from tkinter import *
from PIL import Image, ImageGrab, ImageTk
import ctypes, sys

if sys.getwindowsversion().major == 10:
    ctypes.windll.shcore.SetProcessDpiAwareness(2) # Set DPI awareness


root = tk.Tk()
def area_sel():
    def getPress(event): # get press position
        global press_x,press_y
        press_x,press_y = event.x,event.y

    def mouseMove(event): # movement
        global press_x, press_y, rectangleId
        fullCanvas.delete(rectangleId)
        rectangleId = fullCanvas.create_rectangle(press_x,press_y,event.x,event.y,width=5)

    def getRelease(event): # get release position
        global press_x, press_y, rectangleId
        top.withdraw()
        img = ImageGrab.grab((press_x, press_y,event.x,event.y))
        img.show()

    top = tk.Toplevel()
    top.state('zoomed')
    top.overrideredirect(1)
    fullCanvas = tk.Canvas(top)

    background = ImageTk.PhotoImage(ImageGrab.grab().convert("L"))
    fullCanvas.create_image(0,0,anchor="nw",image=background)

    # bind event for canvas
    fullCanvas.bind('<Button-1>',getPress)
    fullCanvas.bind('<B1-Motion>',mouseMove)
    fullCanvas.bind('<ButtonRelease-1>',getRelease)

    fullCanvas.pack(expand="YES",fill="both")
    top.mainloop()

rectangleId = None
sel_btn = tk.Button(root, text='select area', width=20, command=area_sel)
sel_btn.pack()

root.mainloop()
...