自制 Windows 小工具 ———— 智能截屏工具

  • 背景
  • 需求分析
  • 环境准备
  • 功能实现
    • 获取截图区域
    • 获取文件保存路径
    • 图像算法
    • 截屏
    • 快捷启动

背景

上网课期间,很多同学(包括老师)都会选择(提倡)截屏来记录笔记,然后课后再进行整理。但是往往越截越多,到后来干脆每张都截,课后面对几十张的照片直接泄了气,不写了。另外有些同学,继续保持在课堂上的习惯,手写笔记。但是没了黑板的帮助,老师又默认PPT上的重点大家都会截图,往往过的非常快,手写时间根本不够,最后笔记跟不上,越落越多,最后也泄了气,不写了
那么,如果既想截图,又想快速写笔记,还想着摸鱼,该怎么办呢?
当然是制作工具了 ———— 智能截屏

需求分析

  1. 将老师的重点截屏(不能遗漏)
  2. 尽量避免重复的图片,方便课后整理
  3. 操作简单智能(上课时不需要监管程序)

环境准备

  • 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()

图像算法

这里为了过滤相似的图片,我们用到了一些图像处理算法,为了更加精确和灵活,我一下采用了五种算法

  1. 均值哈希算法
  2. 差值哈希算法
  3. 感知哈希算法
  4. 灰度直方图算法
  5. 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 小工具 ———— 智能截屏工具相关推荐

  1. 自制 Windows 小工具 ———— 文字识别助手

    自制 Windows 小工具 ---- 文字识别助手 背景 问题分析 工具准备 第一部分:屏幕截图的实现 文字识别 结果展示 保持原格式 事件绑定 背景 使用电脑的时候经常遇到图片上满是文字,想复制却 ...

  2. Windows CE/Moblie截屏工具及实现源码

    Windows CE/Moblie截屏工具及实现源码 [img]http://dl2.iteye.com/upload/attachment/0084/6997/c72941f2-b86e-3683- ...

  3. 截屏工具Snipaste使用指南

    Snipaste 是一个简单但强大的贴图工具,同时也可以执行截屏.标注等功能. 开始截图 快捷键(默认为 F1) 鼠标左键 单击托盘图标 何为一次成功的截图 保存到剪贴板 ( Ctrl + C / E ...

  4. 绿色抓屏截屏工具:FastStoneCapture

    FastStoneCapture下载 软件是绿色版本,下载后直接打开即可 链接:绿色抓屏截屏工具FastStoneCapture下载地址 提取码:ebxy FastStoneCapture安装 下载后 ...

  5. mac idea用自带的maven还是_苹果电脑自带截图工具怎么用?mac自带截屏工具使用技巧分享

    一说到截图工具我们脑袋里最先跳出来应该是 QQ 和微信等社交软件自带的截图工具,这里小编为大家推荐的是经常被忽昭略的mac自带截屏工具.也许你想不到苹果自带截图工具功能是十分的强大的. mac自带截屏 ...

  6. java浏览器无界面后台截屏工具

    不同于上一篇文章中所讲到的通过客户端浏览器将 HTML 转 canvas 再生成图片的方式,本次记录的内容为服务器端(Windows Server)截屏工具.该工具特点为:通过 java 代码调用无界 ...

  7. 截屏工具 HyperSnap

    听说Tencent开发了1款截屏工具,叫"snip".确实字体效果不错,但是丫只有for mac的,不知道脑子里怎么想的,该不是直接买了第三方的然后冠了个名儿吧. 那么Windows有没有类似的工具呢 ...

  8. winsmac最强滚动截屏工具

    Snagit是跨平台截屏工具,目前只支持Mac和Windows. 下载安装 Download 如何滚动截屏 打开如下设置即可. 深度截图for ubuntu # sudo apt install de ...

  9. UEFI开发探索99 – UEFI Shell下截屏工具

    (请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) UEFI Shell下截屏工具 1 PrintScreenLogger的代码结构 1)Print ...

最新文章

  1. mysql并发提交事务_Mysql事务并发问题解决方案
  2. MySQL基本操作及乱码问题的解决方法
  3. jq修改导航栏样式(选中、使用两张图片替代的是否选中效果)
  4. 原始人java生存游戏_原始人人生模拟器
  5. redis aof持久化遇到的Can't open the append-only file Permissi
  6. padodb time.inc.php,怎样实现PHP中ADODB事务处理
  7. react admin项目部署到tomcat_一个tomcat同时部署多个项目
  8. ofdm误码率仿真代码_共享源代码之MSK仿真(1)
  9. Node单线程高并发原理
  10. 计算机辅助设计工业产品cad竞赛试题,2017工业产品设计CAD比赛试题
  11. 递归解决换零钱问题--代码实现
  12. ideaIU-2019.2.4版安装
  13. 光线:提高照片的艺术感
  14. REASONING ABOUT ENTAILMENT WITH NEURAL ATTENTION 论文阅读笔记
  15. 强连通基础与例题(Kosaraju算法与Tarjan算法)
  16. linux 万能五笔安装
  17. 补码,数据溢出变负的原因
  18. Struts——开源MVC框架
  19. javascript操作数组的方法大全
  20. 应用检查后台启动权限方法(小米官方给出的)

热门文章

  1. C语言 字符串数组 的输入 总结
  2. 第二次C程序设计上机报告
  3. 为什么信息熵要定义成-Σp*log(p)?
  4. 更换人工晶体的最佳时期是什么时候?
  5. 一文读懂华为FIDO2指纹/3D 面容登录技术
  6. uniapp指纹面容检测功能案例
  7. Win10搭建ftp(含设置用户名和密码)测试成功!!!
  8. 零基础Java开发好学吗?
  9. 测试圈相亲平台开发流程(11):数据层简单实现-个人信息表/择偶要求表
  10. 【±5V集成稳压电源Multisim设计】