'commit'
This commit is contained in:
@@ -43,6 +43,20 @@ class ReadImageKit:
|
||||
res_text = await self.vlm.analyze_image(image_path, prompt)
|
||||
json_str = self.vlm.extract_json(res_text)
|
||||
data = json.loads(json_str)
|
||||
|
||||
# 保存诊断图片
|
||||
if data.get("found") and data.get("point"):
|
||||
p = data["point"]
|
||||
# 转换坐标
|
||||
img = read_image(image_path)
|
||||
if img is not None:
|
||||
h, w = img.shape[:2]
|
||||
actual_p = [int(p[0] * w / 1000), int(p[1] * h / 1000)]
|
||||
# 生成虚拟 bbox
|
||||
bbox = [actual_p[0]-50, actual_p[1]-30, actual_p[0]+50, actual_p[1]+30]
|
||||
draw_rectangles(image_path, bboxes=[bbox], click_points=[actual_p])
|
||||
logger.info(f"已生成价格入口诊断图片: {image_path.replace('.jpg', '_vl.jpg')}")
|
||||
|
||||
return data
|
||||
except Exception as e:
|
||||
logger.error(f"VLM 寻找价格入口失败: {e}")
|
||||
@@ -56,6 +70,10 @@ class ReadImageKit:
|
||||
分析这张截图,判断是否存在弹窗广告或遮罩层。
|
||||
如果存在,请找到关闭按钮(通常是圆圈里的 X,或者写着“跳过”、“关闭”的按钮)。
|
||||
|
||||
**重要警告**:
|
||||
1. 严禁选择屏幕最右上角的按钮(微信小程序的“胶囊按钮”,包含三个点和圆圈)。
|
||||
2. 广告关闭按钮通常在弹窗的边缘,或者是页面中心大弹窗的某个角落。
|
||||
|
||||
输出格式为 JSON:
|
||||
{
|
||||
"has_ad": true/false,
|
||||
@@ -67,11 +85,52 @@ class ReadImageKit:
|
||||
res_text = await self.vlm.analyze_image(image_path, prompt)
|
||||
json_str = self.vlm.extract_json(res_text)
|
||||
data = json.loads(json_str)
|
||||
|
||||
# 保存诊断图片
|
||||
if data.get("has_ad") and data.get("close_point"):
|
||||
p = data["close_point"]
|
||||
# 转换坐标
|
||||
img = read_image(image_path)
|
||||
if img is not None:
|
||||
h, w = img.shape[:2]
|
||||
actual_p = [int(p[0] * w / 1000), int(p[1] * h / 1000)]
|
||||
# 生成虚拟 bbox
|
||||
bbox = [actual_p[0]-50, actual_p[1]-30, actual_p[0]+50, actual_p[1]+30]
|
||||
draw_rectangles(image_path, bboxes=[bbox], click_points=[actual_p])
|
||||
logger.info(f"已生成广告关闭诊断图片: {image_path.replace('.jpg', '_vl.jpg')}")
|
||||
|
||||
return data
|
||||
except Exception as e:
|
||||
logger.error(f"VLM 寻找关闭按钮失败: {e}")
|
||||
return {"has_ad": False}
|
||||
|
||||
async def check_wrong_page_vlm(self, image_path):
|
||||
"""
|
||||
检查是否误触进入了错误的页面(如:新人福利、我的卡券、活动页等)
|
||||
"""
|
||||
prompt = """
|
||||
分析这张截图,判断这是否是一个真实的“充电站详情页”。
|
||||
|
||||
**识别准则**:
|
||||
1. 真正的“详情页”必须包含:充电站的具体名称、电价列表、终端状态(空闲/占用)等信息。
|
||||
2. 如果页面标题是“新人福利专区”、“活动规则”、“我的卡券”、“领券中心”或类似的营销活动页,则判定为错误页面。
|
||||
|
||||
输出格式为 JSON:
|
||||
{
|
||||
"is_detail_page": true/false,
|
||||
"page_type": "detail" / "marketing" / "coupons" / "other",
|
||||
"reason": "判断依据"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
res_text = await self.vlm.analyze_image(image_path, prompt)
|
||||
json_str = self.vlm.extract_json(res_text)
|
||||
data = json.loads(json_str)
|
||||
return data
|
||||
except Exception as e:
|
||||
logger.error(f"VLM 检查页面类型失败: {e}")
|
||||
return {"is_detail_page": True} # 默认认为是详情页,避免死循环
|
||||
|
||||
async def analyze_detail_price(self, image_path):
|
||||
"""
|
||||
分析详情页截图,提取电价信息,包括优惠价、PLUS价和挂牌价
|
||||
@@ -175,7 +234,7 @@ class ReadImageKit:
|
||||
cv_bboxes = detect_cards_cv(image_path, top_ratio=SAFE_EXCLUDE_RATIO, bottom_ratio=BOTTOM_SAFE_EXCLUDE_RATIO)
|
||||
|
||||
if cv_bboxes:
|
||||
draw_rectangles(image_path, cv_bboxes)
|
||||
draw_rectangles(image_path, bboxes=cv_bboxes)
|
||||
prompt = f"""
|
||||
图片中已经用绿色矩形框标记了 {len(cv_bboxes)} 个可能的充电站卡片。
|
||||
请按从上到下的顺序,识别每个绿色框内的场站信息。
|
||||
@@ -237,13 +296,33 @@ class ReadImageKit:
|
||||
|
||||
# 2. 坐标安全过滤:忽略页面上半部分的误点击(通常是 Logo 或广告)
|
||||
# 即使 VLM 没听话,我们也在这里硬性过滤
|
||||
y_threshold = h * 0.4 if h > 0 else 800
|
||||
# 根据主屏幕截图,顶部广告区和功能图标区占用了约 55% 的空间
|
||||
y_threshold = h * 0.58 if h > 0 else 1400
|
||||
if actual_p[1] < y_threshold:
|
||||
logger.warning(f"过滤掉可能的误点击点 (y={actual_p[1]} < {y_threshold}): {res.get('name')}")
|
||||
continue
|
||||
|
||||
res["point"] = actual_p
|
||||
final_stations.append(res)
|
||||
|
||||
# 保存诊断图片 (_vl.jpg, _flag.jpg)
|
||||
if final_stations:
|
||||
debug_bboxes = []
|
||||
debug_points = []
|
||||
for s in final_stations:
|
||||
if s.get("bbox"):
|
||||
debug_bboxes.append(s["bbox"])
|
||||
if s.get("point"):
|
||||
debug_points.append(s["point"])
|
||||
|
||||
# 如果没有 bbox,根据 point 生成一个虚拟 bbox 供可视化
|
||||
if not debug_bboxes and debug_points:
|
||||
for p in debug_points:
|
||||
debug_bboxes.append([p[0]-50, p[1]-30, p[0]+50, p[1]+30])
|
||||
|
||||
if debug_bboxes or debug_points:
|
||||
draw_rectangles(image_path, bboxes=debug_bboxes, click_points=debug_points)
|
||||
logger.info(f"已生成诊断图片: {image_path.replace('.jpg', '_vl.jpg')} 和 _flag.jpg")
|
||||
|
||||
return final_stations
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user