py电脑端条件触发音频文件突然跑通了--需要准备adb用于连接手机端执行拨打电话、scrcpy-win64-v3.3(识别屏幕元素)、tesseract.exe(用于屏幕元素识)开源下载布置到系统路径

import cv2
import numpy as np
import subprocess
import time
import os
import pytesseract
from PIL import Image
import re

# ================== 配置 ==================
PHONE_NUMBERS = ["18868091626","18868091626"]
VLC_PATH = r"E:\vlc_vlc\VLC\vlc.exe"
AUDIO_FILE = r"C:\Users\Lenovo\Desktop\20250615_162636.m4a"
SCREENSHOT_PATH = r"screenshots"
pytesseract.pytesseract.tesseract_cmd = r"E:\tt-ocr\tesseract.exe"
# 使用完整路径的 adb.exe
ADB_PATH = r"E:\androidplatformADB\platform-tools\adb.exe"

THRESHOLD = 30  # 图像差异阈值


# ================== 核心函数 ==================

def adb_call(number):
    """通过 ADB 拨打电话"""
    print(f"正在拨打号码: {number}")
    encoded_number = number.replace("#", "%23").replace("+", "%2B").replace(" ", "%20")
    cmd = f'"{ADB_PATH}" shell am start -a android.intent.action.CALL -d tel:{encoded_number}'
    subprocess.run(cmd, shell=True)
    time.sleep(1)  # 等待1秒后开始截图监控


def take_screenshot(filename):
    """截取当前手机屏幕并保存"""
    path = os.path.join(SCREENSHOT_PATH, filename)
    print(f"正在截图到: {path}")

    # 创建截图目录(如果不存在)
    os.makedirs(SCREENSHOT_PATH, exist_ok=True)

    # 执行截图命令
    cmd = f'"{ADB_PATH}" exec-out screencap -p > "{path}"'
    result = subprocess.run(cmd, shell=True, capture_output=True, text=True)

    # 检查文件是否存在且非空
    if not os.path.exists(path) or os.path.getsize(path) == 0:
        raise FileNotFoundError(f"截图失败,文件未生成或为空: {path}")

    # 可选:图像预处理增强 OCR 效果
    preprocess_image(path)

    return path


def preprocess_image(image_path):
    """
    图像预处理:灰度化 + 二值化 + 去噪
    提高 OCR 准确率
    """
    img = cv2.imread(image_path, 0)  # 灰度图
    _, img_bin = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)  # 自动二值化
    kernel = np.ones((1, 1), np.uint8)
    img_bin = cv2.dilate(img_bin, kernel, iterations=1)
    img_bin = cv2.erode(img_bin, kernel, iterations=1)
    cv2.imwrite(image_path, img_bin)  # 覆盖原图
    return image_path


def compare_images(img1_path, img2_path):
    """比较两张图片是否发生变化"""
    img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
    img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)

    if img1 is None or img2 is None:
        raise ValueError(f"图像读取失败:{img1_path} 或 {img2_path}")

    if img1.shape != img2.shape:
        raise ValueError("两张图片尺寸不一致,无法比较")

    diff = cv2.absdiff(img1, img2)
    _, thresh = cv2.threshold(diff, THRESHOLD, 255, cv2.THRESH_BINARY)
    non_zero = cv2.countNonZero(thresh)
    return non_zero > 100  # 根据像素变化数量判断是否有变化


def play_audio_with_vlc():
    """使用 VLC 播放音频文件"""
    print("播放音频...")
    process = subprocess.Popen([VLC_PATH, "--play-and-exit", AUDIO_FILE])
    process.wait()  # 等待音频播放完成
    print("音频播放完毕")


def detect_text(image_path, pattern=r"\b\d{2}:\d{2}\b"):
    """
    使用 OCR 检测图像中是否包含符合时间格式(如 00:00)的文本。
    :param image_path: 图像文件路径
    :param pattern: 正则表达式,默认是 \b\d{2}:\d{2}\b 表示两位数:两位数格式
    :return: True 如果检测到匹配的文本
    """
    print(f"OCR 检测图像中的文本:{image_path}")
    try:
        image = Image.open(image_path)
        text = pytesseract.image_to_string(image, lang='eng')  # eng 表示英文+数字
        match = re.search(pattern, text)
        if match:
            print(f"检测到符合 '{pattern}' 格式的文本!内容为:{match.group()}")
            return True
        else:
            print("未检测到目标文本格式。")
            return False
    except Exception as e:
        print(f"OCR 识别出错: {e}")
        return False


def monitor_screen_changes(max_attempts=5):
    """
    在首次截图前等2秒,之后每隔3秒截图一次,
    并两两比较是否有屏幕变化,若变化中有 'dd:dd' 格式文本,则播放音频。
    如果连续 max_attempts 次没有检测到目标文本,则主动挂断电话。
    """
    print("等待 2 秒后开始第一次截图...")
    time.sleep(2)  # 拨号后首次截图延迟 2 秒
    prev_img = take_screenshot("s0.png")

    no_match_count = 0  # 用于记录未匹配目标文本的次数

    while True:
        time.sleep(3)  # 每次截图间隔 3 秒
        curr_img = take_screenshot(f"s{int(time.time())}.png")  # 使用时间戳命名避免冲突

        if compare_images(prev_img, curr_img):
            print("检测到屏幕元素发生变化!")
            if detect_text(curr_img):  # 默认检测 dd:dd 格式
                print("检测到 'dd:dd' 格式字样,触发音频播放")
                play_audio_with_vlc()
                break
            else:
                no_match_count += 1
                print(f"未检测到目标文本,连续失败次数:{no_match_count}/{max_attempts}")
        else:
            print("屏幕无明显变化,跳过OCR识别")
            no_match_count += 1
            print(f"无有效变化,连续失败次数:{no_match_count}/{max_attempts}")

        # 判断是否达到最大失败次数
        if no_match_count >= max_attempts:
            print(f"连续 {max_attempts} 次未检测到目标文本,主动挂断电话")
            hang_up_call()
            return False  # 表示未成功播放音频

        prev_img = curr_img

    return True  # 表示成功播放了音频


def hang_up_call():
    """挂断电话"""
    print("挂断电话...")
    cmd = f'"{ADB_PATH}" shell input keyevent KEYCODE_ENDCALL'
    subprocess.run(cmd, shell=True)
    time.sleep(1)


def main():
    # 创建截图目录
    os.makedirs(SCREENSHOT_PATH, exist_ok=True)

    for number in PHONE_NUMBERS:
        print(f"=== 开始拨打号码: {number} ===")
        adb_call(number)

        # 开始监控屏幕变化(首次截图前等2秒)
        try:
            monitor_screen_changes()
        except Exception as e:
            print(f"发生异常: {e}")

        hang_up_call()
        print(f"=== 结束拨打号码: {number} ===\n")


if __name__ == "__main__":
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值