阅读文章,大约需要5分钟时间
文章目录
- 前言
- 如何实现?
- 算法思路分析
- 代码如下
- 总结
前言
如果想要识别电脑屏幕上微信输入框的位置,有什么办法呢?
这里提出了一种通过屏幕像素来识别的思路。
如何实现?
利用python第三方库:PIL图像处理库,对屏幕进行截图,通过分析屏幕像素点的RGB颜色值,只要匹配到微信输入框的某一特征位置像素点的RGB值,即找到了微信输入框的位置。
先来看看电脑微信有什么位置可以作为我们去匹配的特征位置。
有哪些可以作为特征提取的地方呢?
有6个地方都是可以作为特征位置,我们选择一个最容易被识别的位置,那就是第6个位置。我们来看看第6个位置有什么特点。
注意留意上面gif图中鼠标位置的RGB颜色值的变化,在分割线以下和分割线以上的位置RGB都是 (245,245,245)1,而分割线的位置RGB为 (236,236,236)
通过这个特征我们就可以找到微信输入框的位置。
算法思路分析
- 对屏幕进行截屏,并把截图转换成可以读取RGB值的序列对象。
- 对屏幕截图的RGB值进行遍历,去匹配(236,236,236)
但是,一个屏幕的像素点这么多,(比如我屏幕有1920*1080=2073600个像素点),这么多像素点难道要一个一个遍历?
如何快速而准确地找到 (236,236,236) 的位置?
上图是我的屏幕,划上6条竖线,只要两条竖线之间的间距小于微信输入框的宽度,竖线就一定会落在微信输入框上。因此,只要遍历6条竖线上的像素点,就一定能找到微信输入框位置。
代码如下
(完整代码在末尾)
- 所需的库:PIL
from PIL import ImageGrab
width, height = 1920, 1080 # 屏幕尺寸大小
img = ImageGrab.grab((0,0,width,height)) # 截取整个屏幕
imgData = img.getdata() # 转换成序列化数据
变量imgData保存着截图的序列化数据,也就是说包含着每个像素点的RGB值的大小。
先来看一下imgData的长度:
2073600 刚好等于1920*1080,也就是包含了整个屏幕的像素点 。分别索引看一下第1、2、3个像素点的值看一下是多少:
可以看出是用 二维元组 的数据类型存储着每个像素点的RGB值。
接下来便开始遍历这个二维数组:
spacing = int(width / 5) # 两条竖线之间的间距
for j in range(height): # 遍历竖线上的像素点
place = j*width + i*spacing # 第i列第j行在imgData的位置
if imgData[place] == (236,236,236): # 找到(236,236,236)这个颜色值
if imgData[place-width] == (245,245,245) and \
imgData[place+width] in ((245,245,245),(255,255,255)):
# 判断分割线上面一个像素点和下面一个像素点的RGB值是否符合,防止误判
for long in range(1,21): # 判断分割线连续20个像素点是否都为(236,236,236),防止误判
if imgData[place+long] != (236,236,236):
break
else:
# 返回正确的位置(微信输入框分割线上某个点的位置)
return place%width, int(place/width)
ps:
- imgData是用二维的数据格式保存,所以寻找点(X,Y)时,需要 (Y-1)*屏幕宽度 +X .
- 可以用numpy库将二维转换成三维数组,这样可以更方便对行和列进行处理,但是为了缩短程序运行时间(大约需要多花2秒钟),就不进行转换了,感兴趣的朋友可以试一下。
总结
- 可以调用PIL.ImageGrab.grab() 进行屏幕截图
- 遍历一张图片的所有像素点,寻找你想要的RGB值
识别屏幕上微信聊天输入框的位置,识别到位置之后,可以干什么呢?
欢迎有兴趣有想法的朋友一起交流。
以下贴出完整代码:
from PIL import ImageGrab
import numpy as np
def analysis_pixel():
width, height = 1920, 1080
img = ImageGrab.grab((0,0,width,height))
imgData = img.getdata()
# imgDataNp = np.array(imgData).reshape((1920,1080,3)) # 转换成三维数组
spacing = int(width / 5) # 两条竖线之间的间距
for i in range(6): # 遍历6条竖线
for j in range(height): # 遍历竖线上的像素点
place = j*width + i*spacing # 第i列第j行在imgData的位置
try:
if imgData[place] == (236,236,236): # 找到(236,236,236)这个颜色值
if imgData[place-width] == (245,245,245) and imgData[place+width] in ((245,245,245),(255,255,255)):
# 判断分割线上面一个像素点和下面一个像素点的RGB值是否符合,防止误判
for long in range(1,21): # 判断分割线连续20个像素点是否都为(236,236,236),防止误判
if imgData[place+long] != (236,236,236):
break
else:
# 返回正确的位置(微信输入框分割线上某个点的位置)
return place%width, int(place/width)
except IndexError:
# 当遍历到最后一个点的时候会超出索引范围
return 0
return 0
if __name__ == '__main__':
print(analysis_pixel())
- 当微信输入框没有获得焦点的时候RGB为 (245,245,245) ,获得焦点的时候RGB为 (255,255,255) ↩︎