'commit'
This commit is contained in:
@@ -82,6 +82,7 @@ async def get_vlm_analysis(image_path):
|
||||
|
||||
【核心任务】
|
||||
识别图中的【语音消息气泡】和【文本消息气泡】,并区分【发送者】。
|
||||
⚠️ **特别注意**:必须识别屏幕上**所有**的消息,特别是位于**屏幕最底部**的消息,哪怕只有一部分,也要识别!
|
||||
|
||||
【重要判别规则】
|
||||
1. 👤 **发送者 (Sender)**:
|
||||
@@ -95,13 +96,19 @@ async def get_vlm_analysis(image_path):
|
||||
- **极短 (1"-2")**:气泡非常短,形状接近一个小正方形。
|
||||
- **极长 (60")**:气泡很长,宽度接近屏幕的一半。
|
||||
- **内容**:气泡内**只有一个**表示时长的数字(如 `8"`)和一个声波图标。
|
||||
- **辅助文字**:语音气泡右侧可能会有灰色的“转文字”或“取消转文字”字样,**请忽略这些文字**,依然将该气泡识别为语音消息!
|
||||
- **绝对排除**:凡是包含汉字、长句子的气泡,**统统不是**语音消息。
|
||||
|
||||
3. 📝 **文本消息 (Text)**:
|
||||
- **视觉特征**:气泡内包含汉字、标点符号、表情等文本内容。
|
||||
|
||||
4. 🔴 **未读状态 (Unread)**:
|
||||
- **特征**:语音气泡右上角或附近有一个明显的**小红点**。
|
||||
4. 🔴 **未读状态 (Unread) - 极度重要!**:
|
||||
- **特征**:语音气泡的右上角(或紧邻右侧)有一个明显的**红色圆形小点**。
|
||||
- **判别**:
|
||||
- 只要看到红色小点,`is_unread` 必须为 **true**。
|
||||
- 如果没有红色小点,`is_unread` 为 false。
|
||||
- **注意**:红点可能很小,请仔细观察!这是判断是否处理的关键依据。即使红点旁边有灰色的“转文字”字样,只要有红点,就是未读!
|
||||
|
||||
|
||||
【坐标系统】
|
||||
**必须使用 [0-1000] 的归一化坐标系。**
|
||||
@@ -133,7 +140,7 @@ async def get_vlm_analysis(image_path):
|
||||
注意:
|
||||
1. 坐标 `center` 和 `input_box` 必须是 [0-1000] 的归一化坐标。
|
||||
2. `status` 判断:如果语音气泡的正下方紧挨着一条文本消息(通常是转换出的文字),则为 `converted`,否则为 `unconverted`。
|
||||
3. `is_unread` 判断:如果有红点则为 true,否则为 false (仅针对语音消息)。
|
||||
3. `is_unread` 判断:务必准确识别红点!如果有红点则为 true。
|
||||
4. 请按从上到下的顺序输出所有消息。
|
||||
"""
|
||||
|
||||
@@ -392,11 +399,96 @@ def find_template_match(screen_path, template_path, threshold=0.8):
|
||||
logger.error(f"Template matching failed: {e}")
|
||||
return None
|
||||
|
||||
def find_all_template_matches(screen_path, template_path, threshold=0.8):
|
||||
"""
|
||||
使用 OpenCV 模板匹配寻找**所有**符合条件的坐标
|
||||
"""
|
||||
try:
|
||||
if not os.path.exists(template_path):
|
||||
logger.error(f"Template file not found: {template_path}")
|
||||
return []
|
||||
|
||||
img = cv2.imread(screen_path)
|
||||
template = cv2.imread(template_path)
|
||||
if img is None or template is None:
|
||||
return []
|
||||
|
||||
h, w = template.shape[:2]
|
||||
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
|
||||
|
||||
# 找到所有大于阈值的点
|
||||
loc = np.where(res >= threshold)
|
||||
|
||||
points = []
|
||||
for pt in zip(*loc[::-1]): # Switch collumns and rows
|
||||
center_x = pt[0] + w // 2
|
||||
center_y = pt[1] + h // 2
|
||||
points.append((center_x, center_y))
|
||||
|
||||
# 简单的去重(非极大值抑制的简化版,合并相近的点)
|
||||
# 这里假设红点不会重叠,暂时直接返回,或者做一个简单的聚类
|
||||
# 实际应用中,matchTemplate 对同一个目标周围可能会有多个连续的匹配点
|
||||
# 我们需要合并它们
|
||||
|
||||
unique_points = []
|
||||
for p in points:
|
||||
is_close = False
|
||||
for up in unique_points:
|
||||
if abs(p[0] - up[0]) < 10 and abs(p[1] - up[1]) < 10:
|
||||
is_close = True
|
||||
break
|
||||
if not is_close:
|
||||
unique_points.append(p)
|
||||
|
||||
if unique_points:
|
||||
logger.info(f"Found {len(unique_points)} matches for {os.path.basename(template_path)}")
|
||||
|
||||
return unique_points
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"find_all_template_matches failed: {e}")
|
||||
return []
|
||||
|
||||
def perform_input_action(d, center_point, text, auto_send=True):
|
||||
"""
|
||||
执行输入操作
|
||||
"""
|
||||
try:
|
||||
# --- 新增逻辑:确保处于文字输入模式 ---
|
||||
logger.info("正在检查输入模式...")
|
||||
tmp_check_shot = os.path.join(os.path.dirname(os.path.abspath(__file__)), "temp_input_check.jpg")
|
||||
d.screenshot(tmp_check_shot)
|
||||
|
||||
wen_zi_template = r"d:\dsWork\aiData\WeiXin\Templates\wen_zi_input.jpg"
|
||||
input_text_template = r"d:\dsWork\aiData\WeiXin\Templates\input_text.jpg"
|
||||
|
||||
# 1. 检查是否存在 '切换到文字' 图标 (表示当前是语音模式)
|
||||
# 注意:这里假设 wen_zi_input.jpg 是那个“键盘”图标
|
||||
wen_zi_pos = find_template_match(tmp_check_shot, wen_zi_template, threshold=0.8)
|
||||
|
||||
if wen_zi_pos:
|
||||
logger.info(f"检测到语音模式 (找到切换文字图标: {wen_zi_pos}),点击切换...")
|
||||
d.click(wen_zi_pos[0], wen_zi_pos[1])
|
||||
time.sleep(1.0) # 等待 UI 切换
|
||||
else:
|
||||
# 2. 如果没找到切换图标,假设是文字模式,尝试点击输入区域标识
|
||||
logger.info("未检测到语音模式切换图标,尝试寻找文字输入区域...")
|
||||
input_text_pos = find_template_match(tmp_check_shot, input_text_template, threshold=0.8)
|
||||
if input_text_pos:
|
||||
logger.info(f"找到文字输入区域标识 (input_text.jpg): {input_text_pos},点击激活...")
|
||||
d.click(input_text_pos[0], input_text_pos[1])
|
||||
time.sleep(0.5)
|
||||
else:
|
||||
logger.info("未找到特定的输入区域标识,将使用默认坐标或控件查找。")
|
||||
|
||||
# 清理临时文件
|
||||
if os.path.exists(tmp_check_shot):
|
||||
try:
|
||||
os.remove(tmp_check_shot)
|
||||
except:
|
||||
pass
|
||||
# --- 新增逻辑结束 ---
|
||||
|
||||
# 1. 尝试找到原生输入框并输入
|
||||
edit_text = d(className="android.widget.EditText")
|
||||
input_success = False
|
||||
|
||||
Reference in New Issue
Block a user