python+PIL识别微信聊天输入框位置 [图像处理]!

414 阅读5分钟

前言

如果想要识别电脑屏幕上微信输入框的位置,有什么办法呢?
这里提出了一种通过屏幕像素来识别的思路。

如何实现?

利用python第三方库:PIL图像处理库,对屏幕进行截图,通过分析屏幕像素点的RGB颜色值,只要匹配到微信输入框的某一特征位置像素点的RGB值,即找到了微信输入框的位置。

先来看看电脑微信有什么位置可以作为我们去匹配的特征位置。

![](https://p1.pstatp.com/origin/pgc-image/76c6369a65cc4360bf61aa8a0fa34f65)

有哪些可以作为特征提取的地方呢?

![](https://p1.pstatp.com/origin/pgc-image/376baf7d9507432a9085d73a1cdfe68b)

有6个地方都是可以作为特征位置,我们选择一个最容易被识别的位置,那就是第6个位置。我们来看看第6个位置有什么特点。

![](https://p1.pstatp.com/origin/pgc-image/f7b13f26ac8949bcb4e9a7ec0825e90a)

注意留意上面gif图中鼠标位置的RGB颜色值的变化,在分割线以下和分割线以上的位置RGB都是 **(245,245,245)**1,而分割线的位置RGB为 (236,236,236)

![](https://p1-tt-ipv6.byteimg.com/large/pgc-image/6ffa9e4cf22d42c4bd0e4247d5cd44dd)

通过这个特征我们就可以找到微信输入框的位置。

算法思路分析

  • 对屏幕进行截屏,并把截图转换成可以读取RGB值的序列对象。
  • 对屏幕截图的RGB值进行遍历,去匹配(236,236,236)

但是,一个屏幕的像素点这么多,(比如我屏幕有1920*1080=2073600个像素点),这么多像素点难道要一个一个遍历?

如何快速而准确地找到 (236,236,236) 的位置?

![](https://p26-tt.byteimg.com/large/pgc-image/b0dae4111e93463785dd38395ae8ce7c)

上图是我的屏幕,划上6条竖线,只要两条竖线之间的间距小于微信输入框的宽度,竖线就一定会落在微信输入框上。因此,只要遍历6条竖线上的像素点,就一定能找到微信输入框位置。

代码如下

(完整代码在末尾)

  • 所需的库:PIL

    from PIL import ImageGrab

    width, height = 1920, 1080 # 屏幕尺寸大小 img = ImageGrab.grab((0,0,width,height)) # 截取整个屏幕 imgData = img.getdata() # 转换成序列化数据 12345

变量imgData保存着截图的序列化数据,也就是说包含着每个像素点的RGB值的大小。
先来看一下imgData的长度:

![](https://p1.pstatp.com/origin/pgc-image/81fcf32e1e46456abfaa19afc5b5dde6)

2073600 刚好等于1920*1080,也就是包含了整个屏幕的像素点 。

分别索引看一下第1、2、3个像素点的值看一下是多少:

![](https://p1.pstatp.com/origin/pgc-image/9f176394be814ddc99bfb0ee09faee37)

可以看出是用 二维元组 的数据类型存储着每个像素点的RGB值。

接下来便开始遍历这个二维数组:

spacing = int(height / 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)
1234567891011121314

ps:

  • imgData是用二维的数据格式保存,所以寻找点(X,Y)时,需要 (Y-1)*屏幕宽度 +X .
  • 可以用numpy库将二维转换成三维数组,这样可以更方便对行和列进行处理,但是为了缩短程序运行时间(大约需要多花2秒钟),就不进行转换了,感兴趣的朋友可以试一下。

总结

  • 可以调用PIL.ImageGrab.grab() 进行屏幕截图
  • 遍历一张图片的所有像素点,寻找你想要的RGB值

识别屏幕上微信聊天输入框的位置,识别到位置之后,可以干什么呢?

![](https://p1.pstatp.com/origin/pgc-image/59b0f20d771846599b650671fa47919c)

欢迎有兴趣有想法的朋友一起交流。

以下贴出完整代码:

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(height / 5)  # 两条竖线之间的间距
    for i in range(6):  # 遍历6条竖线
        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)
    return 0

if __name__ == '__main__':
    print(analysis_pixel())
123456789101112131415161718192021222324252627
  1. 当微信输入框没有获得焦点的时候RGB为 (245,245,245) ,获得焦点的时候RGB为 (255,255,255) ↩︎