首页 > 编程语言 >Python的GUI应用,用于实时监控屏幕区域的图片变化

Python的GUI应用,用于实时监控屏幕区域的图片变化

时间:2024-11-10 10:57:02浏览次数:1  
标签:截图 end screenshot Python GUI start tk 屏幕 root

         

如何使用Python监控屏幕变化并截图

 

1、导入所需模块

首先,我们需要导入一些Python模块,包括PIL(Python Imaging Library)、numpy、os和time。这些模块将帮助我们截取屏幕图像,并进行文件和时间相关的操作。

from PIL import ImageGrab  # 导入ImageGrab模块,用于截取屏幕图像
import numpy as np  # 导入numpy模块,用于处理图像数据
import os  # 导入os模块,用于文件和文件夹操作
import time  # 导入time模块,用于时间相关操作

2、设置截图保存路径

接下来,我们将设置截图保存的路径。在本例中,我们将截图保存到用户桌面的一个名为“Screenshots”的文件夹中。

desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")  # 获取当前用户的桌面路径
screenshot_folder = os.path.join(desktop_path, "Screenshots")  # 设置截图保存文件夹路径
os.makedirs(screenshot_folder, exist_ok=True)  # 创建截图保存文件夹,如果文件夹已存在则忽略

3、定义监控区域

我们需要定义要监控的屏幕区域的左上角和右下角坐标。在这个示例中,我们选择了一个800x600像素的区域

monitor_region = (0, 0, 800, 600)  # 示例:左上角(0, 0),右下角(800, 600)

4、初始化上一次截图

我们将使用一个变量来保存上一次的屏幕截图,以便与当前截图进行比较,以检测屏幕是否发生了变化。

last_screenshot = ImageGrab.grab(bbox=monitor_region)  # 截取指定区域的屏幕图像,并赋值给last_screenshot变量

5、 监控屏幕变化并截图

现在,我们将进入一个无限循环,在循环中持续监控屏幕的变化。当检测到屏幕发生变化时,我们将进行截图并保存。

复制代码
try:
    while True:  # 进入无限循环,持续监控屏幕变化
        # 获取当前屏幕截图
        current_screenshot = ImageGrab.grab(bbox=monitor_region)  # 截取指定区域的屏幕图像,并赋值给current_screenshot变量

        # 将图像转换为 NumPy 数组...

        # 计算监控区域的像素值差异...

        # 检查像素值差异是否超过阈值...

        # 保存截图...

        # 输出截图信息...

        # 更新上一次截图...

        # 每隔一定时间进行一次截图...
except KeyboardInterrupt:  # 捕获键盘中断异常,用于停止监控
    print("Monitoring stopped.")  # 打印停止监控的提示信息
复制代码

6、完整代码

复制代码
from PIL import ImageGrab  # 导入ImageGrab模块,用于截取屏幕图像
import numpy as np  # 导入numpy模块,用于处理图像数据
import os  # 导入os模块,用于文件和文件夹操作
import time  # 导入time模块,用于时间相关操作

# 设置截图保存路径
desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")  # 获取当前用户的桌面路径
screenshot_folder = os.path.join(desktop_path, "Screenshots")  # 设置截图保存文件夹路径
os.makedirs(screenshot_folder, exist_ok=True)  # 创建截图保存文件夹,如果文件夹已存在则忽略

# 定义监控区域的左上角和右下角坐标
monitor_region = (0, 0, 800, 600)  # 示例:左上角(0, 0),右下角(800, 600)

# 初始化上一次截图
last_screenshot = ImageGrab.grab(bbox=monitor_region)  # 截取指定区域的屏幕图像,并赋值给last_screenshot变量

