自制 Windows 小工具 ———— 智能截屏工具
自制 Windows 小工具 ———— 智能截屏工具
- 背景
- 需求分析
- 环境准备
- 功能实现
- 获取截图区域
- 获取文件保存路径
- 图像算法
- 截屏
- 快捷启动
背景
上网课期间,很多同学(包括老师)都会选择(提倡)截屏来记录笔记,然后课后再进行整理。但是往往越截越多,到后来干脆每张都截,课后面对几十张的照片直接泄了气,不写了。另外有些同学,继续保持在课堂上的习惯,手写笔记。但是没了黑板的帮助,老师又默认PPT上的重点大家都会截图,往往过的非常快,手写时间根本不够,最后笔记跟不上,越落越多,最后也泄了气,不写了
那么,如果既想截图,又想快速写笔记,还想着摸鱼,该怎么办呢?
当然是制作工具了 ———— 智能截屏
需求分析
- 将老师的重点截屏(不能遗漏)
- 尽量避免重复的图片,方便课后整理
- 操作简单智能(上课时不需要监管程序)
环境准备
- python
- pyautogui
- opencv
- numpy
- PIL
后面的几项都是第三方库,直接pip
即可,大家自行百度
功能实现
获取截图区域
既让要操作简单,那么图形化必然少不了,用户也可能需要自己设置截图区域
这里和上一篇文章的截图部分很像,就不做过多分析
代码大家自行研究,还是封装一个模块ScreenArea.py
import tkinter as tk
import pyautogui#鼠标左键按下
def button_1(event):global x, y ,xstart,ystartx, y = event.x, event.yxstart,ystart = event.x, event.yxstart,ystart = event.x, event.y cv.configure(height=1)cv.configure(width=1)cv.place(x=event.x, y=event.y)#鼠标左键按下并移动
def b1_Motion(event):global x, yx, y = event.x, event.yglobal cvcv.configure(height = event.y - ystart)cv.configure(width = event.x - xstart)#鼠标左键松开
def buttonRelease_1(event):global x, y,xstart,ystartx, y = event.x, event.yif x == xstart and y == ystart:returnglobal cvglobal rootPstart=[0,0]cv.place_forget()root.attributes("-alpha", 0) root.destroy()# 退出
def sys_out(even = True):global root#from tkinter import messagebox#if messagebox.askokcancel('Exit','Confirm to exit?'):root.destroy()def SelectArea():global rootroot = tk.Tk()root.overrideredirect(True) # 隐藏窗口的标题栏# root.attributes("-alpha", 0.3) # 窗口透明度70 %root.attributes("-alpha", 0.3) # 窗口透明度60 %root.attributes("-topmost", 1)#root.geometry("300x200+10+10") # 设置窗口大小与位置root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))root.configure(bg="black")# 再创建1个Canvas用于圈选global cv, x, y, xstart, ystartcv = tk.Canvas(root)x, y = 0, 0xstart,ystart = 0 ,0# 绑定事件到Esc键,当按下Esc键就会调用sys_out函数,弹出对话框root.bind('<Escape>',sys_out)root.bind("<Button-1>", button_1)root.bind("<B1-Motion>", b1_Motion)root.bind("<ButtonRelease-1>", buttonRelease_1)root.mainloop()return (xstart,ystart,x - xstart,y - ystart) # 左上角坐标,宽,高if __name__ == "__main__":print(SelectArea())
获取文件保存路径
虽然智能过滤了相似的图片,但是图片量仍然很大,所以要让用户可以自行选择保存路径
使用 tkinter
的文件选择框 主程序 screenAI.py
中 实现
import screenArea
from tkinter import filedialog
import timedef StartscreenAI(): # 一会儿可以绑定快捷键global x,y,width,heightx,y,width,height = screenArea.SelectArea() # 获取截图区域global save_pathsave_path = filedialog.askdirectory()print(save_path)if __name__ == "__main__":time.sleep(3) # 给操作者一个反应的时间StartscreenAI()
图像算法
这里为了过滤相似的图片,我们用到了一些图像处理算法,为了更加精确和灵活,我一下采用了五种算法
- 均值哈希算法
- 差值哈希算法
- 感知哈希算法
- 灰度直方图算法
- RGB每个通道的直方图相似度
五个算法根据场景进行加权平均得到相似值。这里封装一个模块进行实现 imageAI.py
import cv2
import numpy as npN = 16 # 压缩程度,越大越精确,但是空间和时间越多 注意为 2 的次幂def aHash(img):# 均值哈希算法# 缩放为N*Nglobal Nimg = cv2.resize(img, (N, N))# 转换为灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# s为像素和初值为0,hash_str为hash值初值为''s = 0hash_str = ''# 遍历累加求像素和for i in range(N):for j in range(N):s = s+gray[i, j]# 求平均灰度avg = s/N/N# 灰度大于平均值为1相反为0生成图片的hash值for i in range(N):for j in range(N):if gray[i, j] > avg:hash_str = hash_str+'1'else:hash_str = hash_str+'0'return hash_strdef dHash(img):global N# 差值哈希算法# 缩放N * Nimg = cv2.resize(img, (N + 1, N))# 转换灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)hash_str = ''# 每行前一个像素大于后一个像素为1,相反为0,生成哈希for i in range(N):for j in range(N):if gray[i, j] > gray[i, j+1]:hash_str = hash_str+'1'else:hash_str = hash_str+'0'return hash_strdef pHash(img):# 感知哈希算法# 缩放4n * 4nglobal Nimg = cv2.resize(img, (4 * N, 4 * N)) # , interpolation=cv2.INTER_CUBIC# 转换为灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 将灰度图转为浮点型,再进行dct变换dct = cv2.dct(np.float32(gray))# opencv实现的掩码操作dct_roi = dct[0:N, 0:N]hash = []avreage = np.mean(dct_roi)for i in range(dct_roi.shape[0]):for j in range(dct_roi.shape[1]):if dct_roi[i, j] > avreage:hash.append(1)else:hash.append(0)return hashdef cmpHash(hash1, hash2):# Hash值对比# 算法中1和0顺序组合起来的即是图片的指纹hash。顺序不固定,但是比较的时候必须是相同的顺序。# 对比两幅图的指纹,计算汉明距离,即两个64位的hash值有多少是不一样的,不同的位数越小,图片越相似# 汉明距离:一组二进制数据变成另一组数据所需要的步骤,可以衡量两图的差异,汉明距离越小,则相似度越高。汉明距离为0,即两张图片完全一样N = 0# hash长度不同则返回-1代表传参出错if len(hash1) != len(hash2):return -1# 遍历判断for i in range(len(hash1)):# 不相等则n计数+1,n最终为相似度if hash1[i] != hash2[i]:N = N + 1return Ndef calculate(image1, image2):# 灰度直方图算法# 计算单通道的直方图的相似值hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])# 计算直方图的重合度degree = 0for i in range(len(hist1)):if hist1[i] != hist2[i]:degree = degree + \(1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))else:degree = degree + 1degree = degree / len(hist1)return float(degree)def classify_hist_with_split(image1, image2, size=(256, 256)):# RGB每个通道的直方图相似度# 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值image1 = cv2.resize(image1, size)image2 = cv2.resize(image2, size)sub_image1 = cv2.split(image1)sub_image2 = cv2.split(image2)sub_data = 0for im1, im2 in zip(sub_image1, sub_image2):sub_data += calculate(im1, im2)sub_data = sub_data / 3return float(sub_data)
截屏
在主程序中控制截图与保存 screenAI.py
import screenArea
import imageAI
from tkinter import filedialog
import time
import os
import cv2
import numpy as np
import pyautoguidef ScreenCut():global x,y,width,heightreturn pyautogui.screenshot(region = (x,y,width,height))def SaveFile(img):global pic_cntglobal save_pathpic_cnt += 1print('保存了图片',save_path + '/' + str(pic_cnt) + '.png')img.save(save_path + '/' + str(pic_cnt) + '.png')def StartscreenAI(): # 一会儿可以绑定快捷键global x,y,width,heightx,y,width,height = screenArea.SelectArea() # 获取截图区域global save_pathtry:save_path = filedialog.askdirectory()except:print('已取消')returnglobal pic_cntpic_cnt = 0try:filenames = os.listdir(save_path)except:print('已取消(或无效路径)')returnfor filename in filenames:try:if pic_cnt < int(filename.replace('.png','')):pic_cnt = int(filename.replace('.png',''))except:pass# 一个小小的优化,自动找到未被使用的编号,防止多次启动覆盖lstimg = ScreenCut()lstcv2img = cv2.cvtColor(np.asarray(lstimg), cv2.COLOR_RGB2BGR)lstdhash = imageAI.dHash(lstcv2img)lstahash = imageAI.aHash(lstcv2img)lstphash = imageAI.pHash(lstcv2img)SaveFile(lstimg)global SCREENCUTSCREENCUT = Truewhile SCREENCUT:nowimg = ScreenCut()nowcv2img = cv2.cvtColor(np.asarray(nowimg), cv2.COLOR_RGB2BGR)nowdhash = imageAI.dHash(nowcv2img)nowahash = imageAI.aHash(nowcv2img)nowphash = imageAI.pHash(nowcv2img)nowcalculate = round(imageAI.calculate(nowcv2img,lstcv2img),8)nowclassify_hist_with_split = imageAI.classify_hist_with_split(nowcv2img,lstcv2img)dn1 = imageAI.cmpHash(lstdhash,nowdhash)an1 = imageAI.cmpHash(lstahash,nowahash)pn1 = imageAI.cmpHash(lstphash,nowphash)arv = ((imageAI.N * imageAI.N - dn1) / imageAI.N / imageAI.N * 2 + (imageAI.N * imageAI.N - an1) / imageAI.N / imageAI.N + (imageAI.N * imageAI.N - pn1) / imageAI.N / imageAI.N + nowcalculate) / 5 # PPT 的较好算法if arv < 0.85: # ppt的较好参数SaveFile(nowimg)lstcv2img = nowcv2imglstdhash = nowdhashlstahash = nowahashlstphash = nowphashif __name__ == "__main__":time.sleep(3) # 给操作者一个反应的时间StartscreenAI()
到目前为止,一次启动已经做好
快捷启动
接下来,为了多课程之间的切换和停止,我们给程序增加一些快捷键 screenAI.py
注意,因为StartscreenAI
中有死循环,会影响keyboard
的循环,所以要停止的检测要在while
循环中用is_pressed
import screenArea
import imageAI
from tkinter import filedialog
import time
import os
import cv2
import numpy as np
import pyautogui
import keyboard
import threadingSCREENCUT = Falsedef ScreenCut():global x,y,width,heightreturn pyautogui.screenshot(region = (x,y,width,height))def SaveFile(img):global pic_cntglobal save_pathpic_cnt += 1print('保存了图片',save_path + '/' + str(pic_cnt) + '.png')img.save(save_path + '/' + str(pic_cnt) + '.png')def StartscreenAI(): # 一会儿可以绑定快捷键global SCREENCUTif SCREENCUT != False:print('已开始,ctrl+alt+e 停止')returnglobal x,y,width,heightx,y,width,height = screenArea.SelectArea() # 获取截图区域global save_pathtry:save_path = filedialog.askdirectory()except:print('已取消')returnglobal pic_cntpic_cnt = 0try:filenames = os.listdir(save_path)except:print('已取消(或无效路径)')returnfor filename in filenames:try:if pic_cnt < int(filename.replace('.png','')):pic_cnt = int(filename.replace('.png',''))except:passprint('选择了路径: %s 已有编号 %d' % (save_path,pic_cnt))# 一个小小的优化,自动找到未被使用的编号,防止多次启动覆盖lstimg = ScreenCut()lstcv2img = cv2.cvtColor(np.asarray(lstimg), cv2.COLOR_RGB2BGR)lstdhash = imageAI.dHash(lstcv2img)lstahash = imageAI.aHash(lstcv2img)lstphash = imageAI.pHash(lstcv2img)SaveFile(lstimg)SCREENCUT = Truewhile SCREENCUT:if keyboard.is_pressed('ctrl+alt+e'):SCREENCUT = Falsenowimg = ScreenCut()nowcv2img = cv2.cvtColor(np.asarray(nowimg), cv2.COLOR_RGB2BGR)nowdhash = imageAI.dHash(nowcv2img)nowahash = imageAI.aHash(nowcv2img)nowphash = imageAI.pHash(nowcv2img)nowcalculate = round(imageAI.calculate(nowcv2img,lstcv2img),8)nowclassify_hist_with_split = imageAI.classify_hist_with_split(nowcv2img,lstcv2img)dn1 = imageAI.cmpHash(lstdhash,nowdhash)an1 = imageAI.cmpHash(lstahash,nowahash)pn1 = imageAI.cmpHash(lstphash,nowphash)arv = ((imageAI.N * imageAI.N - dn1) / imageAI.N / imageAI.N * 2 + (imageAI.N * imageAI.N - an1) / imageAI.N / imageAI.N + (imageAI.N * imageAI.N - pn1) / imageAI.N / imageAI.N + nowcalculate) / 5 # PPT 的较好算法if arv < 0.85: # ppt的较好参数SaveFile(nowimg)lstcv2img = nowcv2imglstdhash = nowdhashlstahash = nowahashlstphash = nowphashprint('截图已结束')if __name__ == "__main__":keyboard.add_hotkey('ctrl+alt+b',StartscreenAI)keyboard.wait()
大功告成,希望可以帮助到专心学习的你
希望大家在评论区分享更好的做法
希望大家关注,评论,点赞哦
自制 Windows 小工具 ———— 智能截屏工具相关推荐
- 自制 Windows 小工具 ———— 文字识别助手
自制 Windows 小工具 ---- 文字识别助手 背景 问题分析 工具准备 第一部分:屏幕截图的实现 文字识别 结果展示 保持原格式 事件绑定 背景 使用电脑的时候经常遇到图片上满是文字,想复制却 ...
- Windows CE/Moblie截屏工具及实现源码
Windows CE/Moblie截屏工具及实现源码 [img]http://dl2.iteye.com/upload/attachment/0084/6997/c72941f2-b86e-3683- ...
- 截屏工具Snipaste使用指南
Snipaste 是一个简单但强大的贴图工具,同时也可以执行截屏.标注等功能. 开始截图 快捷键(默认为 F1) 鼠标左键 单击托盘图标 何为一次成功的截图 保存到剪贴板 ( Ctrl + C / E ...
- 绿色抓屏截屏工具:FastStoneCapture
FastStoneCapture下载 软件是绿色版本,下载后直接打开即可 链接:绿色抓屏截屏工具FastStoneCapture下载地址 提取码:ebxy FastStoneCapture安装 下载后 ...
- mac idea用自带的maven还是_苹果电脑自带截图工具怎么用?mac自带截屏工具使用技巧分享
一说到截图工具我们脑袋里最先跳出来应该是 QQ 和微信等社交软件自带的截图工具,这里小编为大家推荐的是经常被忽昭略的mac自带截屏工具.也许你想不到苹果自带截图工具功能是十分的强大的. mac自带截屏 ...
- java浏览器无界面后台截屏工具
不同于上一篇文章中所讲到的通过客户端浏览器将 HTML 转 canvas 再生成图片的方式,本次记录的内容为服务器端(Windows Server)截屏工具.该工具特点为:通过 java 代码调用无界 ...
- 截屏工具 HyperSnap
听说Tencent开发了1款截屏工具,叫"snip".确实字体效果不错,但是丫只有for mac的,不知道脑子里怎么想的,该不是直接买了第三方的然后冠了个名儿吧. 那么Windows有没有类似的工具呢 ...
- winsmac最强滚动截屏工具
Snagit是跨平台截屏工具,目前只支持Mac和Windows. 下载安装 Download 如何滚动截屏 打开如下设置即可. 深度截图for ubuntu # sudo apt install de ...
- UEFI开发探索99 – UEFI Shell下截屏工具
(请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) UEFI Shell下截屏工具 1 PrintScreenLogger的代码结构 1)Print ...
最新文章
- mysql并发提交事务_Mysql事务并发问题解决方案
- MySQL基本操作及乱码问题的解决方法
- jq修改导航栏样式(选中、使用两张图片替代的是否选中效果)
- 原始人java生存游戏_原始人人生模拟器
- redis aof持久化遇到的Can't open the append-only file Permissi
- padodb time.inc.php,怎样实现PHP中ADODB事务处理
- react admin项目部署到tomcat_一个tomcat同时部署多个项目
- ofdm误码率仿真代码_共享源代码之MSK仿真(1)
- Node单线程高并发原理
- 计算机辅助设计工业产品cad竞赛试题,2017工业产品设计CAD比赛试题
- 递归解决换零钱问题--代码实现
- ideaIU-2019.2.4版安装
- 光线:提高照片的艺术感
- REASONING ABOUT ENTAILMENT WITH NEURAL ATTENTION 论文阅读笔记
- 强连通基础与例题(Kosaraju算法与Tarjan算法)
- linux 万能五笔安装
- 补码,数据溢出变负的原因
- Struts——开源MVC框架
- javascript操作数组的方法大全
- 应用检查后台启动权限方法(小米官方给出的)