Home avatar

东东东尼君

东尼君的世界

机器视觉算法与应用 第2版 (Carsten Steger)

在工业自动化设备开发过程中,机器视觉往往是决定设备精度和稳定性的关键环节。很多时候,我们面对一个视觉检测需求,第一反应可能是:“有没有一个现成的算子可以解决?”。边缘检测、模板匹配、Blob分析……这些算法在 Halcon、OpenCV 等视觉库中已经被封装得非常方便。但随着项目复杂度提升,真正困难的问题逐渐浮现:

  • 为什么这个场景应该选择这种算法?
  • 为什么换一种光源,算法效果会完全不同?
  • 为什么同样的模板匹配,在不同工位、不同角度、不同产品公差下稳定性差异巨大?

这些问题本质上不是“会不会调用算子”,而是是否建立了完整的机器视觉算法体系。

《机器视觉算法与应用(第2版)》由 Carsten Steger(MVTec 联合创始人) 等人编写,是工业机器视觉领域非常经典的一本参考书。它没有简单罗列各种视觉算法,而是从图像形成、特征提取、定位、测量、识别等角度,系统介绍机器视觉中常见问题背后的数学原理和工程方法,这篇文章记录阅读过程中的一些理解和总结,希望通过这个过程,把零散的视觉知识,逐步整理成一套可以用于实际设备开发的“认知框架”。。

机电一体化实用手册 第2版 (三浦宏文)

作为此前专注于软件/算法开发、并逐步向工业设备与机电一体化方向延伸的工程师,这本书给我的冲击更多来自“视角切换”——从纯软件系统的抽象世界,进入到机械、电气与控制交织的真实物理系统之中。过去在写代码时,我们习惯处理的是确定性的输入输出:接口、协议、状态机、数据流,一切都可以在逻辑层面闭环。但在机电一体化系统中,变量开始变得“有重量”:惯性、摩擦、延迟、抖动、误差累积,这些因素不再是边界条件,而是系统设计的一部分。软件不再只是“控制逻辑”,而是与硬件共同构成一个持续运行的闭环系统。

这本书的价值,并不只是讲解机械结构或电气控制原理,而是在不断强调一个核心思想:真正的机电一体化,不是“机械 + 电气 + 软件”的简单叠加,而是三者在设计阶段就必须协同优化的系统工程。

对我而言,这种思维方式的转变尤为重要。因为在实际设备开发中,很多问题并不是“代码 bug”,而是系统层面的设计耦合问题:

  • 为什么视觉定位会漂移?
  • 为什么PLC信号延迟会导致节拍不稳定?
  • 为什么同一个算法在实验室稳定,在产线上却波动明显?

这些问题的答案,往往都不在软件本身,而在系统整体结构里。

如果你也来自软件领域,正在向工业自动化、设备开发、机器视觉或机器人方向过渡,希望这篇文章能帮你少走一些“只懂代码、不懂系统”的弯路。

C#高效编程 改进C#代码的50个行之有效的办法 第2版 (Bill Wagner)

在软件开发过程中,写出“能运行”的代码并不难,真正困难的是写出一段容易理解、容易维护、容易扩展,并且能够长期稳定运行的代码。随着项目规模不断扩大,代码往往会经历这样的变化。

最初,一个类可能只有几十行。逻辑简单,修改起来非常直接;但随着需求不断增加,功能不断堆叠,代码开始出现越来越多的问题:

  • 一个方法越来越长,承担了太多职责;
  • 类之间的依赖越来越复杂,修改地方可能影响多个模块;
  • 重复代码不断出现,导致维护成本增加;
  • 异常处理、资源释放、性能优化等细节容易被忽略;
  • 新成员接手代码时,需要花费大量时间理解历史逻辑。

这些问题并不是因为开发者能力不足,而是因为代码质量需要持续演进。C# 作为一门成熟的面向对象语言,提供了大量语言特性帮助我们编写更优雅、更安全的代码,例如泛型、委托、Lambda、LINQ、异步编程、特性(Attribute)、模式匹配等。但如果只是掌握语法,而没有形成良好的编程习惯,很容易写出“看起来能工作,但长期维护困难”的代码。

《C# 高效编程:改进 C# 代码的 50 个有效办法 第2版》这本书并不是单纯讲解 C# 语法,而是从工程实践角度,总结了大量能够改善代码质量的技巧和原则。

