做自动化脚本的朋友大概都遇到过这种尴尬界面上的按钮明明就在那儿可脚本就是点不准因为按钮没有可用的控件标识或者控件树里压根找不到它。这时候最稳的兜底方案就是把屏幕截下来交给 OCR 把文字认出来再按文字位置去点。EasyClick 这套自动化框架本身提供了不少控件操作能力但一旦碰上游戏界面、自绘 UI、图片按钮、验证码提示这类控件不可达的场景OCR 就成了绕不开的一环。这篇内容就围绕 EasyClick 调用 OCR 文字识别接口这件事展开从为什么要接、接口怎么选、代码怎么写、识别不准怎么调一路讲到实际项目里踩过的坑。适合已经会用 EasyClick 做基础点击、想进一步搞定看图找字的脚本作者也适合刚接触自动化、想弄明白 OCR 在脚本里到底扮演什么角色的新手。全文会给出可直接复现的完整示例代码参数含义、调用时机、结果解析都会讲透看完你就能把屏幕文字识别接进自己的脚本里。1. 为什么脚本里非得塞一个 OCR1.1 控件树拿不到的东西只能靠看EasyClick 的核心能力之一是控件操作通过无障碍服务读取界面节点找到文本、id、类名去定位元素。这条路在标准 Android 应用里非常顺但现实中的目标界面往往不按套路出牌。游戏引擎渲染的画面、Flutter 或 Unity 打包的界面、某些加固过的应用控件树要么是空的要么只有一个巨大的 SurfaceView里面什么节点都没有。你让脚本去text(确定)找按钮它返回空脚本就卡在那儿了。这时候 OCR 的价值就体现出来了它不关心控件树长什么样它只关心屏幕上看起来有什么字。截一张图把图里的文字连同坐标一起吐出来脚本拿着坐标去点击逻辑就闭环了。换句话说OCR 是控件操作的视觉备份控件能找到就用控件找不到就退化成看图找字两条腿走路脚本才稳。我在实际项目里总结出一个判断顺序优先控件定位因为快且准控件定位失败或目标区域是自绘内容时切 OCROCR 也认不出时再考虑模板匹配或固定坐标兜底。这个降级链条写进脚本里稳定性会明显上一个台阶。1.2 OCR 在自动化里的三种典型用法第一种是文字定位点击最常见。比如界面上有个领取奖励的按钮控件抓不到那就 OCR 出领取奖励这四个字的包围盒取中心点点击。第二种是状态判断比如识别屏幕上有没有出现网络异常的提示有就走重试分支。第三种是信息提取比如把界面上的金币数量、倒计时读出来喂给脚本做决策。这三种用法对 OCR 的要求不太一样定位点击要求坐标准状态判断要求召回率高宁可多认也别漏信息提取要求字符准确率高。理解这个差异很重要因为它直接决定你后面调参的方向。定位点击时识别框稍微偏一点没关系中心点还在按钮上就行但信息提取时把8认成B就是灾难。所以同一套 OCR 接口在不同用法下要配不同的预处理和校验策略这个后面会细讲。1.3 别把 OCR 当万能药得泼一盆冷水OCR 是有成本的。一次识别要截图、要传输、要跑模型推理耗时通常在几百毫秒到一两秒比控件查找慢一个数量级。如果你的脚本每秒要判断十几次状态全用 OCR 会把机器拖垮。合理的做法是把 OCR 用在低频但关键的节点上比如进入某个界面后识别一次而不是每帧都识别。另外 OCR 对图像质量敏感分辨率太低、字体太花、背景太杂、文字被遮挡识别率都会掉。所以接 OCR 之前先想清楚目标文字是不是足够清晰、足够大、对比度足够高。如果答案是否定的可能得先做图像预处理裁剪、放大、二值化这部分内容会在第 4 节展开。2. EasyClick 里调 OCR 的几种路子2.1 内置能力与外部接口的取舍EasyClick 生态里做 OCR 大致有三条路。第一条是用框架自带或插件市场里的 OCR 能力优点是集成简单、不用自己搭服务缺点是识别精度和可定制性受限于插件本身。第二条是调用外部 OCR 服务接口把截图编码后发出去拿回 JSON 结果自己解析优点是精度高、语种全、可调参数多缺点是需要网络、有调用配额和延迟。第三条是本地部署识别引擎把模型跑在设备或局域网机器上优点是离线、隐私可控缺点是部署门槛高、包体大。对大多数脚本作者来说第二条路性价比最高接口稳定、文档清楚、返回结构规整调通了就能用。本文的示例代码也以调用外部 OCR 接口为主线来写因为它的通用性最强换成别的服务商时只需要改请求地址和参数映射主体逻辑不变。如果你用的是内置插件思路是一样的只是把发请求换成调插件方法。2.2 接口调用的基本链路不管用哪家服务OCR 接口调用的链路都差不多可以拆成五步截图、编码、请求、解析、映射坐标。截图用 EasyClick 的截屏能力拿到当前屏幕的位图编码是把位图转成 Base64 或者按接口要求打包成表单请求就是发 HTTP 调用解析是把返回的 JSON 里文字和位置信息抽出来映射坐标是把接口返回的、基于图片像素的坐标换算成屏幕上的实际坐标。这五步里最容易出错的是最后一步——坐标映射。因为截图可能被缩放、可能只截了局部区域、可能设备有分辨率适配接口返回的坐标是基于你发过去的那张图的不是基于屏幕的。很多新手直接把接口返回的 x、y 拿去点击结果点偏了排查半天以为是识别不准其实是坐标没换算。这个坑后面会专门讲。2.3 选接口时该看哪几个指标挑 OCR 服务别只看识别准不准这一句宣传语要落到具体指标上。我一般看四个是否返回文字包围盒只有纯文本没坐标的接口做定位点击没法用、是否支持中英混排脚本界面经常中英夹杂、单次调用延迟超过两秒的接口做实时判断会很吃力、免费额度与计费方式脚本跑起来调用量不小得算成本。还有一个容易被忽略的点接口对图片大小和格式的限制。有的接口要求图片不超过 2MB、长边不超过 4096 像素超了会直接报错或者自动压缩导致识别率下降。截图前最好先按接口要求做一次缩放别等报错了再回头改。指标为什么重要建议阈值返回包围盒定位点击必需必须支持中英混排界面文字常见形态优先支持单次延迟影响脚本节奏小于 1.5 秒图片大小限制决定是否要预缩放提前确认计费方式长期运行成本按量算清3. 完整示例代码逐段拆解3.1 截图与编码把屏幕变成接口能吃的格式先看截图这一段。EasyClick 里拿当前屏幕位图通常用截屏相关的方法拿到的是一个位图对象。接口一般要 Base64 字符串所以得先压成 JPEG 或 PNG 字节流再编码。这里有个细节压缩质量别设太高JPEG 质量 80 左右足够 OCR 用质量拉满会让 Base64 字符串变得很大请求体膨胀、传输变慢识别率却提升有限。// 截取当前屏幕压缩为 JPEG 并转 Base64 function captureScreenBase64() { // 获取全屏截图位图 var bmp screenCapture(); if (!bmp) { toast(截图失败检查截屏权限); return null; } // 压缩为 JPEG质量 80兼顾清晰度与体积 var jpegBytes bmp.toBytes(jpg, 80); // 转 Base64 字符串 var base64Str base64Encode(jpegBytes); // 及时回收位图避免内存堆积 bmp.recycle(); return base64Str; }这段代码里有两个容易踩的点。一是recycle()别漏脚本长时间跑位图不回收会内存泄漏跑几个小时就崩。二是截图前要确认截屏权限已经授予否则screenCapture()返回空后面全链路都断。我在项目里习惯在脚本启动时先做一次权限自检把截屏、无障碍这些前置条件都过一遍避免跑到一半才发现权限没给。如果接口对图片尺寸有限制就在压缩前先缩放。缩放比例按长边不超过接口上限来算比如接口限 2000 像素、屏幕长边 2400那就缩到 2000/2400 约 0.83 倍。缩放会损失一点清晰度但通常 OCR 还能认比直接报错强。3.2 发请求与解析返回把 JSON 拆成能用的结构请求部分用 HTTP POST把 Base64 字符串按接口要求的字段名塞进请求体。不同服务商字段名不一样有的叫image有的叫img_base64有的还要求带image_type说明格式。这些以你选的接口文档为准代码里留好配置项换服务商时只改配置不改逻辑。// 调用 OCR 接口返回解析后的文字块数组 function callOcrApi(base64Str) { var url https://your-ocr-endpoint.example.com/recognize; var body { image: base64Str, image_type: jpg, language: zh_en }; var headers { Content-Type: application/json, Authorization: Bearer YOUR_TOKEN }; var resp httpPost(url, JSON.stringify(body), headers, 10000); if (!resp || resp.status ! 200) { log(OCR 请求失败: (resp ? resp.status : 无响应)); return []; } var json JSON.parse(resp.body); // 不同接口字段名不同这里做一层归一化 var blocks []; var rawList json.words_result || json.data || []; for (var i 0; i rawList.length; i) { var item rawList[i]; blocks.push({ text: item.words || item.text || , left: item.location ? item.location.left : item.left, top: item.location ? item.location.top : item.top, width: item.location ? item.location.width : item.width, height: item.location ? item.location.height : item.height }); } return blocks; }这段代码的关键设计是归一化。不同 OCR 服务返回的 JSON 结构五花八门有的把坐标放在location对象里有的平铺在顶层有的字段叫words有的叫text。与其在业务代码里到处判断不如在解析层统一成一种结构后面所有逻辑都只认这一种。这个习惯能省掉大量重复代码换服务商时改动面也小。超时时间设 10 秒是个经验值。网络差的时候接口可能卡住不设超时脚本会一直挂着。设太短又容易误判失败10 秒对大多数 OCR 接口够用。失败时返回空数组而不是抛异常让上层逻辑自己决定重试还是降级这样脚本不会因为一次识别失败就整个崩掉。3.3 坐标映射与点击别让识别结果点歪拿到文字块之后最容易被忽略的就是坐标映射。接口返回的坐标是基于你发过去的那张图的像素坐标而点击需要的是屏幕坐标。如果截图是全屏且没缩放两者一致直接用如果截图缩放过就得按缩放比例还原如果只截了局部区域还得加上区域偏移。// 把图片坐标映射为屏幕坐标并点击文字中心 function clickText(blocks, targetText, scale, offsetX, offsetY) { for (var i 0; i blocks.length; i) { var b blocks[i]; if (b.text.indexOf(targetText) 0) { // 还原缩放并加上偏移 var cx (b.left b.width / 2) / scale offsetX; var cy (b.top b.height / 2) / scale offsetY; click(cx, cy); log(点击 [ b.text ] 于 ( cx , cy )); return true; } } log(未找到目标文字: targetText); return false; }这里的scale是截图相对屏幕的缩放比全屏未缩放就是 1。offsetX、offsetY是局部截图的左上角在屏幕上的偏移全屏截图就是 0。把这两个参数显式传进来而不是写死是为了让同一套函数既能处理全屏也能处理局部截图。我见过太多脚本把坐标写死成全屏逻辑后来想改成局部截图优化性能结果全乱套。还有一个细节点击前最好判断一下坐标是否在屏幕范围内。接口偶尔会返回越界的坐标比如识别到边缘文字时包围盒超出图片直接点可能点到屏幕外或者触发系统手势。加一句范围校验超出就跳过能避免不少莫名其妙的误操作。3.4 串起来一个可复用的识别点击函数把上面几段拼起来就是一个完整的识别并点击流程。实际项目里我会把它封装成一个函数传入目标文字内部完成截图、识别、匹配、点击返回是否成功。这样业务代码里只需要一行调用清爽很多。// 识别屏幕文字并点击返回是否成功 function ocrClick(targetText) { var base64Str captureScreenBase64(); if (!base64Str) return false; var blocks callOcrApi(base64Str); if (blocks.length 0) { log(OCR 无结果); return false; } // 全屏截图缩放比 1偏移 0 return clickText(blocks, targetText, 1, 0, 0); }调用的时候就是ocrClick(领取奖励)简单直接。但要注意这个函数每次调用都会截一次图、发一次请求开销不小。如果同一个界面要连续找多个文字更好的做法是识别一次、把结果缓存下来多次匹配复用同一份结果。这个优化在后面的性能章节会讲。4. 识别不准从图像到参数的排查链路4.1 先分清是没认出来还是认错了OCR 效果不好先别急着换接口得分清是哪种不好。没认出来是指目标文字压根没出现在结果里可能是文字太小、对比度太低、被遮挡或者接口的检测模型没框到。认错了是指结果里有这块区域但文字内容不对比如领取认成领职这是字符识别环节的问题。两种情况的处理方向完全不同没认出来要改图像质量或检测参数认错了要改字符集或后处理。怎么快速区分把截图存下来人眼看一遍再对照接口返回的结果。如果人眼都看不清那 OCR 认不出很正常先解决图像问题如果人眼清清楚楚但 OCR 没框到那是检测环节的问题可以试试调整接口的检测灵敏度参数如果有的话如果框到了但字认错那就是识别环节考虑换语种模型或者加后处理纠错。4.2 图像预处理裁剪、放大、二值化三板斧图像质量是 OCR 效果的地基。三板斧按优先级排裁剪把无关区域去掉让目标文字占比更大放大把太小的文字拉到合适尺寸一般文字高度到 30 像素以上识别率会明显提升二值化把彩色背景压成黑白提升对比度。这三步不一定全用按实际情况选。裁剪最有效也最容易被忽略。如果目标文字固定在屏幕某个区域就别全屏识别只截那一块。好处有三图片小了请求快、无关文字少了干扰少、目标文字占比大了识别准。EasyClick 支持区域截图把区域参数传进去就行。我做过一个对比同一个界面全屏识别要 1.2 秒、识别出 40 多个文字块局部识别只要 0.4 秒、识别出 5 个块又快又准。放大和二值化要看情况。放大用双线性插值就够别用最近邻最近邻放大会让文字边缘出现锯齿反而更难认。二值化阈值别拍脑袋定可以先转灰度再看直方图或者干脆用自适应阈值。不过很多 OCR 接口内部已经做了预处理你外面再做一遍可能适得其反所以这两步建议在裁剪后仍不理想时再上别一上来就全套招呼。4.3 参数与调用策略的微调除了图像调用策略也有讲究。识别区域能限定就限定很多接口支持传区域参数只识别指定矩形内的文字这比截局部图再传更省事。语种要选对纯中文界面选中文模型比中英混排模型更准因为候选字符集小了混淆概率低。返回粒度有的接口支持按行或按字返回定位点击用按行就够信息提取可能要用按字。还有一个反直觉的经验别迷信高精度模式。有些接口提供高精度和快速两档高精度模式延迟可能是快速模式的三倍但识别率只提升几个百分点。对定位点击这种认个大概就行的场景快速模式完全够用省下的时间能让脚本节奏更顺。只有在信息提取、要求字符级准确时才值得上高精度。提示调 OCR 参数时一次只改一个变量改完立刻用同一张截图复测。同时改三四个参数效果变好了你也不知道是哪个起的作用下次遇到问题还是抓瞎。5. 性能与稳定性让 OCR 不拖垮脚本5.1 缓存识别结果别重复劳动前面提过OCR 单次调用不便宜。同一个界面里要找多个文字正确做法是识别一次、缓存结果、多次匹配。更进一步如果界面没变化连截图都可以省。判断界面是否变化可以用简单的图像差分或者干脆用距上次识别是否超过 N 毫秒做节流。// 带缓存的识别同一界面短时间内复用结果 var ocrCache { blocks: [], timestamp: 0 }; var CACHE_TTL 800; // 缓存有效期 800 毫秒 function ocrClickCached(targetText) { var now Date.now(); if (now - ocrCache.timestamp CACHE_TTL || ocrCache.blocks.length 0) { var base64Str captureScreenBase64(); if (!base64Str) return false; ocrCache.blocks callOcrApi(base64Str); ocrCache.timestamp now; } return clickText(ocrCache.blocks, targetText, 1, 0, 0); }缓存有效期设多少要看场景。界面切换频繁的设短一点比如 500 毫秒界面稳定的设长一点比如 2 秒。设太长会拿到过期结果点了已经消失的按钮设太短又起不到缓存作用。800 毫秒是个折中值多数场景能用。5.2 失败重试与降级OCR 调用失败网络抖动、接口限流、返回异常是常态脚本必须能扛住。重试策略我一般用两次重试 指数退避第一次失败等 300 毫秒重试第二次失败等 900 毫秒再试还不行就降级。降级不是放弃而是换条路走比如切回控件定位、或者用固定坐标兜底、或者记录日志后跳过这一步继续往下跑。这里有个原则单点失败不能导致全流程崩。OCR 只是脚本的一个环节它挂了脚本还得能跑。所以每个 OCR 调用都要有超时、有失败返回、有上层兜底别让一个异常把整个脚本带崩。我在项目里会给 OCR 调用包一层 try-catch捕获所有异常转成识别失败的返回值上层按失败处理日志里记下原因方便排查。5.3 并发与节流的边界有的朋友想用多线程并发调 OCR 提速这个要谨慎。多数 OCR 接口对单账号有 QPS 限制并发太高会被限流甚至封禁。而且并发截图本身在设备上就有竞争多个线程同时截屏可能拿到不一致的画面。我的建议是 OCR 调用保持单线程串行靠缓存和局部截图来提速而不是靠并发。如果确实有大量识别需求比如批量处理一堆截图那也应该在服务端做批处理或者用接口提供的批量识别能力而不是在脚本里开一堆线程硬怼。脚本运行在设备上资源有限把设备搞卡了反而得不偿失。优化手段收益代价适用场景局部截图快、准需知道目标区域目标位置固定结果缓存减少重复调用可能拿到过期结果同界面多次匹配快速模式延迟低精度略降定位点击失败重试提升成功率增加耗时网络不稳时并发调用理论提速限流风险、资源竞争不推荐6. 实战里踩过的那些坑6.1 坐标偏移最冤的一种识别不准前面提过坐标映射这里讲个真实场景。有次脚本在某个设备上死活点不准识别结果明明有确定两个字点下去却偏到旁边。排查了半天发现是那台设备有显示缩放截图拿到的分辨率比实际屏幕分辨率大接口返回的坐标是基于大图的直接拿去点击就偏了。解决办法是截图后先按屏幕实际分辨率缩放或者点击前按比例还原。这个坑的教训是永远不要假设截图分辨率和屏幕分辨率一致。不同设备、不同系统版本、有没有开显示缩放都会影响这个关系。稳妥的做法是截图后读一下位图的宽高和屏幕宽高比一下算出实际缩放比再拿这个比去映射坐标。多写这几行能省掉大量点歪的排查时间。6.2 文字被拆成多块匹配逻辑要能容错OCR 返回的文字块粒度不一定符合你的预期。你想找领取奖励结果接口把它拆成领取和奖励两块或者把旁边的图标文字也混进来变成领取奖励5。这时候用indexOf精确匹配就找不到。解决办法是匹配逻辑放宽要么把相邻的文字块按位置合并后再匹配要么用模糊匹配包含关键词即可要么对目标文字做分词后逐词匹配。我一般用包含匹配 位置校验先找包含目标关键词的块再校验它的位置是否在预期区域内两个条件都满足才点。这样既能容错拆分又能避免点到别处的同名文字。如果目标文字可能被拆得很碎那就得做块合并把同一行、间距小的块拼起来再匹配这个逻辑稍微复杂点但对付复杂界面很有效。6.3 接口限流与配额跑着跑着就失败了免费额度的 OCR 接口跑久了会遇到限流表现是突然大量请求返回 429 或者错误码。这时候别慌着改代码先看返回的错误信息确认是限流还是别的问题。如果是限流就得降频加调用间隔、加大缓存有效期、减少不必要的识别。长期跑的项目最好提前算好调用量选个额度够用的方案别等跑挂了才临时抱佛脚。还有个隐蔽的坑失败重试反而加剧限流。接口已经限流了你还在那儿疯狂重试只会让情况更糟。所以重试策略里要识别限流错误码遇到限流就退避更久而不是按普通失败处理。这个细节很多示例代码都不写但实际项目里很关键。6.4 权限与前置条件跑之前先自检OCR 链路依赖截屏权限截屏权限没给screenCapture()返回空后面全断。类似的前置条件还有网络权限、存储权限如果要把截图存下来调试。我的习惯是在脚本启动时跑一个自检函数逐项检查权限、检查网络连通性、检查 OCR 接口是否可达任何一项不过就明确提示而不是等跑到一半莫名其妙失败。自检还有个好处是方便排查。用户反馈脚本不工作你先让他跑自检哪项红了就是哪项的问题比让他描述现象高效得多。这个习惯看起来笨但省下的沟通成本很可观。7. 把它用顺手的几个进阶思路7.1 识别结果结构化业务逻辑才好写原始识别结果是扁平的文字块数组业务代码里到处遍历匹配会很乱。更好的做法是加一层结构化把同一行的块合并成行对象把行按 y 坐标排序再按区域分组。这样业务代码可以按第几行第几个或者某区域内包含某关键词来取逻辑清晰很多。比如判断是否在奖励弹窗可以看屏幕中央区域是否同时出现恭喜和领取两个词判断金币数量可以找金币这个词右边最近的数字块。这些判断建立在结构化结果之上写起来很自然。结构化这层代码不多但能让后续业务逻辑的可读性提升一大截。7.2 和控件定位组合成降级链单靠 OCR 不够稳单靠控件也不够全两者组合才是正解。我常用的降级链是先试控件定位快、准失败则 OCR 定位兜底再失败则模板匹配或固定坐标最后手段。每一层失败都记日志方便分析哪一层在起作用。跑一段时间后看日志如果某层几乎不用可以考虑去掉简化如果某层频繁兜底说明前面的层需要优化。这个降级链的另一个好处是性能自适应控件能搞定的时候不触发 OCR省下调用开销控件搞不定的时候 OCR 顶上保证功能。两条腿走路比单腿蹦稳得多。7.3 调试期把中间产物存下来调 OCR 最痛苦的是看不到中间过程。识别不准你不知道是截图的问题、编码的问题、请求的问题还是解析的问题。解决办法是调试期把每一步的中间产物存下来截图存成文件、Base64 长度打日志、接口原始返回打日志、解析后的结构化结果打日志。出问题时对着这些产物一步步看很快能定位到哪一环。这些日志在正式发布时可以关掉或降级避免占空间。但调试期一定要开这是排查效率的关键。我见过不少人调 OCR 全靠猜改一版试一版效率极低把中间产物存下来多数问题看一眼就明白了。7.4 版本兼容与接口变更的应对OCR 服务商的接口不是一成不变的字段名、返回结构、鉴权方式都可能调整。应对办法是把接口相关的配置和解析逻辑集中到一个模块里业务代码不直接碰原始返回。这样接口一变只改这一个模块业务代码不动。同时解析层要做好字段缺失的容错某个字段没了不至于整个解析崩掉而是降级处理。另外鉴权 token 别硬编码在脚本里放到配置里或者做一层获取逻辑。token 过期是常见问题脚本要能识别鉴权失败并触发重新获取而不是一直拿着过期 token 重试。8. 一些收尾的实操建议写到这里OCR 调用这条链路基本讲透了。最后分享几个我在实际项目里沉淀下来的小习惯都是踩坑换来的。第一先跑通再优化。别一上来就追求局部截图、缓存、降级链全套先用全屏识别把链路跑通确认能识别、能点击再逐步加优化。链路没通就加优化出了问题你分不清是链路问题还是优化引入的问题。第二用真实界面调参别用测试图。测试图往往太干净真实界面有背景、有干扰、有动态元素识别表现差很多。调参一定要在真实目标界面上调调完多跑几轮看稳定性。第三给 OCR 调用留够超时和兜底。网络、接口、设备都可能出问题每个调用都要有超时、有失败返回、有上层处理。别让一个 OCR 异常把整个脚本带崩。第四日志要能定位问题。识别失败时日志里要有截图路径、请求参数摘要、返回状态、解析结果这样排查时不用重现现场。日志级别分好调试期全开正式期只留关键信息。第五定期复测识别率。界面会改版、字体可能变、接口模型可能升级今天能认的明天未必能认。定期跑一遍回归发现识别率下降及时调整比等用户反馈再修主动得多。这套东西用顺了OCR 就不再是脚本里的玄学环节而是一个可控、可调、可兜底的常规能力。控件搞不定的界面截个图认个字脚本照样能稳稳跑下去。
企业数字化 ERP 产品动态
相关推荐
fio硬盘性能测试指南:从原理到实战优化 1. 为什么需要专业的硬盘性能测试 刚入行那会儿,我对硬盘性能测试的理解还停留在简单的文件拷贝计时阶段。直到有次线上服务出现严重IO瓶颈,才发现这种粗放的测试方式根本反映不出真实场景下的性能问题。fio(Flexible I/O Tester)… · 2026/11/4 8:01:40
Java物联网宠物自助洗澡系统设计与实践 1. 项目概述:当宠物店遇上物联网技术 去年帮朋友改造宠物店时,我设计了一套基于Java的宠物自助洗澡系统。这个看似简单的项目,实际上融合了物联网控制、移动支付和宠物行为分析三大技术模块。整套系统部署后,单店每月节省了40%的人… · 2026/11/4 8:01:40
截图转代码工具实战:从视觉到可执行代码的完整指南 1. 这个工具到底在解决什么问题 第一次看到“截图转代码”这个概念的时候,我脑子里蹦出来的第一个念头是:这不就是把设计稿丢进去、代码吐出来吗,前端圈喊了这么多年的“设计稿一键生成”又来了?但真正上手用了一段时间之后&#… · 2026/11/4 8:00:40
中小学信息学竞赛真题的CT式诊断与动态验证方法 简介:本资源为2024年海淀区中小学生信息学竞赛校级预选赛官方试题PDF,面向小学高年级及初中阶段编程初学者,聚焦基础编程能力与算法思维的阶段性测评。试题涵盖编程基础知识单选题(变量命名、赋值语句、进制转换、表达式运算、逻辑… · 2026/11/4 8:36:06
Spring Boot与微信小程序打造智能市容考核系统 1. 项目概述 这个基于Spring Boot和微信小程序的市容监察城市管理考核管理系统,是我最近完成的一个毕业设计项目。作为一名有10年开发经验的全栈工程师,我设计这个系统的初衷是想解决城市管理中常见的考核效率低下、数据不透明等问题。系统采用了前后端分… · 2026/11/4 8:36:06
GEO优化与AI推荐系统的地域内容策略 1. GEO概念解析:内容优化的地理维度 GEO(Geographic Targeting)是数字内容分发领域的核心策略之一,指根据用户地理位置特征进行内容优化的技术体系。这个看似简单的概念背后,其实包含着从数据采集到算法适配的完整技术… · 2026/11/4 8:36:06
ISO/IEC 42001:2023 是组织级 AI 治理的结构性约束协议 简介:本资源为国际标准化组织(ISO)与国际电工委员会(IEC)联合发布的首版人工智能管理体系标准——ISO/IEC 42001:2023官方英文原版PDF文档,面向AI产品研发团队、信息技术安全管理者、企业质量体系建设负责人… · 2026/11/4 8:36:06
.NET Core与微信小程序构建市容监管系统实践 1. 项目概述 市容监察管理系统是一个基于.NET框架和微信小程序的综合解决方案,旨在为城市管理部门提供高效、便捷的市容环境监管工具。作为一名从事软件开发十余年的工程师,我深知这类系统在实际应用中的痛点——传统纸质记录方式效率低下、信息传递滞后… · 2026/11/4 8:36:06
SequenceO1:当推理从token级跃升到序列级,长文本生成的新范式 开篇先说清楚一件事:这篇论文的标题挂着“SequenceO1”,但别被名字骗了。它讲的不是又一个“把O1的结果蒸馏成SFT数据”的跟风工作,而是把O1那套“先想后答”的推理范式,从“单步思考”推广到了“整段序列生成”的层面。我读第一遍… · 2026/11/4 8:35:06
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38