支持了识别颜色形状

This commit is contained in:
灼眼者 2024-06-03 12:15:05 +08:00
parent 96bcc12efc
commit dea993b57d
3 changed files with 91 additions and 16 deletions

55
main.py
View File

@ -1,20 +1,11 @@
import asyncio
from api.qinglong import QlApi
from config import (
slide_difference,
slide_x_position,
slide_y_position,
auto_move,
qinglong_data,
user_datas,
jd_login_url,
auto_shape_recognition,
backend_top_left_x,
backend_top_left_y,
small_img_top_left_x,
small_img_top_left_y,
small_img_bottom_right_x,
small_img_bottom_right_y
)
from loguru import logger
import time
@ -22,7 +13,7 @@ from playwright.async_api import Playwright, async_playwright
import random
import traceback
from typing import Union
from utils.consts import supported_types
from utils.consts import supported_types, supported_colors
from utils.tools import (
base_move,
get_img_bytes,
@ -33,6 +24,7 @@ from utils.tools import (
get_word,
save_screenshot_img,
get_shape_location_by_type,
get_shape_location_by_color,
click_by_autogui
)
@ -46,6 +38,11 @@ async def auto_move_slide(page, retry_times: int=2):
"""
自动识别移动滑块验证码
"""
from config import (
slide_difference,
slide_x_position,
slide_y_position
)
for i in range(retry_times):
logger.info(f'{i}次尝试自动移动滑块中...')
try:
@ -70,6 +67,14 @@ async def auto_move_slide(page, retry_times: int=2):
async def auto_shape(page, retry_times: int=5):
from config import (
backend_top_left_x,
backend_top_left_y,
small_img_top_left_x,
small_img_top_left_y,
small_img_bottom_right_x,
small_img_bottom_right_y
)
ocr = get_ocr(beta=True)
"""
自动识别滑块验证码
@ -101,11 +106,31 @@ async def auto_shape(page, retry_times: int=5):
word = get_word(ocr, small_img_path)
if word.find('') > 0:
logger.info(f'不支持颜色,刷新中......')
# 刷新
await refresh_button.click()
await asyncio.sleep(random.random() * 2)
continue
target_color = word.split('请选出图中')[1].split('的图形')[0]
if target_color in supported_colors:
logger.info(f'正在点击中......')
# 获取点的中心点
center_x, center_y = get_shape_location_by_color(background_img_path, target_color)
if center_x is None and center_y is None:
logger.info(f'识别失败,刷新中......')
await refresh_button.click()
continue
# 得到网页上的中心点
x, y = backend_top_left_x + center_x ,backend_top_left_y + center_y
# 点击图片
click_by_autogui(x, y)
await asyncio.sleep(random.random() * 3)
# 点击确定
await button.click()
await asyncio.sleep(3)
continue
else:
logger.info(f'不支持该颜色,刷新中......')
# 刷新
await refresh_button.click()
await asyncio.sleep(random.random() * 2)
continue
else:
type = word.split('请选出图中的')[1]
if type in supported_types:

View File

@ -6,4 +6,15 @@ supported_types = [
"六边形",
"圆形",
"梯形"
]
]
# 定义了支持的每种颜色的 HSV 范围
supported_colors = {
'紫色': ([125, 50, 50], [145, 255, 255]),
'灰色': ([0, 0, 50], [180, 50, 255]),
'粉色': ([160, 50, 50], [180, 255, 255]),
'蓝色': ([100, 50, 50], [130, 255, 255]),
'绿色': ([40, 50, 50], [80, 255, 255]),
'橙色': ([10, 50, 50], [25, 255, 255]),
'黄色': ([25, 50, 50], [35, 255, 255]),
'红色': ([0, 50, 50], [10, 255, 255])
}

View File

@ -2,12 +2,15 @@ import base64
import cv2
import ddddocr
import io
import numpy as np
import pyautogui
import random
import os
from PIL import Image, ImageGrab
import re
import time
from utils.consts import supported_colors
def get_tmp_dir(tmp_dir:str = './tmp'):
# 检查并创建 tmp 目录(如果不存在)
@ -211,6 +214,42 @@ def get_shape_location_by_type(img_path, type: str):
return None, None
def get_shape_location_by_color(img_path, target_color):
"""
根据颜色获取指定形状在图片中的坐标
"""
# 检查目标颜色是否在定义的颜色范围内
if target_color not in supported_colors:
raise ValueError(f"Color {target_color} is not defined in the color ranges.")
# 读取图像
image = cv2.imread(img_path)
# 读取图像并转换为 HSV 色彩空间。
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 获取目标颜色的范围
lower, upper = supported_colors[target_color]
lower = np.array(lower, dtype="uint8")
upper = np.array(upper, dtype="uint8")
# 创建掩码并找到轮廓
mask = cv2.inRange(hsv_image, lower, upper)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 遍历轮廓并在中心点画点
for contour in contours:
# 过滤掉太小的区域
if cv2.contourArea(contour) > 100:
M = cv2.moments(contour)
if M["m00"] != 0:
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
return cX, cY
return None, None
def click_by_autogui(x, y):
"""
点击指定坐标的元素