From ac79e44282ec04c637c1c65221d114ccab329f34 Mon Sep 17 00:00:00 2001 From: HuangHai <10402852@qq.com> Date: Mon, 12 Jan 2026 20:11:18 +0800 Subject: [PATCH] 'commit' --- .idea/Crawler.iml | 14 ---- .idea/modules.xml | 2 +- Apps/AiTeJiYiChong/Crawler.py | 6 +- Apps/AiTeJiYiChong/Opener.py | 15 +---- Apps/AiTeJiYiChong/ReadImageKit.py | 62 +++++++++++++++++ Apps/AiTeJiYiChong/Service.py | 63 ++++++++++++++++++ Apps/AiTeJiYiChong/TestClick.py | 41 ------------ .../__pycache__/Crawler.cpython-310.pyc | Bin 7883 -> 7505 bytes .../__pycache__/Opener.cpython-310.pyc | Bin 1737 -> 1464 bytes .../__pycache__/ReadImageKit.cpython-310.pyc | Bin 9538 -> 10898 bytes .../__pycache__/Service.cpython-310.pyc | Bin 5449 -> 6506 bytes Apps/AiTeJiYiChong/说明.txt | 1 - Apps/XinDianTu/SearchButton.jpg | Bin 1303 -> 0 bytes Config/Config.py | 20 +++--- Config/__pycache__/Config.cpython-310.pyc | Bin 1327 -> 1330 bytes Util/OcrParser.py | 4 +- Util/PaddleOCRKit.py | 12 +++- Util/__pycache__/OcrParser.cpython-310.pyc | Bin 2165 -> 2155 bytes 18 files changed, 155 insertions(+), 85 deletions(-) delete mode 100644 .idea/Crawler.iml delete mode 100644 Apps/AiTeJiYiChong/TestClick.py delete mode 100644 Apps/AiTeJiYiChong/说明.txt delete mode 100644 Apps/XinDianTu/SearchButton.jpg diff --git a/.idea/Crawler.iml b/.idea/Crawler.iml deleted file mode 100644 index 4ba3f29..0000000 --- a/.idea/Crawler.iml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index f1a2754..ad51e97 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/Apps/AiTeJiYiChong/Crawler.py b/Apps/AiTeJiYiChong/Crawler.py index 55bfeb6..13bce89 100644 --- a/Apps/AiTeJiYiChong/Crawler.py +++ b/Apps/AiTeJiYiChong/Crawler.py @@ -74,11 +74,11 @@ async def get_station_list(d, service, max_scrolls=MAX_SCROLLS): logger.info("正在执行图形学切片分析...") json_data = Kit.crop_cards_from_image(screenshot_path) - # 3. 调用 VL 模型识别并保存数据 - stations = await service.process_station_list_vl(screenshot_path, device_info=device_info) + # 3. 调用混合模式识别 (图形学切片 + 本地 OCR) + stations = await service.process_station_list_hybrid(screenshot_path, device_info=device_info) logger.info(f"本页识别到 {len(stations)} 个场站") - # 4. 匹配几何卡片与 VL 识别结果 + # 4. 匹配几何卡片与识别结果 (混合模式下已经包含在 stations 中,但为了兼容旧逻辑进行填充) if json_data and json_data.get("cards") and stations: for card in json_data["cards"]: card_rect = card["rect"] # [x1, y1, x2, y2] diff --git a/Apps/AiTeJiYiChong/Opener.py b/Apps/AiTeJiYiChong/Opener.py index fa03766..2b778a7 100644 --- a/Apps/AiTeJiYiChong/Opener.py +++ b/Apps/AiTeJiYiChong/Opener.py @@ -27,18 +27,9 @@ async def open_mini_program(): await asyncio.sleep(5) # 2. 确保在消息列表页并点击搜索 - logger.info("尝试查找并点击 '搜索按钮'...") - # 优先尝试从 XinDianTu 的模板中复用 SearchButton.jpg (如果存在) - search_template = os.path.join(os.path.dirname(BASE_DIR), "XinDianTu", "Templates", "SearchButton.jpg") - if not os.path.exists(search_template): - search_template = os.path.join(BASE_DIR, "Templates", "SearchButton.jpg") - - if click_image_template(d, search_template): - logger.info("点击了搜索按钮") - else: - logger.warning("未找到搜索按钮,使用坐标点击 (84%, 8%)") - w, h = d.window_size() - d.click(int(w * 0.84), int(h * 0.08)) + logger.info("直接使用坐标点击 '搜索按钮' (84%, 8%)...") + w, h = d.window_size() + d.click(int(w * 0.84), int(h * 0.08)) await asyncio.sleep(2) diff --git a/Apps/AiTeJiYiChong/ReadImageKit.py b/Apps/AiTeJiYiChong/ReadImageKit.py index dad2c08..4a30318 100644 --- a/Apps/AiTeJiYiChong/ReadImageKit.py +++ b/Apps/AiTeJiYiChong/ReadImageKit.py @@ -7,6 +7,7 @@ import json import aiohttp import logging import base64 +import cv2 from openai import AsyncOpenAI, BadRequestError from Config.Config import ( ALY_LLM_API_KEY, VL_MODEL_NAME, VL_MODEL_NAME_AD @@ -15,6 +16,8 @@ from Apps.AiTeJiYiChong.Config.Setting import ( SAFE_EXCLUDE_RATIO, FALLBACK_WIDTH, FALLBACK_HEIGHT, BOTTOM_SAFE_EXCLUDE_RATIO ) +from Util.PaddleOCRKit import get_ocr_kit +from Apps.AiTeJiYiChong import Kit logger = logging.getLogger(__name__) @@ -287,6 +290,65 @@ class ReadImageKit: logger.error(f"Error calling VL model for detail: {e}") return None + @classmethod + async def get_stations_hybrid(cls, image_path: str, device_info=None): + """ + 混合识别模式:图形学切片 + 本地 PaddleOCR 识别 + """ + if not os.path.exists(image_path): + logger.error(f"Image not found: {image_path}") + return [] + + # 1. 使用 Kit 中的图形学算法识别卡片区域 + # Kit.crop_cards_from_image 会生成 .json, _flag.jpg, _vl.jpg + # 我们主要需要它返回的 json_data + json_data = Kit.crop_cards_from_image(image_path, save_debug=True) + if not json_data or not json_data.get("cards"): + logger.warning("No cards detected by graphical slicing.") + return [] + + img = Image.open(image_path).convert("RGB") + ocr_kit = get_ocr_kit() + + final_stations = [] + + # 2. 对每个卡片区域进行 OCR 识别 + # 注意:PaddleOCR 识别过程较快,且通常不涉及网络请求,可以根据需要选择并行或串行 + # 这里使用串行以保证日志输出整齐,如果追求极致性能可改用 asyncio.to_thread 并行 + for card in json_data["cards"]: + rect = card["rect"] # [x1, y1, x2, y2] + # 裁剪卡片 + patch = img.crop((rect[0], rect[1], rect[2], rect[3])) + + # 转换为 ndarray 供 PaddleOCR 使用 + patch_cv = cv2.cvtColor(np.array(patch), cv2.COLOR_RGB2BGR) + + # OCR 识别 + logger.info(f"正在识别卡片 {card['id']}: {rect}") + res = ocr_kit.recognize(patch_cv) + + if res and res.get("station_name"): + # 注入点击坐标和原始区域信息 + res["uia_center_x"] = card["click_point"][0] + res["uia_center_y"] = card["click_point"][1] + res["rect"] = rect + + # 转换 bounds 到 0-1000 空间(保持与 VL 模式兼容) + w, h = img.size + res["bounds"] = [ + int(rect[0] * 1000 / w), + int(rect[1] * 1000 / h), + int(rect[2] * 1000 / w), + int(rect[3] * 1000 / h) + ] + + final_stations.append(res) + logger.info(f"卡片 {card['id']} 识别成功: {res['station_name']}") + else: + logger.warning(f"卡片 {card['id']} 识别失败或无名称") + + return final_stations + @classmethod async def get_stations_from_image(cls, image_path: str, device_info=None): """ diff --git a/Apps/AiTeJiYiChong/Service.py b/Apps/AiTeJiYiChong/Service.py index b5ada8d..7bf3baf 100644 --- a/Apps/AiTeJiYiChong/Service.py +++ b/Apps/AiTeJiYiChong/Service.py @@ -125,6 +125,69 @@ class AiTeJiYiChongService: logger.info(f"场站详情处理完成: {name}") return detail + async def process_station_list_hybrid(self, image_path, device_info=None) -> list: + """ + 基于混合模式处理场站列表 (图形学切片 + 本地 OCR) + """ + station_list = await ReadImageKit.get_stations_hybrid(image_path, device_info=device_info) + if not station_list: + return [] + + processed_stations = [] + async with await self.db.get_session() as session: + for station in station_list: + name = station.get("station_name") + if not name: + continue + + station_hash = self.get_hash(name) + now = datetime.now() + station["station_hash"] = station_hash + + # 1. 保存 Profile + profile_id = self.generate_id() + await self.station_profile_model.save( + session=session, + id=profile_id, + station_hash=station_hash, + operator=self.operator, + station_name=name, + valid_start_time=now + ) + station["profile_id"] = profile_id + station["valid_start_time"] = now.isoformat() + + # 2. 保存 Status (解析价格和电桩) + status_id = self.generate_id() + + # 处理 piles 字段 + piles_data = station.get("piles") + total, free = 0, 0 + if isinstance(piles_data, list): + for p in piles_data: + total += int(p.get("total", 0)) + free += int(p.get("free", 0)) + + await self.station_status_model.save( + session=session, + id=status_id, + station_hash=station_hash, + total_piles=total, + free_piles=free, + piles_detail_json=piles_data, + current_price=float(station.get("price", 0)) if station.get("price") else 0.0, + parking_info=station.get("parking", ""), + distance=station.get("distance", ""), + valid_start_time=now + ) + station["status_id"] = status_id + + processed_stations.append(station) + + await session.commit() + + return processed_stations + async def process_station_list_vl(self, image_path, device_info=None) -> list: """ 基于 VL 模式处理场站列表 diff --git a/Apps/AiTeJiYiChong/TestClick.py b/Apps/AiTeJiYiChong/TestClick.py deleted file mode 100644 index 15924f0..0000000 --- a/Apps/AiTeJiYiChong/TestClick.py +++ /dev/null @@ -1,41 +0,0 @@ -# coding=utf-8 -import asyncio -import uiautomator2 as u2 -import os -import sys -import uuid - -project_root = r"D:\dsWork\aiData" -if project_root not in sys.path: - sys.path.append(project_root) - -from Apps.AiTeJiYiChong import Kit -from Apps.AiTeJiYiChong.Kit import take_screenshot, read_image -from Config.Config import TEMP_IMAGE_DIR - -async def test_click_and_detail(): - d = u2.connect() - image_uuid = str(uuid.uuid4()) - print(f"Taking initial screenshot...") - screenshot_path = take_screenshot(d, image_uuid, save_dir=TEMP_IMAGE_DIR) - - print(f"Analyzing cards in {screenshot_path}...") - json_data = Kit.crop_cards_from_image(screenshot_path) - - if json_data and json_data.get("cards"): - first_card = json_data["cards"][0] - click_x, click_y = first_card["click_point"] - print(f"Clicking card at ({click_x}, {click_y})...") - d.click(click_x, click_y) - - print("Waiting for detail page...") - await asyncio.sleep(5) - - detail_uuid = f"detail_{image_uuid}" - detail_path = take_screenshot(d, detail_uuid, save_dir=TEMP_IMAGE_DIR) - print(f"Detail page screenshot: {detail_path}") - else: - print("No cards found on current screen.") - -if __name__ == "__main__": - asyncio.run(test_click_and_detail()) diff --git a/Apps/AiTeJiYiChong/__pycache__/Crawler.cpython-310.pyc b/Apps/AiTeJiYiChong/__pycache__/Crawler.cpython-310.pyc index d57bc83df26612c1e05d5b76e553fb9c7e808e94..6d625981c0809c95ae12bec846642bd4e490217f 100644 GIT binary patch delta 1503 zcmZ8hTTC2P7@jjT3)=w}c3GComWs664(u+=rI!#`O1ZU7B}C9vDvraRaT(m58P3cW zXa><>Bc{@joX4gKm>BJo)itI`9~!OtVtml2X4LqgRr{om#uq*RV1YQv`Okm;%lF^T zoUi-8?G2e#RT9U(sh_c4pZF*=!iPk56xh1YmVJV%{E2cj$;pA@Y5F&xi2QQ*>aXv- z{cv;RxA$*9yngr5TN`vjsOM#YUK0-UvPd5YUE(c{L}|Bpp{Is{@UKgvh(sjuHH?ag z#F#J(As&C7jHzO4jV=2ndSA5A#Zph;Bx=sMm0Kc?Y@Di6f2N8XD#{(acO~ zz3dLZy6_Xu;DI+eH#p2REA4LkFgH`bl5i7SN4GiVchM2Hj^Wcg=NsHjej6cXy(PN| z;5PY%F=oNzL0=xg$tKQu(k;WiQHIC!E6J6VyHD!0HE{oFI#$wdj+<|BlWxlGaMSn{ z?%D_-&Z*mqIqlo%9EYpVa)?_v?gm*RANXO;I3YKN7eI+quQ@3i$t|7jjWc& zLpq|LRiEqxLm7D@HVsYYJwBE8kVAa;Jq)QYuiH-6ELfR4RIYgxPm(ggu2|F!Y%VIc zens;{-FU?$DVhwQJs7u$nbmAtu^rXXO+x{HWo~(v=$LMVkDwU+IGiq%A+}#NJ?uPPQBao@J4?)b-X>wN z7z8)8=%G2%Oz%a`GjOSPjCJPO+B7;&*J?ivOHi-h6PskfoX$sEp7ty51_-}(H93~Z z{t6OIWq(d@N8f90Kp`QBBosv-_2KmNtet0mkdX4G5prU|CQDlC6N^T<)AS}{tMO`gA zW~>QmZz{RMq!&SVkc8Jvz$bf}iDH{UzuR|)SU@hgXZkjHr& iYC%&JPas8OUzs}trmKers;aovV5@XESkK7%Q6yDigJN71V94B$?rfJhZU>nDE9Qq@Zq%EXzQc6{+6|GXrYUA0un>w~T zJ8qmZCP7JoRyB&477kUBBY~hG1jtnd65@iyfj@!h0qun!DT#XE0OC}T%FMb=%SiL) z&G+7XZ{EC_`7!a$fG^kBs0gfG{s5X?y`T8@iM~2Em0ACib?bGii#t*-0?rE7Mgl4l zbT0ywgmpxO67-xG!@^bJnpl#FP!Wl|2u1}cjR++daiJuZi3_{tM3f}1A>o8lauavO zO+>~p3(K>dZ+b&cpe!i&0^xV zn`NZdA&CukAeAxntY%>yo4Kr()h7*`Hc8&Cw#UdqYs$o@Y{j(9Ec3{w3|r2a7Pb{O zL)fvZb##psSI3kZyLQ@`9&5004jIs4vuy9lLMG$r*9Eke9+D0Wb+ORmtRl-m28!fo zGT;iZ(FZ(00d64Pl|{6UIi>g}@3%gtG_pR&x^Y#N8mtNVg+XYKsfUY+ynQ{3&bjq0DemxGEZeIiE?d0JYz8z5kBSMF4(h1z#E7gCR!PxD3-RBV&owd zcZY;~mfljF2oqgo8;Ox#5{J8ByzBx3ZmR@wo~1C^^%qX`t`=U&ZB(2Q?qFJGeqTZXx;p^CN`joAPrhv@;G($8;M zDmR%Q{Epu8-3C$mMN=5;pg%W_fOfjU-zJ{T(0>1Bu#W2fn7fyUh|@RyaWF=|_V>>O z7+`xW18Y!cH?^MITR7%5iYX({uR7Yv!NkcCeEmJR4^b06EujpigfsehYeV1V`nZua`_ zJrNTYooC`RiY!eto31^SF@+yWjROsHYWjDetKK=5CwSyey1u2&onWfu zbt^i?!MaQ?oo3ZX2RQ{#%9gBY%a*apK4Iz5=m8{hOPq@n++3%RTX}Xv(er%PkVm-* zBZW1T%VBiffeNNxz`04C{l9T^kwNs=jxez4osOS&Il1sp6*>9wtkM15@qb^_YzY;z a4<%E}h`Ks=H+Bd!9#z@oX=k7H-TwfS&+H8V diff --git a/Apps/AiTeJiYiChong/__pycache__/Opener.cpython-310.pyc b/Apps/AiTeJiYiChong/__pycache__/Opener.cpython-310.pyc index 92f6bbc5fa4b731f2603413af7f0cdefe4758139..b075cfa549bc90299283a0710c047be815b513fb 100644 GIT binary patch delta 478 zcmZWjO(;ZB6u#%)_vYt~86z4N)Rf;TrbwABQP>D8Qm^4YdEt%T8%;#SLQ0Y=8`KOb zHcD9#vaqtWy&D^5vL$QIAc<4w^nK@i=X~eRf9?w;{CCorigf*pu|m0r!@WWk5u^mPZ*1B&nud+?Rna!rh$&IZZQOkO3gL zrEz~AeQE-KG=<-q|1LqiUHoNJ^kai(MU;kITqd)l%?*!xvVg>W^hl|fM6KL9_QhYkP$ delta 753 zcmZ`#-)qxQ7|l)6rcHmZomzEeFQXP_K^eFw(NS6JquqlRA!NOAP1mI*xurTPuJ_9hREDXk&RX`XALzG!8U{KrD zb;Ga)atsu*3~5li$iQL*j!=f^O!S|b*neY2hcSnSG1T?&(Cf%wFE`}#Oe$`kV;{AX z$ov$zM+YcVw>mPeNulp-Iy|wq_Nqcjv|LUQ=vHtDu^JF@mE_g4iT1J(%xq87n zr!3VfGE$7?a9)x1Vriz1P*qEpYYX*J;`!TT|J|*FF7+v**jvwN&h2fgB>x0_-`&{% z@Tq_ANw2eMch?60aAJCDVsdCU*(DmFud344ox$SZK()rfLh=*HATBZAgZ?tQ1_uidtO6oT{OM*HAPlEh;yR z6psNcgbZgR2@Q6{pn*Z@DWe}JerATBO`Il#z3JgaAaX$vCU}(f(zWgJ0LIJ}*D2Rz I81O%T0pAhswg3PC diff --git a/Apps/AiTeJiYiChong/__pycache__/ReadImageKit.cpython-310.pyc b/Apps/AiTeJiYiChong/__pycache__/ReadImageKit.cpython-310.pyc index 791acdb4be93bef1c23b7c09db987d9948b1dd7f..46ca2e7de21d73c400aeaaea5b6f5d64d7747d0c 100644 GIT binary patch delta 2822 zcmb7GU2Ggz6`nh@|9@Vu*FWoZ>~%t^mWZS^SfQ>Jk~k!yL{8!)Z8Efs$9u=Sz_s- z!L0V1bI;#B_uPBVonJol`lW;sk4HFoPX3vy>g0N2i2Qo};7pxpQ87w6Drhl1F2?nQ zm>?XCeOi~E6q9%C&H-Y53y{bIkz4`>5=M$CA0P#e^yWB zP-E}ohru!Uo40@oOrv~q^AGV+{_)SCgp^#Ovq#jU zl4VG`TCQ4(dCl3Eyg4zBy22AFtN>TyYeRWN%Oj8Z~i6ua}qd= z@+X})Q~Ss<=Y!Pvr;j7!#I_Y=hb%oBMQBo!^*JgZz3q(jOxH04mIat*JH`-0+cV0J z0p!Chf%MY=t^oOW1zlcZk0Eaac|Ox%mg{G7xu~$Cz{$ti=TQ(=%a+0xWzBR6+nvD; zFvYBD79&qNf9)BI?#Yz%sdSdCZk|fV{D~yE_yO^M2^Je$oQ@?;_0A<48DqbUCZ!cLy{WH;+PF_a}A zZvHmg#ZS$E)-=0-x)%{HAz)1GS%k|7R}e&mFC#n;@bG~El!U`sCp&z~xjH;qXE-zw z0swA8sxU*ZSQ1q%S=Cq-C5s3cF1wDfhMW>tk^17^B1{Vz!s=4!=2<_*r)~V zAPr`?TFCY_;&zCJG8|yo!-$8`3^xznYhkONXmnZ0MzeZn!8-_V z-$L*6d@WXsTYc@o>a-`#*|99QN<0>rc%1kS2O@q%2cqBADf+;58e9h&{dN?C^uq7m z3BM2IUAU0;60RNbGP*6VbF}}ifM(Z@*a2ut1J!e|IgwoF*}8wfb!+XxPhV-R{b=i* zX6yZL{O$eQt&Lx_KKM@S-uGH-uYUCPS91q*TX%lky7O-CoJ^^voSmADJn<)@yH0 z+e0+goej-1=6db?fFw-+wnhz~({DiU=hHXJt52j{_z47MM|yygW$r zP_L4z%h2FXgUk(HmsuH7z;Lnbs>doAAEQTW=8oNSaaZC&q7Og2mGnmVlE3RK= zOkNh_Q)kbdosl4aV<%3}cqK1}A(2M0tgh4*=&9<8!j7PK?6LX8Zt1&Gsw}DnMZ%6J zhP~cKWlMGiRWFLc&gCd3=GC&SLD%zAY>GZy30uS9{1w?Ml*Ewtk_wBi01eqC*W33_ zAGZLrdQI88b9(T~-F73DmgksCAA{{SvDNc0$NWj+BMElM@v zBjCpu+d#Mj&?%CFu2?05x&q!}-raBmHM|3Y7qfTovKNuUcEKzF7b;3N&9)``8nRzO zxQ%cZ!P{gH(mVU@UG^9@ToeB|@bu*r;V1ft$Ia(lf4Qnxmf7ndcZG9bJku@!tRXij zo6F^bYPi9YY?d^2j*S9a49coevaE_5)Qn;gYeoY$TX$ak#6n%{zGSJ|p`A7bpL6Z{ zNgc0L%tOc3i^?hipjAyditWk7 a9SLzUIEdG#Lh&* z>?arQypZ>Exq*oK9lSy9hibd|3c0cS@VSeclX0^~*3B6?5}^?qbMo$>G3X8%L+-FK z9BOfA#4Q*Fw`dgIQDf9C86^^7>1$(b{5mlvo{P`~P3}Z!ayx2FQgS|`r*?n8CB7q* z#-?1$}%faTBenq_%<=d=%fmo?slVh(}|)g3X0-p_8GD)e#?GC^5S~#_356B zzA*)vGub)^tHI6H!1tc&R`d5qXC6ThX-VQjUwFpkzUkUthqJ&F&7rFck7BHLv__$Z zi(^F$Z*-3g-y(^_=${q8j7*WbNEYS}A4lQDy)2zbvff`s zYSFRW%halWChWq}CYAsb3QO>JvZ|rCGWzNYdK$85KcOJCCgW0bt#x<+wJFqMfe&29 z!Sb367L}ss;21j6w#ON)Sxz7c?7cxIfCU|g1DO}|#oA2YPLf7X-7EG~3|2Z4UpnuYtY3WQMXeyTQ!x^!}|$BNcFq+rAgI7D%XrJDQp4*I?)tkJF^9l=A6{$NKx+vB3Nq7h ztRU!R!WPQghz}5ZcPO+5aeBisDk&pa5JZ3Sz7h!)y)5Hi$8B%OsMnU-ndeVI6r-uI z^wM}$nMTsG{TAnKnRNVS)ApLMDn8X$FUhnT$5TpT03Tvb6A?~pUjgCQBem%II8k+? X!h(uIDv~9seg7d+B;(pZd_?;bStvw~ diff --git a/Apps/AiTeJiYiChong/__pycache__/Service.cpython-310.pyc b/Apps/AiTeJiYiChong/__pycache__/Service.cpython-310.pyc index 446095f15082f12556125fe2e7240ef464d4acf9..5a6a5d565aa8729e3e61b83033b712bb3b5ebf21 100644 GIT binary patch delta 1233 zcmYk5-EZ4e6u|Fw65IK(<2WWO8ifpLsObkqoXmqu z2SW~$W@mCDBXZy(GkKwjEXypZ{UVfrU1jPx5!qfLBp_=b_s`~&ayq0hu^5XinFuwV2{OQGw%WuZZYa3sF z7%zVCcX+Kj5?}ox{(dF?`m=cP(#BhtsynLd%U{LI-&Bw7pR8@>TBT8*Ra&pR)2)Wv zIo+M$V^E5Z0#@Z7tENYpId`_@t;()7d=DrbA~(RBtVo+{^4Hu>J0g+JT+eTIrdzA> zJF7nSBn0psfG7)Q|E$+=S?y|CdM(56Ub+n8yIh zf|Hh?*iAYnuNd3&n12v*{ie}YPVl`DbjvjOKG69i2z)C37-BynsSN)Olt(;{cmi<< zaTt*d;|NOFx2%@VJbltuv9om+s!jr_lKF-yZh6z-+AO&c5An5NZgp@Lu(M09WwR4O_YO4UV9p+qkYhb0M@sOTUL&Mt2k zoCG)NBuR*K1z&D}u7R$QD zzQPPPd7q&=lUze?vI_DERz6JG)nTY`ZTMzTWyU6n#@tJO=JvSX4?1E6Q^g{JorRO} zX=s%6HqC^5;6}D0h*TvcnK+1@!QVXA7p{vYfiWJ6qoTRc5$D|Zl2oEH9>tD-=Gt&o zqGk&XVhJJ1<2t^GdYpk@xq`LwM$r(4l-DI}Lfx91pySfT1HU)G7zz*NTAt?qcd&0& zW_Qp`3!_i=m=iljM)?#3U))x%8c9~@I1Uk>`Io7t|L*yNhlKbpjlfc9q86R$UYcTN5AP(YMcN7 diff --git a/Apps/AiTeJiYiChong/说明.txt b/Apps/AiTeJiYiChong/说明.txt deleted file mode 100644 index 849e1c8..0000000 --- a/Apps/AiTeJiYiChong/说明.txt +++ /dev/null @@ -1 +0,0 @@ -微信小程序名称: 艾特吉易充 \ No newline at end of file diff --git a/Apps/XinDianTu/SearchButton.jpg b/Apps/XinDianTu/SearchButton.jpg deleted file mode 100644 index 391d4f9a8562a4c2c0c0b8c1d078808da3e304e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1303 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<4xy^-J4je!1|}vT0R_w~j7+Qy0)h%`NYIs8UOnTD$$npBSH?c+J9EvaSBdTBX`Z~psc7dpTTKfW?)%^8*_6BrDe%w>o%$W* zPeEkwgB<1nb_g(7>>1hdC}4sqFcts?BP%O27dy;fj7$v7EJBI`f`*QP!b*)I3Pw(e zg+&_=K2$a^p0x1dC8$r??3uE!I4~Ps_X~Z<8?@#7(q&}}7OvRpFP7(3m>emi{^7n~ z@v2#GyWHD)x3@_S*QGNc_r5$be-tX{^=)x-c}O;Mg=o76B|6X7zG&=9R&;%0~ab3Hcs4l z(cs|+Sd`f-F8h7WgR4dO*%j%jzm~OZe=;}efofoi-Fan z&+De{`_;c@d-iT=rKA5DW`~`Y*);F!Ue+z^E-X#k#{D~Cg->_gLLoQz5Eg|w7g!i9 zE_!#5g0@ZHy%_lcnA+8fkhTV4(8!nMX{*~E^0Co8w#_8YF4; z9OALP`XNAtu{rML)n7-C*{l?3$*L(lb4IPWeh#yNu%WoT%O4jOH`l#4e;f?56x4cZ zm3q<;Ku1+c1b~{A+jndPJ z&NsLsudS9-em8NIgGY%n%gxuvwwz;J*J+j>x^F(i8BW28h6M{}sI1Ki;W%j78m#xN VJZh@ZhCnN}yjkCy^)LRv2>>Z4!e#&f diff --git a/Config/Config.py b/Config/Config.py index db0ed57..773e1d8 100644 --- a/Config/Config.py +++ b/Config/Config.py @@ -1,16 +1,16 @@ # 黄海在公司内网开发时的配置信息 -DORIS_HOST = "10.10.14.204" -DORIS_PORT = 9030 -DORIS_FENODES = "10.10.14.204:8030" -REDIS_HOST = '10.10.14.14' -REDIS_PASSWORD = None # 如果没有密码则设为 None +# DORIS_HOST = "10.10.14.204" +# DORIS_PORT = 9030 +# DORIS_FENODES = "10.10.14.204:8030" +# REDIS_HOST = '10.10.14.14' +# REDIS_PASSWORD = None # 如果没有密码则设为 None # 黄海在家开发时的配置信息 -#DORIS_HOST = "www.hzkjai.com" -#DORIS_PORT = 27025 -#DORIS_FENODES = "www.hzkjai.com:27024" -#REDIS_HOST = '127.0.0.1' -#REDIS_PASSWORD = "DsideaL147258369" +DORIS_HOST = "www.hzkjai.com" +DORIS_PORT = 27025 +DORIS_FENODES = "www.hzkjai.com:27024" +REDIS_HOST = '127.0.0.1' +REDIS_PASSWORD = "DsideaL147258369" # 视觉模型配置 VL_MODEL_NAME = "qwen3-vl-flash" diff --git a/Config/__pycache__/Config.cpython-310.pyc b/Config/__pycache__/Config.cpython-310.pyc index afc66d1d66befa0bfe346db423f4bf45b1aef58f..0a90099a73e67a439aaba4f0e5bd8baaf8c7b9e8 100644 GIT binary patch delta 232 zcmZ3_wTX*2pO=@50SHVVrew~U$eUHq5+#%(6eXM@oGLh*Aw?ur2uO;iGJx5PKvFDK z7)XlG<&F|bk-!j_oXegnm@1UYlq#GeHHS4yG(|c}EJY?tJViE2B1JArGDSX0Dn%if zK~u4cue`imFQY0uD=||qIX^dZVkQGam5~UlsFjhqfssiSr=gL#o&gXVMhUnSXQrek q`WTv+8<|=dn^|raVboxp?8o$w(QmUp^Fc;#4i-izWS;z+#RLGRtUL$+ delta 228 zcmdnQwVsPNpO=@50SJ~`rDRT@$eUF!6eW}*93`A0k}5cxAw@J*2uO;hGJx5PKvFza z7)VOY<&F|bk;D*}n#-Olm@1UYlq#GeJ%=?)G({##EJZd-JVh=_B1Jw*GDRUuDupGO zK~u4c$Iw6zgiQ2|3`{cJlo=SR1P$eo#H=g~j18)|;mQn6{5ESaYA^~4xD;omq$c_p gnwT4zS{R#IPWESdwAqOHAR{*;3k-5i{>Neh0E0y|v;Y7A diff --git a/Util/OcrParser.py b/Util/OcrParser.py index 622d172..f26ab09 100644 --- a/Util/OcrParser.py +++ b/Util/OcrParser.py @@ -50,8 +50,8 @@ class OcrParser: # 2. 距离 (Distance) for line in clean_lines: - # 匹配 "7.4km", "17.4km" - m = re.search(r"(\d+(\.\d+)?)\s*km", line, re.IGNORECASE) + # 匹配 "7.4km", "17.4km", "90m" + m = re.search(r"(\d+(\.\d+)?)\s*(km|m)", line, re.IGNORECASE) if m: result["distance"] = m.group(0) break diff --git a/Util/PaddleOCRKit.py b/Util/PaddleOCRKit.py index 9d4b24e..e67e880 100644 --- a/Util/PaddleOCRKit.py +++ b/Util/PaddleOCRKit.py @@ -26,13 +26,23 @@ class PaddleOCRKit: Using PP-OCRv4 mobile model for speed. """ try: + # 1. 抑制 PaddlePaddle 的日志输出 + os.environ['GLOG_minloglevel'] = '3' # 抑制 GLOG (C++) 日志 + os.environ['FLAGS_allocator_strategy'] = 'auto_growth' # 减少显存占用警告 + + # 2. 抑制 Python 层的 paddle 日志 + import logging as py_logging + py_logging.getLogger('paddle').setLevel(py_logging.ERROR) + py_logging.getLogger('ppocr').setLevel(py_logging.ERROR) + logger.info("Initializing PaddleOCR (PP-OCRv4 Mobile)...") # use_angle_cls is deprecated, using use_textline_orientation instead # ocr_version='PP-OCRv4' defaults to mobile model self._ocr = PaddleOCR( use_textline_orientation=True, lang="ch", - ocr_version='PP-OCRv4' + ocr_version='PP-OCRv4', + show_log=False # 关键:关闭 PaddleOCR 内部日志打印 ) logger.info("PaddleOCR initialized successfully.") except Exception as e: diff --git a/Util/__pycache__/OcrParser.cpython-310.pyc b/Util/__pycache__/OcrParser.cpython-310.pyc index b36f8f595e10d4f99773546aa80f47e212fd5baa..49ac918ed33fee805fcc51378c49b40d1581b6e8 100644 GIT binary patch delta 73 zcmew=@LGU3pO=@50SFd8PRZ2X$Xm%GsN`Z5lTsX>Uz8n_nCX&Ok~n!O%XM)vjhGZ| ajTk*3scEknQ>>+tom-Quxw)V98500MycaqE delta 83 zcmaDY@Kt~}pO=@50SJ7zBxfpY