3D视觉入门:如何用线结构光测量快速获取物体轮廓(附Python代码示例)

手把手教你用线结构光测量实现3D物体轮廓扫描(附Python代码示例) 本文详细介绍了如何使用线结构光测量技术实现3D物体轮廓扫描,包括硬件选型、系统标定、光条中心提取和三维重建等关键环节,并提供了完整的Python代码示例。通过三角测量原理,开发者可以快速搭建高效、精确的非接触式测量系统,适用于工业检测、逆向工程等领域。 阅读详情

3D视觉实战:从零构建线结构光轮廓测量系统

最近在做一个工业质检的小项目,需要快速获取一批不规则金属零件的表面轮廓。传统的接触式测量效率太低,而市面上的3D扫描仪要么太贵,要么精度不够。折腾了一圈,最后把目光投向了线结构光测量——这个听起来有点学术,但实际搭建起来却相当亲民的技术。它就像用一把“光刀”去切割物体表面,然后用相机拍下这道光的变形,就能反推出物体的三维形状。整个过程不需要复杂的设备,一台普通的工业相机、一个线激光器,再加上我们熟悉的Python和OpenCV,就能搭建一套属于自己的3D测量系统。这篇文章,我就把自己从原理摸索到代码落地的完整过程,以及中间踩过的那些坑,毫无保留地分享给同样想快速上手3D视觉的朋友们。

1. 线结构光:原理与核心思想

很多人第一次接触线结构光,容易被那些“光平面”、“世界坐标系”、“相机标定”之类的术语吓到。其实它的核心思想非常直观。想象一下,在一个黑暗的房间里,你手持一支激光笔,如果激光笔发出的是一个光点,你只能知道墙上某一个点的位置。但如果你在激光笔前加一个特殊的透镜(柱面镜),它就能把光点“拉”成一条明亮的细线,就像一把光做的尺子。

当你把这把“光尺”投射到一个平整的墙面上,相机看到的就是一条笔直的亮线。但如果你把一个小物件(比如一个鸡蛋)放在墙前,光尺照在鸡蛋弯曲的表面上,相机看到的就不再是直线,而是一条随着鸡蛋轮廓弯曲的曲线。这条曲线的每一个像素点的偏移量,都编码了鸡蛋表面在该位置的高度信息。这就是线结构光测量最朴素也最核心的原理:通过观测已知形态的结构光图案在物体表面的变形,来解算物体的三维形貌。

与逐点扫描的“点结构光”相比,线结构光一次就能获取物体一个剖面上的数百个点,效率的提升是指数级的。这也是它被称为“光切法”的原因——就像用光做切片,一次切下物体的一整个剖面。

整个测量流程可以抽象为以下几个关键步骤:

  1. 系统搭建与标定:固定相机和线激光器的相对位置,并精确计算出相机成像的数学模型(内参)以及光平面在空间中的方程(外参)。
  2. 图像采集与预处理:在黑暗或可控光照环境下,采集投射了激光线的物体图像,并通过图像处理技术提取出那条明亮的激光条纹中心线。
  3. 条纹中心提取:这是精度保障的关键,需要从图像中亚像素级地定位激光条纹的中心位置。
  4. 三维坐标重建:将图像上提取的每一个中心点像素坐标,结合相机标定参数和光平面方程,通过三角测量原理,计算其在真实三维空间中的坐标。
  5. 点云处理与轮廓生成:将计算出的三维点集(点云)进行后续处理,如滤波、拼接(如果是多线扫描),最终生成可用的物体轮廓或三维模型。

这个过程里,标定的精度直接决定了整个系统的测量精度,而条纹中心提取的算法则决定了数据的细节丰富程度。下面,我们就深入每个环节,看看具体怎么操作。

2. 硬件搭建与系统标定:给系统装上“尺子”