try:
    while True:  # 进入无限循环,持续监控屏幕变化
        # 获取当前屏幕截图
        current_screenshot = ImageGrab.grab(bbox=monitor_region)  # 截取指定区域的屏幕图像,并赋值给current_screenshot变量

        # 将图像转换为 NumPy 数组
        current_screenshot_array = np.array(current_screenshot)  # 将当前截图转换为NumPy数组
        last_screenshot_array = np.array(last_screenshot)  # 将上一次截图转换为NumPy数组

        # 计算监控区域的像素值差异
        pixel_diff = np.sum(current_screenshot_array != last_screenshot_array)  # 计算两张截图像素差异的总和

        # 检查像素值差异是否超过阈值(根据具体情况调整阈值)
        threshold = 1000  # 示例阈值,根据实际情况调整
        if pixel_diff > threshold:  # 如果像素值差异超过阈值,则表示屏幕发生了变化
            # 生成截图文件名
            screenshot_filename = f"screenshot_{int(time.time())}.png"  # 根据当前时间生成截图文件名
            screenshot_path = os.path.join(screenshot_folder, screenshot_filename)  # 拼接截图文件路径

            # 保存截图
            current_screenshot.save(screenshot_path)  # 将当前截图保存为图片文件

            # 输出截图信息
            print(f"Screenshot saved: {screenshot_path}")  # 打印截图保存路径

            # 更新上一次截图
            last_screenshot = current_screenshot  # 将当前截图赋值给上一次截图,以便下一次比较

        # 每隔一定时间进行一次截图
        time.sleep(5)  # 5秒钟检查一次屏幕变化,可根据需要调整
except KeyboardInterrupt:  # 捕获键盘中断异常,用于停止监控
    print("Monitoring stopped.")  # 打印停止监控的提示信息
复制代码

 

  分类: Python , Windows , 自动截屏 标签: python , 开发语言   监控一个界面的内容变化,以确保自己能第一时间留意到,总不能一直看着吧?
于是我写了一个Python脚本去帮我看。原理就是实时获取界面像素,只要像素变化,代表界面有变化。

jiankong.py

[Python] 纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 from PIL import ImageGrab import numpy as np import time import requests  # Import the requests library   def get_screen_region_screenshot(region):     """     获取屏幕指定区域的截图     """     screenshot = ImageGrab.grab(bbox=region)     return np.array(screenshot)   def send_http_request():     """     发送HTTP请求的函数     """     # 替换接收通知的Url,我这里使用的是iOS的Bark App     url = "https://xxxxxxxxxxxxxxxx"     payload = {"key": "value"}     headers = {"Content-Type": "application/json"}       response = requests.post(url, json=payload, headers=headers)       # 打印结果     print("HTTP Response:", response.text)   def monitor_screen_region_changes(region, polling_interval=1):     """     监控屏幕指定区域的像素变化     """     previous_screenshot = get_screen_region_screenshot(region)       while True:         current_screenshot = get_screen_region_screenshot(region)           if not np.array_equal(previous_screenshot, current_screenshot):             print("指定区域的像素发生变化")             # 发送HTTP请求             send_http_request()               # 更新前一次的截图             previous_screenshot = current_screenshot           time.sleep(polling_interval)   if __name__ == "__main__":       # 替换为要监控的区域坐标 (left, top, right, bottom)     # left:左上角距离屏幕左侧的距离(像素)     # top:左上角距离屏幕上方的距离(像素)     # right:右下角距离屏幕左侧的距离(像素)     # bottom:右下角距离屏幕上方的距离(像素)     region_to_monitor = (0, 0, 100, 100)           monitor_screen_region_changes(region_to_monitor)


如何获得坐标?截图软件一般都有标注像素。

 

运行



接收通知:           Python的GUI应用,用于实时监控屏幕区域的图片变化,并通过图像哈希比较来检测相似度变化,触发警报。它利用Tkinter、PyAutoGUI和PIL库进行图像处理,以及pygame库处理声音。 摘要由CSDN通过智能技术生成

代码拿走就能跑

很乱 才开始学

import sys
import tkinter as tk
#创建图形用户界面(GUI)的标准库
import time
import cv2
#图片处理库
#import numpy as np
import pyautogui
#键鼠库
import pygame
#播放声音用,这个库有点大,但是我测试其他3个库 都不好使,只能用这个
from PIL import Image, ImageTk
#图像处理库
import threading
#线程库
from datetime import datetime
#时间库
start_x, start_y, end_x, end_y = None, None, None, None
#选取的区域坐标
from imagehash import average_hash
pinlv=2  #监控频率 第二版是把图片读取到内存操作 所以可以每秒一次
import io
should_exit = False
im0imagehas=0 #选区的hash值 用全局
isarm=False
i=0 
def print_to_text(*args):
    global i
    global isarm
    i=i+1
    if 8 < i :
        text_widget.delete(1.0, tk.END)#执行8次后清空一下txt,让txt一直滚动 方便进行监控
        i=0
    for arg in args:
        
        if not isarm:
            text_widget.tag_configure('red_text', foreground='blue')#正常字体
        if isarm :
            text_widget.tag_configure('red_text', foreground='red')#报警为红色
        text_widget.insert('end', str(arg), 'red_text' )
    text_widget.insert('end','\n')
    text_widget.yview_scroll(1, 'units')  # 向下滚动一格
