使用 OpenCV 自动点赞抖音小猫
XiaoMa 博士生

看到有人分享 Python 抖音机器人,论如何在抖音上找到漂亮小姐姐? (github.com),Git Clone 下来,发现由于腾讯云人脸识别的接口无法连接,导致截图完停止,不继续往下运行了,没啃下来官方提供的教程(Flag:以后会啃下来的)。于是自己使用 OpenCV 重新写了一个 Python 脚本,不过是识别“猫猫”的哦。

特性

  • 自动翻页
  • 猫脸识别
  • 自动点赞

原理

  • 打开抖音 APP,进入主界面;
  • 获取手机截图;
  • 使用 OpenCV 提供的 xml 文件[1]进行检测;
  • 当检测到是猫猫时,自动点赞;
  • 滑到下一页。重复上述步骤。

使用教程

  • Python 版本 3.9.16(理论上其他的也可以);
  • Anaconda 安装和虚拟环境创建[2]
  • adb 安装[2]
  • 下载 OpenCV 提供的 xml 文件[1]

源码(注释完全版)

1
2
3
4
5
6
7
8
9
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
56
57
58
59
60
61
62
63
64
65
66
67
import subprocess #用于执行 shell 命令
import cv2
import time
import shutil #用于复制、移动、删除文件和目录等操作
import os #提供与操作系统进行交互的功能

# 指定设备序列号
device_serial = "xxx" #在 cmd 中运行 adb devices 查看并复制
# 定义计数器变量
count = 0 #本项目为测试项目,所以只刷 12 次就停止。如果不想,在整个代码中删掉 count 就可以了

while True:

# 等待两秒
time.sleep(2)

# 指定时间戳
timestamp = int(time.time())
# 将时间戳转换为本地时间
local_time = time.localtime(timestamp)
# 将时间格式化为字符串
time_str = time.strftime("%Y-%m-%d-%H-%M-%S", local_time)
# 生成唯一的文件名
screenshot_filename = f"douyin_screenshot_{time_str}.png"

# 截取屏幕上正在播放的抖音视频的截图,并上传保存到计算机上
screenshot_cmd = f"adb -s {device_serial} shell screencap -p /sdcard/{screenshot_filename}"
subprocess.run(screenshot_cmd, shell=True)
pull_cmd = f"adb -s {device_serial} pull /sdcard/{screenshot_filename} ."
subprocess.run(pull_cmd, shell=True)

# 加载截图并进行图像识别
screenshot = cv2.imread(f"{screenshot_filename}") #注意写 f,用于将变量值嵌入到字符串中
gray = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)
cat_cascade = cv2.CascadeClassifier("haarcascade_frontalcatface.xml")
cats = cat_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) #参数解释在下方
if len(cats) > 0:
# 如果识别出小猫,则模拟点击点赞按钮
# 测试使用设备:Redmi Note8,2340x1080,其他手机自行适配参数
like_cmd = f"adb -s {device_serial} shell input tap 1004 1331"
subprocess.run(like_cmd, shell=True)
# 等待 2 秒
time.sleep(1)
# 屏幕上滑(参数解释见下文)
swipe_cmd = f"adb -s {device_serial} shell input swipe 540 1500 540 1000 100"
subprocess.run(swipe_cmd, shell=True)
else:
# 屏幕上滑
swipe_cmd = f"adb -s {device_serial} shell input swipe 540 1500 540 1000 100"
subprocess.run(swipe_cmd, shell=True)

# 指定源文件路径和目标文件夹路径(这是为了把截的图存放到专门的文件夹中,用于检测识别准确度)
source_file = f"{screenshot_filename}"
target_folder = "cved" #文件夹自行创建,在本 python 脚本的文件夹中就可以

# 构建目标文件路径
target_file = os.path.join(target_folder, source_file)

# 移动文件到目标文件夹
shutil.move(source_file, target_file)

# 计数器加 1
count += 1

# 完成 12 次截图,退出循环
if count >= 12:
break

sacleFator:这个参数控制图像金字塔的缩放比例。较小的 scaleFactor 值会导致更多的金字塔层级,从而增加检测准确性,但也会增加计算量,使检测速度变慢。较大的 scaleFactor 值则会减少金字塔层级和计算量,提高检测速度,但可能降低检测准确性。通常情况下,scaleFactor 的值在 1.01 到 1.5 之间。

minNeighbors:这个参数控制检测到的物体的矩形框之间应该有多少个相邻矩形框。较大的 minNeighbors 值可以减少误报率(错误检测),但可能导致一些真实物体被错过(降低检测准确性)。较小的 minNeighbors 值可能会增加误报率,但也可能提高检测准确性。这个参数的最佳值取决于具体的应用场景和数据集。通常情况下,minNeighbors 的值在 3 到 10 之间。

minSize:这个参数用于设置检测到的物体的最小尺寸(宽度和高度)。较大的 minSize 值可以减少误报率,但可能导致一些较小的真实物体被错过。较小的 minSize 值可能会增加误报率,但能检测到更小的物体。设置适当的 minSize 取决于你希望检测到的物体的实际尺寸和应用场景。例如,如果你只关心较大的猫脸,可以将 minSize 设置为一个较大的值。

input swipe 540 1500 540 1000 100:这部分命令是要在设备上执行的实际 shell 命令。input 是一个 Android shell 命令,用于模拟用户输入。swipeinput 命令的一个子命令,用于模拟滑动操作。接下来的四个数字参数表示滑动操作的起点和终点坐标:(500, 1500) 是滑动的起点,(500, 80) 是滑动的终点。坐标系统的原点位于屏幕的左上角,x 轴向右延伸,y 轴向下延伸。100 是指延时 100ms,从第一个坐标滑到第二个坐标用时 100ms。

测试

  1. 抖音 Up 主:怀特喵先生
image-20230315111028379
  1. 抖音 Up 主:电波波波

image-20230315112158413

总结

使用的haarcascade_frontalcatface.xml 这个模型,必须截图截到猫的正脸才可以,而且在视频播放时截图是随机的,可能这个镜头是猫猫的正脸,下个镜头就不是了,具有较大的不确定性。虽然没有达到 100% 识别率,但这个数据已经很好了。

下一步工作

接入腾讯 Ai 人脸识别,对人脸进行检测分析。

参考

[1] opencv/data/haarcascades at master · opencv/opencv (github.com)

[2] ADB 与 Anaconda 使用 | Story Begins…… (storybeginswhen.icu)