在开始写代码之前,你得先把硬件架子搭起来。这套系统最简配置只需要三样东西:

  • 面阵CCD/CMOS相机:建议选择全局快门相机,避免拍摄移动物体时产生拖影。分辨率根据测量范围和精度要求来定,通常200万像素以上即可开始实验。
  • 线激光器:选择功率合适(Class 2或以下更安全)、线宽均匀、发散角小的型号。波长常见有红光(650nm)和蓝光(450nm),在暗环境下红光更醒目,但某些材料表面蓝光反射特性更好。
  • 计算机:用于运行处理程序和存储数据。

安装时,让相机和激光器大致对准待测区域,形成一个经典的三角测量布局。激光器投射的光平面要与相机的成像平面成一定角度(通常20°-45°),这个角度越大,对高度变化的灵敏度越高,但视野可能越小,且容易产生遮挡。

硬件摆好只是第一步,接下来的系统标定才是重头戏,它决定了你的系统“看”得准不准。标定分为两部分:相机标定和光平面标定。

2.1 相机标定:确定相机的“内参”

相机标定的目的是获取相机的内部参数和畸变系数。你可以把它理解为给相机做一次“体检”,弄清楚它的成像特性。我们使用经典的张正友标定法,借助OpenCV可以轻松完成。

你需要准备一个高精度的棋盘格标定板(比如10x7的内角点),从不同角度、不同位置拍摄十几到二十张标定板的图片。确保标定板在每张图中都清晰、完整,且姿态多样。

import cv2
import numpy as np
import glob

# 准备标定板参数 (以10x7内角点为例)
pattern_size = (9, 6) # 内角点数量 (宽度-1, 高度-1)
square_size = 25.0 # 每个方格的实际物理尺寸,单位毫米

# 存储对象点和图像点的容器
obj_points = [] # 3D点 (世界坐标系)
img_points = [] # 2D点 (图像坐标系)