# 将print的输出重定向到text_widget
print = print_to_text.__get__(None, print)
# 这将全局print函数绑定到text_widget

#按坐标获取切图
def qie_tu(img01=None):
    global start_x, start_y, end_x, end_y
    global disktoptu

    # 使用pyautogui进行屏幕截图
    screenshot = pyautogui.screenshot()
    #screenshot.save('temp.png', format='png')
    # 使用BytesIO将图像保持到内存中
    crop_bytes0 = io.BytesIO()
    screenshot.save(crop_bytes0, format='png')
    # 读取到内存中的图像数据
    crop_bytes0 = crop_bytes0.getvalue()
    # 打开图像
    img = Image.open(io.BytesIO(crop_bytes0))
    # 截取部分图像
    disktoptu=img
    crop = img.crop((start_x,start_y ,end_x, end_y))
    # 使用BytesIO将图像保持到内存中
    crop_bytes = io.BytesIO()
    crop.save(crop_bytes, format='png')
    # 读取到内存中的图像数据
    crop_bytes = crop_bytes.getvalue()
    # 对内存中的图像进行处理,例如调整大小
    # 这里使用的是PIL库的Image类,你可以根据需要进行其他操作
    im0 = Image.open(io.BytesIO(crop_bytes))
    # 如果需要,你可以在此处进行其他操作,例如旋转、裁剪等。
    # 在完成所有操作后,你可以使用下面的代码将图像保存到磁盘。

    imimagehash=average_hash(im0)#image hash
    img.save('desktop_screenshot.png', format='png')  # 将处理后的图像保存到磁盘
    if img01 != None:
        im0.save(img01, format='png')  # 将处理后的图像保存到磁盘
    return (str(imimagehash))

#鼠标选区并截取
def select_screen_region():
    load_alarm_sound("警报声.mp3")#放到这里防止错误提示终止运行
    text_widget.delete(1.0, tk.END)
    print('点击选区后,进入选区模式,'+'\n''最下面出现红色按钮才可以开始选区,'+'\n''选区后点击红色按钮退出选区模式')
    btn_xq.config(state=tk.DISABLED)#点击开始选区后 不可以重复点击 ,需要暂停后再次启动
    btn_start.config(state=tk.DISABLED)#开始按键停用
   
    global start_x, start_y, end_x, end_y
    global im0imagehas

    def on_press(event):
        global start_x, start_y
        start_x, start_y = event.x, event.y

    def on_move(event):
        global end_x, end_y
        end_x, end_y = event.x, event.y
        canvas.coords(rect, start_x, start_y, end_x, end_y)

    def on_release(event):
        global end_x, end_y
        end_x, end_y = event.x, event.y
        canvas.coords(rect, start_x, start_y, end_x, end_y)

    root1 = tk.Toplevel(root)
    root1.title("选择监控区域")
    root1.attributes('-fullscreen', True) #设置全屏模式
        
    screenshot = pyautogui.screenshot() #截屏
    screenshot.save('desktop_screenshot.png', format='png')

    canvas = tk.Canvas(root1, bg='white') #创建画布
    canvas.pack(fill=tk.BOTH, expand=True)#添加画布并填充

    desktop_image = ImageTk.PhotoImage(file='desktop_screenshot.png')#创建图片对象
    canvas.create_image(0, 0, anchor=tk.NW, image=desktop_image)#在画布上添加图片

    rect = canvas.create_rectangle(0, 0, 0, 0, outline='red')#创建矩形对象

    canvas.bind("<ButtonPress-1>", on_press)
    canvas.bind("<B1-Motion>", on_move)
    canvas.bind("<ButtonRelease-1>", on_release)
    
    def close_window():  # 新增的关闭窗口函数
        global im0imagehas
        if start_x== None:
            text_widget.delete(1.0, tk.END)
            print("请选定区域后再退出"+'\n'+'\n')
            print('点击选区后,进入选区模式,'+'\n''最下面出现红色按钮才可以开始选区,'+'\n''选区后点击红色按钮退出选区模式。')
        else:
            #im0imagehas = qie_tu('0.png') 在这里切图会再次抓屏 把那条红线抓进来
            img = Image.open('desktop_screenshot.png')
            crop = img.crop((start_x,start_y ,end_x, end_y))
            #crop.save('0.png', format='png')
            # 使用BytesIO将图像保持到内存中
            crop_bytes = io.BytesIO()
            crop.save(crop_bytes, format='png')
            im0imagehas=average_hash(crop)
            text_widget.delete(1.0, tk.END)
            print('成功抓取所选区域 可以开始监控')
            btn_start.config(state=tk.NORMAL)#成功抓取区域图片后,才可以开始监控
            root1.destroy()  # 使用Tkinter的destroy()方法关闭窗口
   
    button_close = tk.Button(root1, text=",选择需要监控的区域后,点击此关闭", fg="red", command=close_window)  # 创建关闭按钮
    button_close.pack()
    root1.mainloop()