这些建议覆盖了多个方面:

  • 如何正确设计类型和接口;
  • 如何减少代码耦合;
  • 如何利用 C# 特性提升表达能力;
  • 如何处理异常、资源和状态;
  • 如何编写更高性能、更可靠的程序。

接下来,我会结合书中的实践建议,并加入自己在项目开发中的理解,对这些技巧进行整理,希望能够帮助自己,也帮助更多 C# 开发者写出更加健壮、优雅的代码。

Shadowsocks源码剖析

前言

很多人第一次接触 Shadowsocks,只把它当作一个代理工具。但是从源码角度看,Shadowsocks 是一个非常适合学习网络编程的项目。它代码量不大,却包含了现代网络服务端开发中的很多核心思想:

  • Socks5 协议解析
  • Socket 编程
  • 非阻塞 IO
  • Reactor 事件模型
  • epoll/kqueue/select
  • 状态机设计
  • TCP Relay 转发
  • UDP Relay
  • 加密通信

阅读 Shadowsocks 源码,可以帮助我们理解一个代理程序从建立连接,到数据转发,再到连接关闭的完整过程。本文以 Python 版 Shadowsocks 为例,分析它内部的设计。

Node.js 源码剖析:非阻塞世界的引擎密码

Node.js 的诞生,让 JavaScript 从浏览器的专属语言,跃升为构建高性能服务器的利器。凭借事件驱动的架构和非阻塞 I/O 特性,Node.js 成为现代网络应用开发中的重要基石。然而,当你写下 http.createServer时,是否好奇过这些简单的 API 背后究竟发生了什么?

本篇文章将带你深入 Node.js 的源码世界,揭开其核心模块、事件循环、异步模型和底层实现的神秘面纱。从 libuv 的非阻塞 I/O,到 V8 引擎对 JavaScript 的极速解析,我们将从代码的视角探索 Node.js 是如何在性能与灵活性之间找到绝佳平衡的。

无论你是想提升对 Node.js 的理解,还是希望从源码中汲取工程设计的智慧,这都将是一次充满收获的技术旅程。准备好了吗?让我们从入口文件开始,走进 Node.js 的源码迷宫!

C#中的nameof运算符

在日常 C# 开发中,我们经常需要获取变量名、属性名、方法名或类型名的字符串形式,比如:

  • 抛出参数异常时提示参数名
  • 日志记录字段名称
  • 数据绑定、反射、序列化
  • MVVM / ASP.NET 中的属性通知

在 C# 6.0 之前,这些字符串往往是硬编码的魔法字符串(Magic String),维护成本极高。而 nameof 的出现,几乎是一次“工程级”的体验升级。

Downloader源码剖析

在开发日常工作中,文件下载看似是一个再普通不过的功能,但当下载规模扩大、速度需要优化、断点续传需要保证、并发控制需要精确、甚至要处理上百 GB 的大文件时,“下载器”就迅速从普通工具变成了一个考验系统设计能力的实战项目。Downloader 正是这样一个值得深入研究的优秀示例。它不仅实现了多线程下载、断点续传、分块合并、速度统计等核心功能,还在架构设计、并发模型、代码组织方式上体现了 C# 在现代并发场景下的最佳实践。对于正在学习 C# 并发编程、网络 IO、上位机开发的工程师来说,它几乎是一个“天然的进阶教材”。

编写可读代码的艺术 (Dustin Boswell & Trevor Foucher)

当我们看到写得很漂亮的代码时,会很受启发。好代码会告很明确告诉你它在做什么。使用它会很有趣,并且会鼓励你把自己的代码写得更好。该书旨在帮助你把代码写得更好。该书的关键思想是代码应该写得容易理解。确切地说,使别人用最短的时间理解你的代码。每一章都会深入编程的某个方面来讨论如何使代码更容易理解。 该书分为四个部分:

  • 表面层次上的改进:命名、注释以及审美——可以用于代码库每一行的小提示。
  • 简化循环和逻辑:在程序中定义循环、逻辑和变量,从而使得代码更容易理解。
  • 重新组织你的代码:在更高层次上组织大的代码块以及在功能层次上解决问题的方法。
  • 精选话题:把“易于理解”的思想应用于测试以及大数据结构代码的例子。

launch-editor源码剖析:快速打开编辑器的实现原理