# 生成标定板角点的世界坐标 (Z=0)
objp = np.zeros((pattern_size[0]*pattern_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2)
objp *= square_size

# 读取所有标定图像
images = glob.glob('./calibration_images/*.jpg')

for fname in images:
    img = cv2.imread(fname)
3D视觉-结构光测量-线结构光测量 线结构光测量中,由激光器射出的激光光束透过柱面透镜扩束,再经过准直,产生一束片状光。这片光束像刀刃一样横切在待测物体表面,因此线结构光法又被成为光切法。线结构光测量常采用二维面阵CCD作为接受器件,因此只要通过增加垂直于面阵探测器的第三维度方向,就可以实现对三维物体的测量。 阅读详情

相关推荐

3D视觉入门:激光三角测量法如何实现高精度工业检测(附Python代码示例)

本文深入浅出地介绍了激光三角测量法在工业3D视觉检测中的应用。通过解析其核心几何原理,详细阐述了从硬件选型、系统标定到算法处理的完整流程,并提供了实用的Python代码示例,帮助读者快速掌握这一高精度、非接触式的测量技术,实现物体尺寸与表面缺陷的精准检测。

php55的博客 478

手把手教你用OpenCV和PnP算法搞定单目视觉测距(附完整Python代码)

本文详细介绍了如何使用OpenCV和PnP算法实现单目视觉测距,从相机标定到目标检测再到距离测量的完整流程。通过Python代码示例,帮助读者掌握单目测距的核心技术,特别适合计算机视觉初学者和电子设计竞赛参赛者。文章重点讲解了PnP算法在目标物测量中的应用,并提供了误差优化策略。

weixin_28745309的博客 915

OpenCV实战:基于参照物的物体尺寸测量技术详解

计算机视觉是人工智能领域的关键技术,它使计算机能够从图像或视频中提取信息并理解其内容。其核心原理在于通过图像处理算法识别和测量视觉特征。这项技术的核心价值在于将物理世界的尺寸信息数字化,从而在自动化领域实现非接触式、高效率的测量。在工业质检、仓储物流、电商商品识别等应用场景中,精确测量物体尺寸是常见需求。本文聚焦于基于OpenCV的物体尺寸测量实战,深入剖析了利用参照物比例法,通过透视校正和轮廓检测,将像素距离转换为真实世界尺寸的完整流程。文中详细介绍了如何应对透视畸变、选择参照物等关键挑战,并提供了从环境

weixin_33724659的博客 333

Python结合D435i深度相机实现物体尺寸测量的实战指南

本文提供了一份使用Python结合Intel RealSense D435i深度相机实现物体尺寸测量的实战指南。详细介绍了从环境搭建、核心概念(像素与相机坐标系转换)到完整代码实现的全过程,并分享了交互式点选与自动边缘检测两种测量方法,帮助开发者快速构建高精度的非接触式测量系统。

python9snake的博客 505

不止于测距:用Orbbec Gemini和Python OpenNI玩转3D视觉,从物体体积测量到简易SLAM初探

本文介绍了如何利用Orbbec Gemini RGB-D相机和Python OpenNI进行3D视觉应用开发,从物体体积测量到简易SLAM实现。通过详细的代码示例和实战项目,帮助开发者掌握深度相机在物流仓储、人员检测和机器人导航等领域的核心应用,提升3D视觉开发能力。

weixin_26873711的博客 431

D视觉(3D Vision)原理与代码实战案例讲解

3D视觉(3D Vision)原理与代码实战案例讲解 作者:禅与计算机程序设计艺术 / Zen and the Art of Computer Programming 关键词:三维视觉,深度估计,点云处理,图像拼接,空间定位 1.背景介绍

AI天才研究院 231

OpenCV-Python实战(10)——详解 OpenCV 轮廓检测

在计算机视觉领域,轮廓通常指图像中对象边界的一系列点。因此,轮廓通常描述了对象边界的关键信息,包含了有关对象形状的主要信息,该信息可用于形状分析与对象检测和识别。在本文中,将首次通过简单示例了解轮廓的基本概念,然后通过实际示例来了解如何检测和压缩轮廓,最后利用介绍如何利用图像矩描述检测到的轮廓属性。

盼小辉丶的博客 3万+

OpenCV工业视觉尺寸测量:从轮廓检测到亚像素精度实战

计算机视觉中的物体尺寸测量技术,其核心原理是通过建立图像像素与实际物理尺寸之间的比例关系来实现非接触式测量。该技术基于参考对象,通过图像处理算法计算像素比例(PPM),从而将像素尺寸转换为毫米级精度。在工业质检、自动化分拣等场景中,这项技术能显著提升效率与准确性。实现高精度测量的关键在于稳定的轮廓检测与几何拟合,涉及图像预处理、边缘增强和形态学操作等步骤。针对工业环境中的光照变化、镜头畸变等挑战,需结合相机标定、亚像素边缘检测等工程实践进行优化。本文以OpenCV和Python为基础,详细解析了从轮廓检测到

weixin_29048775的博客 349

OpenCV双目视觉测量物体尺寸:从标定到立体匹配实战教程

计算机视觉中,从二维图像恢复三维信息是核心课题之一。双目视觉通过模拟人眼视差,利用两台相机获取同一场景的左右视图,计算对应点视差,进而得出物体深度。这一原理被广泛应用于机器人导航、工业检测和物体尺寸测量。OpenCV作为开源视觉库,提供了从相机标定、极线校正到立体匹配的完整工具链,使得基于双目视觉的尺寸测量系统能够以极低成本实现。本文以两个USB摄像头为硬件,深入讲解双目标定、SGBM立体匹配以及像素到毫米的换算方法,并分享标定精度、匹配参数和光照等常见坑位的解决方案,帮助读者构建一套可输出的物体尺寸测量方

weixin_34007886的博客 398

Python+OpenCV双目视觉测量物体尺寸:原理、标定与SGBM视差实现

双目视觉(Stereo Vision)是计算机视觉中获取三维信息的基础手段,其核心价值在于通过左右相机成像的视差(Disparity)恢复深度,进而计算物体的实际物理尺寸。相比单目深度估计只能给出相对深度,双目系统利用固定基线作为物理尺子,天然具备绝对尺度,因此在工业测量、机器人导航、无人驾驶等领域被广泛采用。一个典型技术链路包含棋盘格标定、立体校正、SGBM立体匹配与三维点云重投影,其中SGBM(Semi-Global Block Matching)作为高效匹配算法,其参数设置和质量对测量误差影响显著。工

weixin_33851604的博客 350

3D视觉代码

Yi Ma , Stefano Soatto. An Invitation to 3-D Vision , From Images to Geometric Models的代码

GNSS接收机性能测试全攻略:从实验室到真实场景

本文系统介绍了GNSS接收机从实验室到真实场景的完整性能测试流程。首先通过GNSS模拟器进行射频传导测试,评估接收机的基础性能;其次进行天线OTA测试,考察整机系统表现;最后通过精心设计的外场路测,在复杂环境中验证其实际定位精度与可靠性。文章强调,只有结合可控的实验室验证与多变的外场挑战,才能对接收机性能做出全面、真实的评价。

weixin_28365523的博客 500

将机器人urdf模型转换为Mujoco环境下的mjcf模型

在使用gym环境进行人形模型站立训练的过程中,我想要将之前ros环境下的机器人urdf模型导入到mujoco环境下,这时候就需要将urdf模型转换为mujoco专用的mjcf模型。-AzureLoong.urdf是机器人模型(我这里使用青龙的模型);--custom_robot.xml是转换完成之后的机器人模型的名字和格式;包要求 Python 版本必须是 3.11 或更高),保证自己的其他训练环境和依赖不被干扰。首先将meshes文件迁移到需要输出的目录下,然后再运行转换命令。最后就可以成功输出了。