# 初始化pygame库
pygame.init()
pygame.mixer.init()

# 全局变量,加载MP3文件
def load_alarm_sound(file_path):
    try:
        pygame.mixer.music.load(file_path)
    except pygame.error:
        print(f"无法加载音频文件:{file_path}")

# 封装一个播放MP3警报的函数
def play_alarm():
    try:
        # 播放MP3文件
        pygame.mixer.music.play()
    except pygame.error:
        print("播放警报音频失败")

def monitor(data_source):
    global pinlv
    global should_exit
    global isarm
    global im0imagehas

    while not should_exit:
            current_time = datetime.now()
            time_string = current_time.strftime("%H:%M:%S")
            #im1imagehas = qie_tu('1.png')
            im1imagehas = qie_tu()

            #print('im0imagehas:',str(im0imagehas))
            #print('im1imagehas:',str(im1imagehas))


            if str(im0imagehas) != str(im1imagehas) :
                print(time_string,'  相似度有变化,进行报警!')
                play_alarm()
                isarm=True
            else:
                print(time_string,'  相似度没有变化')
                isarm=False

            time.sleep(pinlv)  # 等待5秒后再获取下一帧
            
    if should_exit and suspend :
        print('暂停监控')
    else :
        cv2.destroyAllWindows()

def start_recognition():
    btn_start.config(state=tk.DISABLED)
    btn_suspend.config(state=tk.NORMAL)
    global should_exit
    global suspend
    suspend = False
    should_exit = False
    print("开始监控")
    th_monitor = threading.Thread(target=monitor, args=("screenshot",))
    th_monitor.daemon = True
    th_monitor.start()

def suspend_recognition():
    btn_xq.config(state=tk.NORMAL)
    btn_start.config(state=tk.NORMAL)
    btn_suspend.config(state=tk.DISABLED)
    global suspend
    global should_exit
    should_exit = True
    suspend=True


def end_program():
    global should_exit
    should_exit = True
    print("结束监控")
    sys.exit(1)
# 创建主窗口
root = tk.Tk()
root.title("监控报警")
root.wm_attributes('-topmost', True)
root.protocol("WM_DELETE_WINDOW",end_program)

#计算屏幕中央的位置
x = int((root.winfo_screenwidth() - root.winfo_reqwidth()) / 2)
y = int((root.winfo_screenheight() - root.winfo_reqheight()) / 2)
#将窗口居中显示
root.geometry("+{}+{}".format(x, y))

text_widget = tk.Text(root, width=55, height=10) # 设置文本框的最小宽度为40个字符,最小高度为10行
#text_widget.grid(column=0, row=0, width=10)  # 在grid中设置文本框的宽度为10个字符
text_widget.pack()

# 添加按钮
print('点击选区后,进入选区模式,'+'\n''最下面出现红色按钮才可以开始选区,'+'\n''选区后点击红色按钮退出选区模式。')
btn_xq = tk.Button(root, text="开始选区", command=select_screen_region)
btn_start = tk.Button(root, text="开始监控", command=start_recognition)
btn_suspend = tk.Button(root, text="暂停监控", command=suspend_recognition)
btn_end = tk.Button(root, text="结束监控", command=end_program)

#btn_start.config(state=tk.DISABLED)
# 使用pack布局并设置side参数为LEFT实现横向排列

btn_suspend.config(state=tk.DISABLED)#暂停按键停用
btn_start.config(state=tk.DISABLED)#开始按键停用

btn_xq.pack(side=tk.LEFT, padx=10, pady=10)
btn_start.pack(side=tk.LEFT, padx=10, pady=10)
btn_suspend.pack(side=tk.LEFT, padx=10, pady=10)
btn_end.pack(side=tk.LEFT, padx=10, pady=10)