在阅读 Vite 源码的过程中,我注意到一个有趣的依赖 —— launch-editor。起初只是随手点开,结果却发现它正是支撑起「浏览器报错信息 → 一键跳转到编辑器」这一开发体验的核心工具。其实,我们在使用 Vite、Vue CLI 等工具的时候,不止一次用过这个功能:报错时点击链接,代码编辑器立刻打开到对应的文件和行号。背后的关键实现,正是 launch-editor。

ES6模块教程

在前端开发的进化历程中,模块化 一直是一个核心问题。早期我们用全局变量、命名空间、立即执行函数(IIFE)来组织代码,但都存在依赖管理复杂、命名冲突等问题。 直到 ES6(ECMAScript 2015) 正式引入了 模块化语法,才为 JavaScript 带来了原生的模块方案。

80. Remove Duplicates From Sorted Array II

Given an integer array nums sorted in non-decreasing order, remove some duplicates in-place such that each unique element appears at most twice. The relative order of the elements should be kept the same.

Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.

Return k after placing the final result in the first k slots of nums.

Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.

如何解决 Node.js 中的 EMFILE 错误

在日常 Node.js 开发中,你有没有遇到过这样一个错误:

Error: EMFILE: too many open files

该错误通常出现在:批量文件操作、递归复制、日志处理等场景中。为什么会出现该错误?其实是因为在操作系统中每个进程最多可以同时打开一定数量的文件或 Socket, 而当打开的文件或 Socket 超过了这个限制时,就会出现“打开文件过多”的错误,导致程序突然崩溃。这种“打开文件过多”的问题看 似简单,但如果不加处理,尤其是在批量文件处理场景下,会让我们的 Node.js 程序非常脆弱。

189. Rotate Array

Given an integer array nums, rotate the array to the right by k steps, where k is non-negative.

Example 1:

Input: nums = [1,2,3,4,5,6,7], k = 3

Output: [5,6,7,1,2,3,4]

Explanation:

rotate 1 steps to the right: [7,1,2,3,4,5,6]

rotate 2 steps to the right: [6,7,1,2,3,4,5]

rotate 3 steps to the right: [5,6,7,1,2,3,4]

如何查看PowerShell的版本

在使用 PowerShell 进行脚本开发或系统运维时,知道当前环境的 PowerShell 版本是非常有必要的。不同的版本在功能和兼容性上存在差异,有些模块或命令在旧版本中可能无法使用,甚至语法支持也会有变化。

本文将介绍多种查看 PowerShell 版本的方法,无论你是在使用 Windows PowerShell 5.1 还是跨平台的 PowerShell 7,都能轻松查到当前版本信息。

json-server源码剖析:快速构建REST API背后的原理

在前端开发中,构建一套完整的后端接口往往耗时费力,而 json-server正是为了解决这一痛点而生。只需一个 JSON 文件,它就能快速生成一个 REST API 服务,被广泛用于前端开发、原型验证、接口测试等场景。本文将深入剖析 json-server的源码,一起理解它是如何工作的,并从中学习一些开发技巧。

用PowerShell玩转文件处理

PowerShell 是一个功能强大的自动化脚本平台,不仅可以管理系统和服务,还可以轻松高效地处理各种文件操作。无论你是系统管理员、开发者,还是数据分析师,掌握 PowerShell 的文件处理能力都能让你的工作事半功倍。本文将带你系统性地了解如何用 PowerShell 玩转文件处理,从基础操作到进阶技巧,让你轻松驾驭文件的读取、修改、管理与批处理任务。

csv2 源码剖析:轻量级 CSV 处理的高效之道

纸上得来终觉浅,绝知此事要躬行。——陆游《冬夜读书示子聿》

csv2是一个轻量级 C++ 库,用于将 CSV 文件解析为 C++ 中的 STL 容器。该库的主要功能是高效地处理 CSV 数据,简化了处理 CSV 文件的代码编写过程。以下是它的主要特性:

  1. 简单易用:通过使用 STL 容器(如 std::vector 和 std::tuple),使得开发者能够轻松将 CSV 文件的内容转换为标准 C++ 数据结构。
  2. 依赖少:该库只有 C++17 标准库的依赖,因此不需要额外的第三方库。
  3. 高效解析:该库采用高效的解析机制,支持处理大型 CSV 文件。
  4. 轻量级:代码库很小,适用于嵌入式或对依赖库要求较高的项目。