AIDI深度学习模型接入C#上位机:从P/Invoke到缺陷检测全流程
简介这是一份面向C#开发者的AIDI深度学习框架调用示例包用于在.NET项目中完成AIDI集成、模型加载与推理调用可应用到图像识别、自然语言处理等深度学习场景。压缩包共34个文件约1.42MB主要包含C#源码cs、AIDI动态库dll、说明文档docx以及工程配置与调试文件目录分层清晰可直接作为工程模板复用。配套文档细致讲解了dll引用、环境配置、模型初始化与API调用流程示例代码展示了实例化AIDI对象、加载预训练模型、执行预测及解析结果的完整链路并给出错误处理与并发性能优化建议。当前已有253人学习下载适合希望快速掌握AIDI并用C#落地深度学习应用的初中级开发者。1. AIDI调用使用demo.zip到底解决什么问题把深度学习缺陷模型接进C#上位机把离线训练好的深度学习模型接到C#上位机里是视觉项目从算法验证走向产线落地最绕不开的一步。AIDI调用使用demo.zip这类离线包目的就是让你少踩一遍手写进程通信、图像搬运和错误码的坑直接在WinForms或WPF程序里把AIDI深度学习模型的推理跑起来。它解决的问题很具体模型文件不是拿来就能跑的AIDI推理引擎是个黑匣子需要先确认初始化方式、图像输入格式和返回值结构。这篇文章按“拆包、封装、解析、避坑、验证”的顺序把AIDI深度学习C#调用demo的完整链路拆开讲适合拿到离线包不知道从哪个函数开始的上位机工程师也适合技术负责人评估“接进现有产线软件要花多少成本”。2. 先拆AIDI离线包和demo.zip运行库、模型目录与C#工程的对齐2.1 解压后先别急着开sln先看目录里这三类东西拿到手的是一个zip还是rar不重要解压后先按内容分层不要一股脑全丢进Visual Studio。我拆过不少这类工业视觉离线包结构上基本是三类内容混在一起第一类是“运行库目录”里面放着AIDI.dll、OpenCV运行库、onnxruntime等第三方依赖这些是推理引擎真正干活时要用到的二进制文件第二类是“模型目录”也就是训练平台导出的深度学习模型可能是一个单独文件也可能是一个带配置文件、标签文件的目录第三类才是demo本身里面是C、C#、Python三种示例工程而AIDI调用使用demo.zip其实就是把C#示例单独抽出来的那份压缩包。先做一个简单的文件清单映射这是集成第一天的核心工作目录/文件在集成中的角色需要注意的点bin / runtimeAIDI推理引擎dll及其依赖必须整体部署到exe同目录缺一个就是DllNotFoundmodel / weights训练好的深度学习模型路径不要带中文和空格层级越浅越好config / license运行时配置和授权文件换机器需要重新生成机器码事前确认demo_csharp / C# Demo官方给的调用示例优先读这个不要先读C版再自己翻译有些离线包把运行库和demo分开给有些合在一起区别不大核心逻辑一致运行库是给产品用的demo是给你看的。真正部署的时候demo工程本身不需要出现在产线机器上需要带过去的是运行库目录、模型目录和你的上位机程序。所以我在集成第一天就做一个“最小部署目录”空壳把运行库、模型、日志目录、配置目录先规划好后续所有代码都围绕这个结构写避免最后上线时找不到依赖文件。2.2 demo.zip里的C#工程先看这两个文件就够了打开demo.zip里的C#工程后不要漫无目的地翻代码。一个典型的AIDI C# demo会包含一个WinForms或WPF界面项目加上一个封装类库项目有时还会有一个控制台测试项目。新手最容易犯的错是直接打开主窗体的代码在里面找“按钮点击后怎么出结果”。这当然能看到完整调用流程但主窗体代码里混杂了文件选择、日志显示、图片缩放、跨线程刷新这些边界逻辑反而把最核心的原生调用淹没了。我一般按这个顺序读第一步找到项目里名字带Native、Interop、APIWrapper或者AIDIConfig的类这里面是所有DllImport声明先看清楚AIDI.dll对外导出的函数长什么样。第二步找到初始化模型和调用推理的封装类看它的构造函数和公开方法这一步能确定三件事初始化需要传什么参数、图像是以路径传入还是以内存字节传入、返回结果是结构体还是指针。第三步才回头看窗体代码理解界面层是如何调用封装类的。如果demo.zip里没有现成的C#工程只有C示例那也别急着放弃。C示例里的头文件是更权威的接口定义把它翻译成C#的DllImport也就几十行。真正需要注意的是函数参数里有没有回调函数、有没有输出指针这两类在C#里处理方式完全不同后面会详细说。2.3 动手前先用dumpbin确认导出函数名别按旧版本惯性写AIDI离线包在不同版本之间导出函数的命名并不完全一致。同一个初始化接口有的版本叫AIDI_Init有的版本叫AIDI_Initialize还有的可能带Engine后缀。如果直接照抄网上教程里的函数名编译能通过运行时却会抛EntryPointNotFoundException。正确做法是在写一行DllImport之前先看一眼你手里这个AIDI.dll的真实导出表。打开Visual Studio自带的开发者命令行切到AIDI.dll所在目录执行dumpbin /exports AIDI.dll输出结果里能看到完整的导出函数列表包括函数名和序号。如果没有dumpbin也可以用Dependency Walker或者Process Explorer的加载模块功能但dumpbin最直接。重点看三点函数名是否与你准备写的EntryPoint完全一致函数是带数字的stdcall命名还是普通cdecl命名这决定了CallingConvention该选哪一个有没有Release、Free、Destroy这类释放函数这决定了后面怎么管理内存。这一步花不了两分钟但能省下后面一整天的排查时间。AIDI推理引擎对调用方来说是个黑匣子所有内部行为都只能通过导出函数和返回值来观察所以第一手资料必须是导出表而不是网上的二手经验。按我的习惯会把这个导出表导成文本文件存档同时把函数签名整理成一个表格放在代码注释里等下次升级包的时候拿出来对照。3. 用P/Invoke把AIDI.dll接进C#初始化、加载模型与单图推理的最小链路3.1 原生接口声明把AIDI调用收敛到一个Native类里C#调用原生深度学习推理引擎绕不开P/Invoke。AIDI离线包提供的是C语言风格接口所以在C#侧要做的第一件事是把这些导出函数声明成DllImport方法。我习惯把这一层单独放在一个internal静态类里不让业务代码直接看到原生方法这样后续换版本、换函数名只需要改这一个文件。下面这段声明不是某个AIDI版本的标准答案而是我按这类SDK的通用命名整理的最小集合。你拿到demo.zip后一定要先用第2.3节的dumpbin导出表核对一遍把EntryPoint换成你自己那版的实际函数名。using System; using System.Runtime.InteropServices; internal static class AidiNative { private const string DllName AIDI.dll; [DllImport(DllName, EntryPoint AIDI_Init, CallingConvention CallingConvention.Cdecl)] internal static extern int Init(IntPtr configJson); [DllImport(DllName, EntryPoint AIDI_LoadModel, CallingConvention CallingConvention.Cdecl)] internal static extern int LoadModel(int engineHandle, string modelPath); [DllImport(DllName, EntryPoint AIDI_Run, CallingConvention CallingConvention.Cdecl)] internal static extern int Run( int engineHandle, [In] byte[] imageData, int rows, int cols, int stride, IntPtr resultPtr, ref int resultCount); [DllImport(DllName, EntryPoint AIDI_FreeResult, CallingConvention CallingConvention.Cdecl)] internal static extern int FreeResult(IntPtr resultPtr); [DllImport(DllName, EntryPoint AIDI_Release, CallingConvention CallingConvention.Cdecl)] internal static extern int Release(int engineHandle); }这段代码里第一个参数configJson用的是IntPtr而不是string是因为初始化配置在多数SDK里是JSON字符串但传法五花八门有的要求UTF-8字节有的要求ANSI直接用string封送容易踩编码坑。用IntPtr传入由调用方显式Marshal逻辑更可控。engineHandle是初始化后拿到的引擎句柄AIDI内部可能是句柄、指针或索引对C#来说就是int。CallingConvention选Cdecl还是StdCall取决于dll导出表里函数名后面有没有符号。有后缀的通常是stdcall没有的是cdecl。这个参数错了最典型的症状是PInvokeStackImbalance异常后面避坑章节会展开讲。3.2 初始化和加载模型一次Init对应一次Release模型加载放在后台线程有了原生声明下一步是封装一个运行时类把Init、LoadModel、Run、Release的生命周期管起来。这个类直接面向业务代码不暴露任何IntPtr或错误码。public sealed class AidiRuntime : IDisposable { private int _engine; public AidiRuntime(string modelPath, string configJson {\device\:\auto\}) { IntPtr cfg Marshal.StringToHGlobalAnsi(configJson); try { int rc AidiNative.Init(cfg); if (rc ! 0) { throw new InvalidOperationException($AIDI初始化失败错误码: {rc}); } _engine rc; // 有些SDK用返回值当句柄有些用输出参数按demo调整 } finally { Marshal.FreeHGlobal(cfg); } int loadRc AidiNative.LoadModel(_engine, modelPath); if (loadRc ! 0) { throw new InvalidOperationException($模型加载失败错误码: {loadRc}); } } public void Dispose() { if (_engine ! 0) { AidiNative.Release(_engine); _engine 0; } } }初始化配置里我最常遇到两种需求一是指定用CPU还是GPU推理二是设置线程数。device字段传auto让引擎自动选择是省心的开始但产线环境里我建议显式指定。如果工控机有独立显卡跑AIDI深度学习模型的计算量不小GPU推理能明显拉高帧率如果只是试运行CPU模式更省事。configJson的具体字段名要以demo里的示例配置为准别自己发明。模型加载这个动作从调用方视角只是一行LoadModel内部却可能要反序列化网络结构、加载权重、初始化输入输出张量耗时从几秒到几十秒不等。所以在桌面程序里这段代码千万不要放在UI线程直接执行至少包一层Task.Run否则用户会看到一个“未响应”的窗口第一反应是程序崩溃。3.3 单图推理优先传内存字节不要先存成临时文件再传路径demo.zip里常见到两种推理入参传图片路径或传内存图像数据。传路径最简单但产线场景里图片往往来自相机回调或OpenCvSharp处理后的Mat先把Mat存成临时文件再传给引擎不但慢还引入了磁盘IO失败的风险。我一般会优先走内存输入把Mat的像素数据直接Marshal到托管数组。public IReadOnlyListAidiDefect Detect(Mat bgr) { if (bgr.Empty()) { throw new ArgumentException(输入图像为空); } int stride (int)bgr.Step; int bytes stride * bgr.Rows; byte[] buffer new byte[bytes]; Marshal.Copy(bgr.Data, buffer, 0, bytes); IntPtr resultPtr Marshal.AllocHGlobal(Marshal.SizeOfNativeResult()); int count 0; try { int rc AidiNative.Run(_engine, buffer, bgr.Rows, bgr.Cols, stride, resultPtr, ref count); if (rc ! 0) { throw new InvalidOperationException($推理失败错误码: {rc}); } return ParseResult(resultPtr, count); } finally { AidiNative.FreeResult(resultPtr); Marshal.FreeHGlobal(resultPtr); } }这里有个关键参数叫stride它代表图像一行像素占多少字节。很多人以为stride等于cols乘3对连续内存的Mat成立但Mat经过ROI裁剪或拼接后Step可能比cols乘3大因为OpenCV会对行做内存对齐。直接把Step传给引擎引擎才知道下一行从哪里开始否则图像会出现斜切或错位。用Marshal.Copy把Mat.Data拷出来之前先确认Mat.IsContinuous()连续时拷贝效率最高。图像通道顺序也需要提一嘴。OpenCvSharp的Imread读出来是BGR三通道AIDI如果按OpenCV惯例训练和推理预期也是BGR。但如果你用System.Drawing的Bitmap转了一遍很可能变成RGB这时候推理结果会集体飘置信度全崩。我在封装层写死了入参格式为BGR Mat业务侧传什么进来都要先转成这个约定。4. 从指针到List 解析AIDI返回结构并用OpenCvSharp叠加框选4.1 先定义与C头文件对应的结构体不要用IntPtr到处乱指AIDI推理返回的通常不是单个结果而是一组缺陷结果。C#侧要安全读取就得先把原生结构体翻译成托管结构体。翻译时最忌讳的是图省事把整个结果集当成一个byte数组去解析偏移量差一个字段就会读出垃圾数据。正确做法是先定义与C头文件布局一致的结构体用StructLayout和Marshal.PtrToStructure做转换。假设demo里的返回结构长这样实际以你手里的头文件为准[StructLayout(LayoutKind.Sequential)] internal struct NativeDefect { public int classId; public float confidence; public int left; public int top; public int right; public int bottom; public int pointCount; public IntPtr points; // float数组成对存储轮廓坐标 } [StructLayout(LayoutKind.Sequential)] internal struct NativeResult { public int count; public IntPtr defects; }LayoutKind.Sequential保证字段按声明顺序连续排列和C结构体的内存布局一致。注意points字段是IntPtr因为它是变长数组不能直接嵌进结构体里。拿到指针后再按pointCount逐个读出坐标。如果AIDI返回的points是绝对坐标还是相对缺陷框左上角的相对坐标doc说明里通常有写没有的话就用测试图验证。4.2 把指针数组转成托管集合读取时拷贝走别引用原生内存从IntPtr里逐个读结构体代码不长但易错点不少。核心原则是指针指向的是原生内存其生命周期由AIDI引擎管理C#侧应该尽快把数据拷贝成托管对象不要保存IntPtr等到后面再读。private static ListAidiDefect ParseResult(IntPtr resultPtr, int count) { var list new ListAidiDefect(count); var header Marshal.PtrToStructureNativeResult(resultPtr); IntPtr p header.defects; int size Marshal.SizeOfNativeDefect(); for (int i 0; i header.count; i) { var nd Marshal.PtrToStructureNativeDefect(p); p size; var contour new ListPoint2f(); if (nd.pointCount 0) { IntPtr fp nd.points; for (int j 0; j nd.pointCount; j) { float x Marshal.PtrToStructurefloat(fp); float y Marshal.PtrToStructurefloat(fp sizeof(float)); contour.Add(new Point2f(x, y)); fp 2 * sizeof(float); } } list.Add(new AidiDefect( nd.classId, nd.confidence, new Rect(nd.left, nd.top, nd.right - nd.left, nd.bottom - nd.top), contour.ToArray())); } return list; }这段里我要强调一个细节resultPtr虽然是我们在C#侧用AllocHGlobal申请的但引擎可能往这个地址写入结果也可能内部维护了一个结果缓冲区resultPtr只是返回那个缓冲区的地址。所以释放时一定要调用AIDI_FreeResult而不是只Marshal.FreeHGlobal前者是引擎自己管理内存的入口后者只是释放我们申请的那一小块外壳。如果demo里没有FreeResult说明Result内存完全由调用方申请和释放那就要仔细读初始化参数确认传入的缓冲区大小是否满足最大检测数量。每次推理完把List 返回给界面层指针相关的一切都已经被隔离在数值类型中。后续无论做日志序列化还是UI绑定操作的都是纯托管对象这是和原生内存打交道的安全边界。4.3 把缺陷结果画回图像用OpenCvSharp做调试可视化拿到结构化结果后最好的验证方式是把缺陷框、轮廓和置信度直接叠加到原图上肉眼看一眼就知道推理靠不靠谱。OpenCvSharp在C#生态里是常规选择它封装的Mat和绘图函数和OpenCV保持一致。public Mat DrawResult(Mat src, IReadOnlyListAidiDefect defects, float minConfidence 0.3f) { var overlay src.Clone(); foreach (var d in defects) { if (d.Confidence minConfidence) { continue; } Scalar color d.ClassId 0 ? Scalar.Red : Scalar.Yellow; Cv2.Rectangle(overlay, d.Rect, color, 2); Cv2.PutText( overlay, $cls:{d.ClassId} {d.Confidence:F2}, new Point(d.Rect.X, d.Rect.Y - 8), HersheyFonts.HersheySimplex, 0.6, color, 2); if (d.Contour.Length 0) { Cv2.Polylines(overlay, d.Contour, true, Scalar.LimeGreen, 1); } } return overlay; }minConfidence这个参数值得多说一句。它在demo阶段的功能是“让画面不那么吵”但上了产线之后阈值高低的决策依据不是画面好不好看而是漏检成本和误检成本哪个更高。缺陷漏掉流到下游损失可能是一整批产品缺陷误报顶多多停一次机。所以我的建议是demo阶段阈值放宽到0.3目的是看到所有可能的候选框上线前再做一次阈值扫描实验选一个在验证集上漏检率和误检率平衡的数值。类别颜色映射在demo里可以写死classId对应颜色但在正式项目里我一般会从模型配置目录里读一个labels.txt动态生成类别到颜色的映射。这样加新品种缺陷时不用改代码只要改模型和标签文件就够了。5. AIDI调用常见坑与排查5个能让推理直接翻车的运行细节5.1 DllNotFoundException和BadImageFormatException平台位数和依赖没对齐现象程序一启动就抛DllNotFoundException或者代码能编译但运行时AIDI.dll那条调用报BadImageFormatException。前者是找不到dll后者是找到了但位数或架构不匹配。原因分两类第一类运行库目录里的依赖dll没有整体复制到exe所在目录。AIDI.dll本身依赖OpenCV和onnxruntime它们必须和AIDI.dll在同一个目录或者在系统PATH里。第二类你的C#工程平台目标是AnyCPU但AIDI.dll是x64的。AnyCPU在64位系统上默认按x64跑但如果框架版本或宿主进程被强制成x86加载64位dll就会BadImageFormat。解决项目属性里把平台目标固定为x64禁止AnyCPU。部署目录里不手动精简文件把运行库目录原样输出到exe同目录用静态库工具比对文件列表。我见过有人为了“清爽”删了一堆看不懂的dll结果跑起来缺一个就崩一次。5.2 PInvokeStackImbalance或调用后直接崩调用约定和函数签名对不上现象第一次调用Init看起来正常但LoadModel或Run时函数还没返回就抛PInvokeStackImbalance或者调用后程序无征兆退出。原因DllImport声明的CallingConvention与实际dll导出符号不一致。C导出的函数没特殊声明时默认是cdecl但有些SDK在模块定义文件里用了stdcall。另一个常见问题是参数类型对不上引擎期望的是int指针或回调函数指针你传了普通int或string。解决用第2.3节的dumpbin导出表核对函数名带不带后缀带的选StdCall不带的选Cdecl。再看demo.zip里的原始C头文件逐参数翻译C#声明尤其注意IntPtr、ref、out的用法。头文件里参数带指针和引用语义的C#这边必须有对应的ref或out漏一个都会让函数读到错误地址。5.3 模型能加载但推理结果全空或坐标错位图像数据没按引擎的胃口喂现象LoadModel成功后不管传什么图返回的缺陷列表都是空的或者画出来的框压在完全错误的区域上。原因引擎对图像格式的约定比想象中严格。一是通道顺序前面提过的BGR和RGB颠倒会导致每个像素的三通道被解释错特征图全乱。二是stride非连续Mat没有按Step传入而是按Cols乘3计算图像行尾的对齐字节被当成下一行开头整张图发生行偏移。三是图像缩放模型训练时固定输入尺寸推理前需要resize如果你直接把相机原图丢进去引擎可能静默报错或直接返回空。解决先用demo自带的测试图和模型跑一遍确定引擎默认尺寸和通道顺序。再写一个图像预处理函数把Mat统一转成BGR、连续内存、预期尺寸。宁可多做一步规范也不要信任每次调用来图都正好合格。这一步能在demo阶段暴露大部分“结果为空”的问题。5.4 推理时UI假死或闪退把多线程当单线程用现象WinForms窗口点击按钮后转圈假死副线程里直接更新Label或PictureBox偶尔闪退或者把AIDI引擎的同一个实例放在多个线程里同时推理偶尔崩溃。原因推理是耗时操作放UI线程就是假死副线程更新控件违反线程封送规则多个线程同时调用同一个引擎句柄而底层dll内部不是线程安全的。解决推理调用放到Task.Run里结果返回后通过UI控件的Invoke或BeginInvoke回到UI线程再绘制。引擎实例按线程隔离每个推理线程持有自己的AIDI运行时实例或者在最外层对Detect方法加锁。前者吞吐更高后者实现简单demo阶段用锁就够。线程数再多也不要挑战一个句柄的多线程并发这个坑在正式项目里炸过太多次。5.5 本机跑得好好的换到产线机器就报授权失败机器码绑定现象开发机上推理一切正常把程序部署到工控机后初始化阶段返回未授权或License校验失败的错误码。原因AIDI的授权机制通常和机器硬件绑定读取CPU或网卡指纹生成机器码。换机器等于换了环境原来的授权文件自然失效。解决提前在目标工控机上运行demo里配套的机器码导出工具把机器码发给平台侧申请正式授权。不要等产线联调当天才想起来机器码申请和授权文件下发可能需要走流程。这也是为什么我在第2章强调拿到离线包第一天就规划部署目录而不是开发到最后才打包。把授权问题提前消化掉联调时才不会卡在环境环节。6. 从demo到可用工具一个最少图像的验证技巧与交付前的检查习惯6.1 一张坏图加一张好图的自检法把demo跑通之后第一步不要直接测相机也不要拿上百张图一起测那样出了问题根本定位不了。我常用的验证方法是“一正一负”挑一张包含明显缺陷的样本挑一张完全无缺陷的正常样本写一个最小的控制台程序依次跑同一份模型。static int SelfCheck(string modelDir, string badSample, string goodSample) { using var rt new AidiRuntime(modelDir); using var bad new Mat(badSample, ImreadModes.Color); using var good new Mat(goodSample, ImreadModes.Color); var badDefects rt.Detect(bad); var goodDefects rt.Detect(good); Console.WriteLine($坏图检出: {badDefects.Count} 个缺陷); foreach (var d in badDefects) { Console.WriteLine($ classId{d.ClassId}, conf{d.Confidence:F3}, rect{d.Rect}); } Console.WriteLine($好图检出: {goodDefects.Count} 个缺陷); return badDefects.Count 0 goodDefects.Count 0 ? 0 : 1; }这个自检脚本同时验证了三件事模型加载是否正常、内存图像输入是否按预期工作、返回结构和解析代码是否对得上。如果坏图检出为空先查图像预处理和通道顺序如果好图也检出大量框先查置信度阈值是不是设得太低。这两张图过了再接相机流进行实时测试问题定位范围会小很多。6.2 交付前把这三样装进部署目录demo阶段代码能跑通还远远不够交付给产线时要保证的是“换一台干净机器也能跑起来”。我常用的做法是维护一个打包清单包含三部分运行库目录里的全部dll、模型目录的完整内容、授权文件和机器码配置。打包用robocopy镜像整个目录而不是手动拖拽避免漏文件。robocopy D:\workspace\AIDI\runtime D:\release\app\runtime /MIR robocopy D:\workspace\AIDI\model D:\release\app\model /MIR程序启动时在日志里记录一句引擎版本、模型路径和初始化结果。上线初期用户反馈的任何问题先看日志里初始化那行能快速判断是环境问题还是业务问题。这个习惯帮我省掉了大量远程排障时间。最后说一个我的教训接手任何AIDI离线包无论demo多简单第一件事永远是跑通官方自带的那张测试图而不是直接拿自己的产品图去试。官方测试图能跑通证明运行环境、函数声明、调用约定这三层没毛病官方测试图都跑不通后面排查全是在猜。只有把基础链路锁死后续业务代码才能可靠地围绕它搭建。希望我的这些经验能帮到你。本文还有配套的精品资源点击获取