# 创建一个下拉列表变量
root.var = tk.StringVar(root)
# 设置下拉列表的默认值
root.var.set("监控频率默认2秒次")
# 定义下拉列表的选项
options = ["1秒次", "5秒次", "10秒次", "20秒次", "30秒次"]
# 创建下拉列表
dropdown = tk.OptionMenu(root, root.var, *options)
# 将下拉列表放置到主窗口
dropdown.pack()

def option_selected(*args):
    global pinlv
    text_widget.delete(1.0, tk.END)
    print(f"选项 {root.var.get()} 被选择了!")
    if root.var.get() == "1秒次" :
        pinlv=1
    if root.var.get() == "5秒次" :
        pinlv=5
    if root.var.get() == "10秒次" :
        pinlv=10
    if root.var.get() == "20秒次" :
        pinlv=20
    if root.var.get() == "30秒次" :
        pinlv=30
root.var.trace("w", option_selected)
    
# 进入事件循环
root.mainloop()


 

  文章知识点与官方知识档案匹配,可进一步学习相关知识

标签:截图,end,screenshot,Python,GUI,start,tk,屏幕,root
From: https://www.cnblogs.com/xinxihua/p/18537744

相关文章

  • python实战(七)——基于LangChain的RAG实践
    一、任务目标    基于之前的RAG实战,相信大家对RAG的实现已经有了一定的了解了。这篇文章将使用LangChain作为辅助,实现一个高效、便于维护的RAG程序。二、什么是LangChain        LangChain是一个用于构建大模型应用程序的开源框架,它内置了多个模块化组件。......
  • 综合能源系统分析的统一能路理论(三):《稳态与动态潮流计算》(Python代码实现)
     ......
  • Google Earth Engine Python——PyGEE-SWToolbox地表水分析工具箱
    目录简介功能安装使用方法代码引用BibTeXifrequired:致谢简介一个用于使用GoogleEarthEngine进行交互式地表水映射和分析的PythonJupyter笔记本工具箱        PyGEE-SWToolbox是一个Python-GoogleEarthEngine(GEE)地表水分析工具箱,开发于Jupyter......
  • 100种算法【Python版】第60篇——滤波算法之粒子滤波
    本文目录1算法步骤2算法示例:多目标跟踪3算法应用:多维非线性系统状态模拟粒子滤波(ParticleFilter)是一种基于随机采样的贝叶斯滤波方法,广泛应用于动态系统的状态估计。它通过在状态空间中使用一组随机粒子(样本)来表示后验分布,从而处理非线性和非高斯的状态估计问......
  • 【PAT_Python解】1120 买地攻略
    原题链接:PTA|程序设计类实验辅助教学平台Tips:以下Python代码仅个人理解,非最优算法,仅供参考!多学习其他大佬的AC代码!defcount_purchase_options(N,M,prices):start=0current_sum=0total_count=0forendinrange(N):current_sum+=......
  • 【PAT_Python解】1115 裁判机
    原题链接:PTA|程序设计类实验辅助教学平台Tips:以下Python代码仅个人理解,非最优算法,仅供参考!多学习其他大佬的AC代码!测试点5:passd有9994个不同的有效数值测试点6:is_given有157386个不同的差值AC代码:importsysdefis_pass(num,is_given,passed_numbers,passed_en......
  • 计算机毕业设计Python+大模型动漫推荐系统 动漫视频推荐系统 机器学习 协同过滤推荐算
    作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业......
  • 计算机毕业设计Python+大模型农产品价格预测 ARIMA自回归模型 农产品可视化 农产品爬
    作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业......
  • jsonargparse python cli 开发库
    jsonargparse是一个pythoncli库,尽管不如其他库火(click)目前Lightningcli就使用了此库包含的特性自动创建cli类似Fire,typer,Clize以及Tyro支持类型校验支持通过配置文件或者环境变量的配置解析(集成confuse,configargparse,dynaconf,omegaconf)dataclass支持说明jsonargpa......
  • 华为OD机试2024年E卷-MVP争夺战[100分]( Java | Python3 | C++ | C语言 | JsNode | Go
    题目描述在星球争霸篮球赛对抗赛中,最大的宇宙战队希望每个人都能拿到MVP,MVP的条件是单场最高分得分获得者。可以并列所以宇宙战队决定在比赛中尽可能让更多队员上场,并且让所有得分的选手得分都相同,然而比赛过程中的每1分钟的得分都只能由某一个人包揽。输入描述输入第一行......