weixin_44334573的博客 3742

Jetson Nano摄像头选型与配置全攻略:CSI与USB接口实战指南

在嵌入式视觉与边缘计算项目中,摄像头作为核心传感器,其选型与配置直接影响系统性能。CSI(Camera Serial Interface)和USB(Universal Serial Bus)是两种主流接口,前者通过MIPI CSI-2协议直接与SoC通信,具备低延迟、高带宽特性,适合实时性要求高的应用;后者基于通用串行总线标准,即插即用,通用性强。在NVIDIA Jetson Nano平台上,合理选择摄像头接口并优化驱动配置,能充分发挥其GPU加速优势,提升图像处理流水线效率。本文聚焦Jetson Nano

weixin_29190651的博客 319

地表最强之Android微信语音/腾讯会议通话录音

地表最强之Android微信语音/腾讯会议通话录音

cczhengv 6086

基于江协科技STM32创建HAL库工程模板

基于江协科技STM32入门教程创建的HAL库工程模板

2401_82728381的博客 1124

01-诊断开发流程概述

传送门 ==>> AutoSAR入门和实战系列总目录。

1781

Explorer.exe系统错误,电脑重启后刚开始一段时间正常,过一会桌面任务栏就卡死,可以打开任务管理器

联想E14Win10专业版。

本博客,博文仅代表个人操作经验,不能完全解决你的问题,仅供参考,佛系回复。 8030

古月学院《如何在Gazebo中实现阿克曼转向车的仿真》课程资料在ROS Noetic版本中运行时的常见错误及解决方法

   最近想在Gazebo中开发一些仿真内容,于是购买了古月学院的《如何在Gazebo中实现阿克曼转向车的仿真》课程,但是由于ROS 版本的更新,拿到手的课程资料不能直接在ROS Noetic版本中运行,经过我这几天的探索,对遇到的错误及解决方法进行了整理,方便后面购买课程的小伙伴更快的成功运行程序    在文章正式开始之前,先放一下我之前为了寻找该资料报错的原因,而写的两篇与该课程相关的文章链接,感兴趣的可以自行阅读    以阿克曼转向车为例对URDF和XACRO文件进行解读(点击可跳转)    将x

慕羽★的博客 5971

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

上一篇: STM32CubeMX回调函数详解:从NVIC配置到多中断处理实战
下一篇: Keil5逻辑分析仪实战:3分钟搞定STM32引脚波形调试(附常见报错解决方案)
web99
博客等级 码龄18年 88粉丝 1303原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值