相关新闻

pstack 实战指南:用调用栈快速定位线上死锁与 CPU 飙高

pstack 实战指南:用调用栈快速定位线上死锁与 CPU 飙高

凌晨两点,线上一个服务进程 CPU 飙到 99%,客户端超时告警一片,可你连它在哪个函数里忙都看不到。这种时候,我最先掏出来的工具就是 pstack。pstack 是一条命令行工具,作用只有一个:打印某个运行中进程的所有…

2026/10/11 10:17:07 阅读更多 →
GAN图像修复实战:从掩码设计到U-Net与PatchGAN训练优化

GAN图像修复实战:从掩码设计到U-Net与PatchGAN训练优化

简介:面向毕业设计、课程设计与项目开发场景,基于Python实现生成对抗网络(GAN)的破损图片修复项目,核心包含cGAN模型、图像修复流程及SSIM/PSNR评估脚本,适合具备一定深度学习基础的读者学习图像生成与修复…

2026/10/11 10:17:07 阅读更多 →
USART串口协议(STM32标准库学习笔记)

USART串口协议(STM32标准库学习笔记)

在上一章中,我们学习了 DMA 直接存储器存取,了解了如何利用 DMA 在不占用 CPU 的情况下高效搬运数据。而数据搬运的最终目的,往往是与外部设备进行通信。在嵌入式系统中,串口(USART)是最常用、最基础的一种…

