机缘

2014年,我一头扎进C#上位机开发的赛道,从此便在工厂产线与工控机之间扎了根。调试PLC、啃透通信协议、对接MES系统,这一干,就是整整十年。

十年里,我踩过工业开发里几乎所有的坑:Modbus通信莫名掉线、串口数据频发丢包、多线程操作导致界面直接卡死、好不容易训好的YOLO模型,部署到工控机上却完全跑不动……每次遇到难题去网上找解决方案,却总逃不开几个困境:要么内容太浅只讲皮毛,要么早已过时适配不了新环境,更无奈的是,满屏都是Python教程,唯独找不到C#工业场景的实战内容。

2024年底,我做了一个决定:把这十年攒下的一线实战经验,一字一句写下来。没有什么宏大的初衷,只希望后来踏入这个领域的同行,在搜解决方案的时候,能看到一篇靠谱的内容,少走一点我走过的弯路。

我的第一篇文章,写的是C#消息队列与多线程编程。那天没有什么特别的仪式感,只是觉得这些踩坑换来的知识,该被好好记下来。没想到笔尖一动,就再也停不下来了。

收获

从提笔到今天,已经过去了512天。
这512天里,我更新了5800+篇原创文章,收获了525万+次阅读,和15119位粉丝的关注。

但说实话,这些冰冷的数字,从来都不是我最大的收获。
真正让我觉得所有付出都值得的,是评论区里那些素未谋面的同行留下的话:
“威哥,这个问题我卡了三天,你一篇文章就给我讲透了”
“终于找到一个专门用C#做YOLO部署的博主,全网几乎只有你在深耕这个方向”
“看了你写的Modbus通信那篇,我的项目直接顺利过了验收”

工业开发是个极其垂直的领域,受众不算多,但每一个点进我文章的人,都是真正在产线上做项目、在一线解决问题的人。能实实在在帮到他们,比任何数据都更让我有成就感。
还有几百位兄弟订阅了我的专栏,这份隔着屏幕的信任,沉甸甸地落在我肩上,一刻不敢辜负。

日常

如今,创作早已成了我生活里刻进骨子里的习惯。
每天早上8点准时发布新文章,晚上10点把当天的内容整理收录进专栏,这个节奏雷打不动,从未间断。

很多人问我,5800篇文章,哪里来的这么多灵感?
其实哪有什么源源不断的灵感,不过是把创作做成了标准化的流水线:选题 → 写代码 → 跑通验证 → 截图留存 → 撰写文章 → 定时发布。一套流程走下来,效率自然就提上来了。

白天我照常上班做项目,晚上回家就把当天在项目里遇到的问题、踩过的坑、验证过的解决方案整理成文,第二天早上准时发出去。
对我来说,创作和工作从来都不是割裂的:创作是把工作里的实战经验沉淀成可复用的内容,而一线的项目工作,又为我的创作提供了源源不断的真实素材。

成就

有人问我,写了这么多文章,最满意的一段代码是什么?
不是什么复杂的框架,也不是什么炫技的写法,而是这段用C#调用OnnxRuntime部署YOLO模型,实现工业缺陷检测的核心推理代码:

using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using OpenCvSharp;

public class YoloDetector : IDisposable
{
    private readonly InferenceSession _session;
    private readonly int _inputWidth;
    private readonly int _inputHeight;

    public YoloDetector(string modelPath, int inputWidth = 640, int inputHeight = 640)
    {
        var options = new SessionOptions();
        options.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_WARNING;
        options.AppendExecutionProvider_CPU(); // 适配工控机无独立GPU的通用场景
        _session = new InferenceSession(modelPath, options);
        _inputWidth = inputWidth;
        _inputHeight = inputHeight;
    }

    public DetectionResult[] Detect(string imagePath, float confThreshold = 0.5f, float iouThreshold = 0.45f)
    {
        using var src = Cv2.ImRead(imagePath);
        using var resized = new Mat();
        Cv2.Resize(src, resized, new OpenCvSharp.Size(_inputWidth, _inputHeight));

        // BGR转RGB,归一化至0~1区间,适配YOLO模型输入要求
        var inputTensor = new DenseTensor<float>(new[] { 1, 3, _inputHeight, _inputWidth });
        var pixels = resized.ToBytes();
        for (int i = 0; i < pixels.Length; i += 3)
        {
            int idx = i / 3;
            int row = idx / _inputWidth;
            int col = idx % _inputWidth;
            inputTensor[0, 0, row, col] = pixels[i + 2] / 255f; // R通道
            inputTensor[0, 1, row, col] = pixels[i + 1] / 255f; // G通道
            inputTensor[0, 2, row, col] = pixels[i] / 255f;     // B通道
        }

        var input = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("images", inputTensor) };
        using var results = _session.Run(input);
        var output = results.First().AsTensor<float>();

        return ParseDetections(output, confThreshold, iouThreshold, src.Width, src.Height);
    }

    private DetectionResult[] ParseDetections(Tensor<float> output, float confThreshold, float iouThreshold, int srcWidth, int srcHeight)
    {
        var results = new List<DetectionResult>();
        int stride = output.Dimensions[1]; // 适配YOLO输出维度,兼容不同版本模型
        // 此处为NMS非极大值抑制后处理核心逻辑,可根据模型版本适配调整
        // 完整实现可参考专栏对应文章
        return results.ToArray();
    }

    public void Dispose() => _session?.Dispose();
}

/// <summary>
/// 检测结果实体
/// </summary>
/// <param name="X">检测框左上角X坐标</param>
/// <param name="Y">检测框左上角Y坐标</param>
/// <param name="Width">检测框宽度</param>
/// <param name="Height">检测框高度</param>
/// <param name="Confidence">置信度</param>
/// <param name="ClassId">分类ID</param>
/// <param name="Label">分类标签</param>
public record DetectionResult(float X, float Y, float Width, float Height, float Confidence, int ClassId, string Label);

这段代码,后来被我用在了一个电池表面缺陷检测的商业项目里,最终实现了98.6%的检测精度,单帧推理耗时仅42ms,直接稳定部署在产线的工控机上,完美打通了从Python模型训练到C#工业落地的全流程。
这也是我一直坚持的:写的每一行代码,每一篇文章,都要能真正落地到产线,解决实际问题。

憧憬

关于未来,我只想踏踏实实干好两件事:
第一件,继续深耕C#上位机与工业视觉赛道,把这两个方向的专栏做深、做透,用更扎实的实战内容,帮助更多工业自动化领域的工程师少踩坑、多落地;
第二件,尝试从文字走向视频,把核心的技术操作、项目落地流程做成视频教程,毕竟很多实操细节,看一遍演示,比读十遍文字来得更直观。

写了512天,我最大的感悟就是:在垂直的领域里,做难而正确的事,坚持长期输出,时间一定会给你最公允的回报。

威哥说编程,始终只想做一件事:帮你少踩坑、多赚钱。
下一个512天,我们继续同行。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