This commit is contained in:
HuangHai
2026-01-12 21:33:21 +08:00
parent 2051cb61c2
commit 4612ee2d81
18 changed files with 457 additions and 191 deletions

View File

@@ -18,6 +18,17 @@ from Apps.XinDianTu.Config.Setting import (
logger = logging.getLogger(__name__)
# 场站过滤黑名单
STATION_EXCLUDED_TITLES = {
"畅充会员", "组团充电", "微信社群", "申卡有礼", "夜间免停",
"洗手间", "不限车长", "不限车高", "组团", "综合排序", "距离优先",
"价格最低", "空闲较多", "筛选", "地图", "列表"
}
STATION_BLACKLIST_KEYWORDS = [
"广告", "优惠券", "点击进入", "立即参与", "咨询电话", "活动详情"
]
class ReadImageKit:
_client = AsyncOpenAI(
@@ -36,18 +47,18 @@ class ReadImageKit:
"仅输出JSON数组(不含任何说明文字),按从左到右、从上到下的顺序识别图片中的充电站区域。识别规则如下:\n"
"1. 必须是卡片形式的充电站信息区域。\n"
"2. 每一个卡片必须同时具备以下所有要素,否则严禁识别:\n"
" - 场站名称 (station_name);\n"
" - **场站名称 (station_name)**: 场站名称通常位于卡片的第一行(左上角),字体最大且加粗。严禁提取'距离优先'、'空闲较多'、'价格最低'等筛选标签。严禁将卡片中下部的描述信息(如'导航到...'、'停车说明...'、'距您...'等)识别为名称。\n"
" - 距离信息 (distance, 例如 '5.3km' 或 '90m'),位于卡片右上角;\n"
" - 金额/电费 (price,例如 '0.8490');\n"
" - 充电枪信息 (piles,包含'超'、'快'或'慢'的类型、总枪数和空闲枪数,例如 '快 闲4/4')。\n"
"3. 如果缺少上述任何一项要素(例如只有名称和距离,但没有电费或枪数信息),说明它不是真正的场站卡片(可能是广告或功能入口),请直接跳过。\n"
" - **充电枪信息 (piles)**: 包含'超'、'快'或'慢'的类型、总枪数和空闲枪数(例如 '快 闲4/4')。如果图中只显示数字(如 '34/42')而没有明确标明类型,请统一识别为 `type: \"慢\"`。\n"
"3. 如果缺少上述任何一项要素(例如只有名称 and 距离,但没有电费或枪数信息),说明它不是真正的场站卡片(可能是广告或功能入口),请直接跳过。\n"
"\n"
"JSON对象字段要求:\n"
"1. b_use: 状态标识(1或0)。如果场站名称为灰色或带有“暂停使用”等标签,则为0,否则为1。\n"
"2. station_name: 场站名称;\n"
"3. price: 一度电的价格(数字);\n"
"4. pro_price: Pro会员价格(数字),无则为null;\n"
"5. piles: 充电枪列表 [{type: '快', free: 4, total: 4}];\n"
"5. piles: 充电枪列表 [{type: '快'|'慢'|'超', free: 4, total: 4}];\n"
"6. parking: 停车费用描述(通常在'P'图标后,例如 '收费停车:以场站实际收费规则为准' 或 '限时免费停车...')。\n"
"7. distance: 距离信息字符串(例如 '5.3km' 或 '90m')。\n"
"8. bounds: {x1,y1,x2,y2} 区域像素坐标(0-1000);\n"
@@ -454,7 +465,7 @@ class ReadImageKit:
"1. station_name: 场站名称;\n"
"2. price: 价格(数字);\n"
"3. pro_price: Pro会员价(数字,无则null);\n"
"4. piles: 充电枪描述字符串(例如 '快 闲4/4');\n"
"4. piles: 充电枪列表 [{type: '快'|'慢'|'超', free: 4, total: 4}]。如果图中只显示数字(如 '34/42')而没有明确标明类型,请统一识别为 `type: \"慢\"`;\n"
"5. tags: 标签列表(如 ['限时免费']);\n"
"6. parking: 停车费用描述(通常在'P'图标后,例如 '收费停车:以场站实际收费规则为准' 或 '限时免费停车...')。\n"
"7. distance: 距离信息字符串(例如 '5.3km')。\n"
@@ -583,7 +594,6 @@ class ReadImageKit:
return final_stations
@staticmethod
@staticmethod
def get_card_segments(image_path, output_dir="./Debug/Patches"):
"""
@@ -785,7 +795,18 @@ class ReadImageKit:
"content": [
{
"type": "text",
"text": "请识别图片中的充电站信息,并以 JSON 格式输出:{\"station_name\": \"...\", \"price\": \"...\", \"piles\": \"空闲数/总数\"}。只输出 JSON,不要有其他文字。"
"text": (
"你是一个专业的充电桩信息提取助手。请识别图片中充电站卡片的核心信息。\n"
"注意以下识别规则:\n"
"1. **场站名称 (station_name)**: 场站名称通常位于卡片的第一行,字体较大且加粗。严禁提取'距离优先'、'空闲较多'、'价格最低'等筛选标签。严禁将卡片中间的长段描述信息识别为名称。\n"
"2. **价格 (price)**: 提取数字部分,通常以'元/度'结尾。\n"
"3. **桩数 (piles)**: 识别所有类型的充电桩。请提取'快'、'慢'或'超'字样及其对应的'空闲/总数'(如 '快 4/4')。\n"
" - 如果图中只显示数字(如 '34/42')而没有明确标明类型,请统一识别为 `type: \"慢\"`。\n"
" - 必须以列表形式输出所有识别到的类型。\n"
"请以 JSON 格式输出:\n"
"{\"station_name\": \"场站名称\", \"price\": \"价格\", \"piles\": [{\"type\": \"快\", \"free\": 4, \"total\": 4}]}\n"
"只输出 JSON,不要有任何解释文字。"
)
},
{"type": "image_url", "image_url": {"url": patch_url}}
]