2026/10/11 10:17:06 阅读更多 →

最新新闻

关键词URL采集工具实战:从乱码链接中高效提取与去重

关键词URL采集工具实战:从乱码链接中高效提取与去重

简介:关键词URL采集工具是一套面向SEO优化、市场调研与数据挖掘从业者的自动化网址搜集方案,核心用途是依据指定关键词批量抓取搜索引擎结果页中的匹配链接,替代人工逐页翻找,降低时间成本。资源包共4个文件,以rar格式…

2026/10/11 13:56:13 阅读更多 →
rea实战:用脚本自动化浏览器重复操作,打造高效流程

rea实战:用脚本自动化浏览器重复操作,打造高效流程

首先要跟看到这个标题的朋友解释一下:我平时写自动化脚本,经常要给临时项目起个随手能打的代号,rea就是从里面蹦出来的三个字母。它的全称被我私下写成 Repeat Everything Automatically——听起来有点中二,实际上做的事情特别接地…

2026/10/11 13:56:13 阅读更多 →
从Cursor杀回命令行:AI辅助编程下的工具选型与控制权

从Cursor杀回命令行:AI辅助编程下的工具选型与控制权

最近几个月,我观察到一个挺有意思的现象:身边不少同事、群里一些老开发者,陆续把默认编辑器从Cursor切回了终端里的Vim、Neovim,或者干脆就是一套纯命令行的开发环境。不是他们跟不上时代,恰恰相反——他们在AI辅助编程…

2026/10/11 13:56:13 阅读更多 →
【程序源代码】校园跑腿服务系统

【程序源代码】校园跑腿服务系统

摘要:校园跑腿服务系统是一套面向高校场景的前后端分离校园服务系统,由微信小程序端、Koa2 服务端、Vue 网页管理后台三部分组成,覆盖跑腿代取、打印服务、校园代理、订单交易、微信支付、用户角色管理等校园生活服务业务。学生可通过小程序发…

2026/10/11 13:56:13 阅读更多 →
UML核心视图实战:图书管理系统建模从用例图到构件图

UML核心视图实战:图书管理系统建模从用例图到构件图

简介:这份PPT面向软件工程、计算机专业学生及UML初学者,围绕统一建模语言UML的核心视图,以ABC高校图书管理系统为完整案例,讲解从需求分析到静态建模的全过程。内容涵盖用例视图的参与者、用例与关系识别,读者借还书、…

2026/10/11 13:56:13 阅读更多 →
某东h5st逆向实战:webpack签名参数定位与Python复现

某东h5st逆向实战:webpack签名参数定位与Python复现

简介:这份资源面向具备一定前端基础、希望深入理解移动端加密参数生成机制的爬虫学习者与安全测试人员,围绕某东平台webpack打包方式下的h5st逆向分析,提供一套可运行的完整代码示例。压缩包共2个文件,包含1个Python脚本与1个Java…

2026/10/11 13:55:12 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →