新闻详情

新闻详情

首页 / 资讯中心 / 详情

指静脉图像预处理全流程:边界去除、静脉提取与去毛刺实战

发布时间:2026/10/2 18:26:20来源:尧图网络
指静脉图像预处理全流程:边界去除、静脉提取与去毛刺实战
简介面向图像处理与生物识别初学者的MATLAB源码包以手指静脉识别为应用场景集中解决图像边界去除、静脉提取、毛刺消除等预处理难题。包内共1个m文件体积仅2KB是一份可直接运行的核心脚本适合快速理解算法逻辑与参数设置。目前已有444人学习下载适合正在开展生物识别实验或课程设计的学生参考。脚本完整覆盖从图像预处理到静脉结构增强的关键环节包括灰度化、二值化、形态学操作、四方向谷形搜索以及斑点噪声与毛刺的清除可帮助读者对照文字描述掌握手指静脉提取的完整流程并为后续识别算法开发提供可复用的基础实现。得益于精简的单文件结构读者可逐行调试便于结合自身数据调整阈值与滤波参数是入门图像处理与静脉识别的高性价比资源。1. fingerwein2 图像预处理边界去除、静脉提取、去毛刺是一条流水线指静脉图像处理的痛点从来不是算法不够高级而是预处理没做干净。fingerwein2 这个命名常见于指静脉图像数据集或实验脚本中拿到手后的第一件事就是跑通“图像边界去除 → 静脉提取 → 去除毛刺”这条流水线。这三个步骤环环相扣边界切不干净后面静脉提取的阈值统计就会被背景污染静脉提取出来毛刺不去后续做特征匹配时端点数和分叉点数全是假的。这篇文章按真实落地顺序拆开讲每步给出可直接运行的 MATLAB 代码和参数顺手补一套 OpenCV 复刻要点适合正在做指静脉识别毕设、MATLAB 图像处理大作业或者 OpenCV 图像处理项目的读者。先说反直觉结论毛刺能不能去干净一半取决于边界去除阶段 ROI 切得准不准别到最后一步才去找后悔药。2. 图像边界去除先把手指从背景里干净地切出来2.1 为什么边界去除要单独做成一步指静脉图像多采用红外透射采集手指区域的灰度值比背景高但边缘并不锐利而是一条渐变的过渡带。如果不先把手指区域切成 ROI后面静脉提取用的自适应阈值会在每个局部窗口里混入大量背景像素分割结果会产生沿手指轮廓排列的亮带或暗带形态学处理怎么调都救不回来。边界去除的目标不是把边缘抠到亚像素级而是拿到一个“不把背景带进来、不把手指区域削掉太多”的二值 mask。我一般把这一步拆成两个动作先粗切阈值或边缘检测再精修形态学开闭和最大连通域筛选。粗切决定 ROI 的大致范围精修负责把边缘上的孔洞和半透明指套造成的假区域补上。裁剪这一步的关键参数只有三个灰度阈值、结构元半径、是否保留最大连通域。阈值决定切在灰度直方图的哪个谷底结构元半径决定边缘毛刺被腐蚀掉多少最大连通域筛选负责把背景里的孤立亮点一次性清干净。2.2 方法一阈值外接矩形三行 MATLAB 代码跑通最省事的路子是全局阈值加外接矩形裁剪适合背景干净、光照均匀的图像。代码量很短但每一步都有讲究img imread(fingerwein2_sample.bmp); if size(img, 3) 3 img rgb2gray(img); % 转灰度 end bw img 60; % 固定阈值背景接近0手指区域明显更亮 bw imopen(bw, strel(disk, 5)); % 消掉边缘的孤立噪点 bw imfill(bw, holes); % 填掉手指内部的暗斑 bw bwareafilt(bw, 1); % 只保留面积最大的连通域 stats regionprops(bw, BoundingBox); roi imcrop(img, stats.BoundingBox); imwrite(roi, roi.bmp);这段代码的逻辑先按固定阈值生成初始二值图再用半径为 5 的圆盘结构元做开运算把手指边缘外的小颗粒噪声腐蚀掉imfill把手指内部因为汗腺或阴影形成的黑点填成白色保证 mask 是实心的bwareafilt(bw, 1)只留面积最大的连通域这一步能直接干掉背景里比手指小得多的高亮异物。最后用regionprops取外接矩形坐标imcrop得到 ROI。参数说明阈值 60 是我在暗背景指静脉图上常用的起点你可以用imhist(img)看灰度直方图如果背景和手指形成双峰取两个峰之间的谷底值如果背景偏亮阈值要往上抬到 80 或 100。disk 半径 5 不能太大太大会把手指边缘的渐变区域整个腐蚀掉导致切出来的手指窄一圈bwareafilt的第二个参数 1 表示保留最大连通域如果图像里同时出现手指和指套高亮区可以先做一次开运算让两者分离再筛选。2.3 方法二逐列边缘跟随处理亮度不均的棘手图像固定阈值在背景均匀时很好用但夜间的采集设备或者手掌根部靠近光源时图像经常出现半边亮半边暗的情况全局阈值会让手指被拦腰切断。这时候我改用逐列扫描找每一列的上下边缘。[m, n] size(img); up zeros(1, n); down zeros(1, n); thresh 60; for c 1:n col img(:, c); idx1 find(col thresh, 1, first); % 该列第一个超过阈值的点 if isempty(idx1) up(c) 1; % 整列无手指置为边界值 else up(c) idx1; end idx2 find(col thresh, 1, last); % 该列最后一个超过阈值的点 if isempty(idx2) down(c) m; else down(c) idx2; end end up medfilt1(up, 15, truncate); down medfilt1(down, 15, truncate); bw false(m, n); for c 1:n bw(round(up(c)):round(down(c)), c) true; end roi img .* uint8(bw);逻辑说明对于每一列find(..., first)和find(..., last)分别给出该列中手指区域的上下边界所有列合起来就构成了手指轮廓。中值滤波medfilt1是这版代码的核心它能把个别列因为水渍或反光造成的边缘突变压平避免 ROI 边缘出现锯齿。最后把每一列上下界之间的像素置 true生成密实 mask。参数说明medfilt1的窗口 15 指的是 15 个像素列宽度如果采集图很大可以调到 31窗口太小时边缘抖动压不住窗口太大则会把手指真实的弧形轮廓过度平滑。这种方法在手指斜放、背景有渐变亮斑时比固定阈值稳得多适合MATLAB 图像处理实验里那种采集条件不受控的素材。2.4 边界去不干净时先检查这四件事边界去除后 ROI 里残留背景我按出现频率排了四个检查点阈值选错看灰度直方图如果背景和前景不是明显的双峰说明光照不均匀别死磕全局阈值直接换 2.3 的逐列扫描。边缘渐变被切成碎块现象是 ROI 边缘有一圈锯齿状空洞。原因是img thresh把半透明的边缘渐变区域判为背景。解决先用小的 disk 结构元做imclose封口再做imfill。手指内部出现黑斑指静脉图像里汗腺或指骨投影会产生暗区imfill没生效是因为这些黑斑和背景连通。解决先做一次imclose(bw, strel(disk, 7))让内部黑斑与外界断开再imfill。ROI 里仍然有大块高亮背景说明背景里有反光板或指套边缘直接用bwareafilt拿最大连通域不够。解决把 mask 做一次开运算让手指和背景高亮分离后再选面积最大且长宽比合理的那个域。边界去除这块我踩过的坑基本都集中在“阈值看起来对但边缘渐变区域把后面静脉提取带崩了”所以宁可裁剪范围保守一点也别让背景混进 ROI。3. 静脉提取从灰度图里把血管纹路分离出来3.1 为什么先增强再分割直接阈值全是噪声指静脉图像的灰度起伏很小血管区域和周围组织的对比度常常只有二三十个灰度级。对这样的图直接im2bw(img, 0.5)得到的只是一片随机黑白噪声即使把阈值卡得很准也只能提取出手指的整体轮廓看不到静脉纹路。所以静脉提取的前置步骤一定是增强而且增强方法要针对“暗纹路”这个特性来选择。指静脉在透射图像里一般表现为比周围暗的条状结构。提取暗结构最典型的形态学工具是黑顶帽变换imbothat它的原理是用一个比静脉脊宽更大的结构元做闭运算把亮背景估计出来再用原图减去这个背景估计剩下的就是暗的静脉。这个过程不需要训练不用调一堆深度学习的超参对 fingerwein2 这类图像能得到稳定可解释的结果。3.2 顶帽变换加自适应阈值的最小实现下面是一段能直接跑通的 MATLAB 实现img imread(roi.bmp); if size(img, 3) 3 img rgb2gray(img); end img im2double(img); % 统一转 double避免 uint8 溢出 se strel(disk, 12); % 结构元直径大于静脉宽度 bg imclose(img, se); % 估计亮背景 vein_img bg - img; % 提取暗结构黑顶帽的等价实现 vein_img imgaussfilt(vein_img, 1.2); % 轻高斯平滑压点状噪声 bw imbinarize(vein_img, adaptthresh(vein_img, 0.6, NeighborhoodSize, 51)); bw bwareaopen(bw, 30); % 删除面积小于30像素的孤立点逻辑说明imclose用半径为 12 的圆盘结构元做闭运算因为结构元比静脉宽闭运算结果会保留背景大范围亮度变化而把静脉这些暗纹“抹平”。bg - img得到的就是原图相对背景的暗部差异也就是静脉候选区域。im2double是为了让减法不做 uint8 截断否则原本的暗静脉差值会被算成 0这一步属于典型的血泪经验。imgaussfilt做轻度平滑sigma 1.2 只压单像素噪声。最后adaptthresh在局部窗口内做自适应阈值分割bwareaopen清理小于 30 像素的点状噪声。参数说明结构元半径 12 的物理含义是“比最宽的静脉粗、比手指宽度细得多”。如果静脉宽度在 3 到 8 像素半径 8 到 15 都是安全范围半径太小会把静脉当成背景抹掉半径太大会让提取结果变成大黑块。adaptthresh的灵敏度 0.6 表示分割阈值偏向更暗的一侧想多提取细静脉就降到 0.5想减少噪声就抬到 0.7。邻域大小 51 对应一个约 50 像素宽的统计窗口窗口必须覆盖几条静脉的间距太小会跟着局部起伏乱跳。3.3 三个参数怎么配合调翻车时看什么结构元半径、自适应阈值灵敏度、邻域尺寸是这整套流程里最关键的三个旋钮。我的调参顺序是先固定邻域 51把结构元半径从 15 往下减看分割结果的静脉是否逐步变粗如果变粗的同时噪声点也变多说明半径太小回到上一个值。然后调灵敏度0.5 到 0.7 之间以 0.05 为步长扫一遍观察静脉断裂数量和噪声点数量。常见翻车现象静脉全变成一块块的“斑”是结构元半径太小静脉只有主干没有细分支是灵敏度太低整幅图全是胡椒盐噪声是高斯平滑 sigma 太小或邻域尺寸太小。这三个现象能定位到具体的参数方向不用盲猜。3.4 用 OpenCV 复刻同一套流程的要点如果项目是用 Python 和 OpenCV 做的同样的流程可以这样写import cv2 import numpy as np img cv2.imread(roi.bmp, cv2.IMREAD_GRAYSCALE) img cv2.normalize(img, None, 0, 1.0, cv2.NORM_MINMAX) kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (25, 25)) bg cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) vein cv2.subtract(bg, img) vein cv2.GaussianBlur(vein, (0, 0), 1.2) vein cv2.normalize(vein, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8) bw cv2.adaptiveThreshold( vein, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 51, 5 )参数说明MORPH_CLOSE对应 MATLAB 的imclose核的尺寸是 25x25对应 disk 半径 12 的效果MORPH_ELLIPSE生成椭圆核比矩形核更接近圆盘。cv2.adaptiveThreshold的最后一个参数 5 是 C 值表示从高斯加权均值里减去的常数作用类似于adaptthresh的灵敏度C 值越大二值化结果越偏亮提取出的暗纹越少C 值越小越容易出噪声。OpenCV 的MORPH_CLOSE在边缘处会有轻微的方形伪影所以GaussianBlur那一步不能省。需要重点提醒的是OpenCV 里图像类型是 uint8 时cv2.subtract(bg, img)会自动截断负值必须保证 bg 的像素值不低于 img否则暗纹信息会被丢光。这也是为什么我先做normalize把图像整体拉伸到 0 到 1 的浮点数域再转回 uint8 做减法这一步相当于 MATLAB 里的im2double。4. 去除毛刺形态学开运算与骨架剪枝哪套更适合 fingerwein24.1 毛刺是从哪冒出来的静脉二值图里最常见的毛刺有两种来源一种来自分割阶段阈值偏低导致静脉边缘产生锯齿状凸起另一种来自骨架化阶段bwskel会把每个小凸起变成一段短枝。毛刺的数量和静脉提取的参数强相关灵敏度越高毛刺越多。去除毛刺不只是一个形态学动作本质上是“保留真实静脉分支删掉短小伪分支”的判断过程。所以我要先分清楚手里的毛刺是哪种形态边缘锯齿型毛刺长度普遍只有 2 到 5 像素方向随机骨架短枝型毛刺长度在 5 到 20 像素末端明显变细。前一种适合用开运算处理后一种适合用骨架剪枝处理混着用容易把真实静脉一起删掉。4.2 方案A形态学开运算简单但容易削真静脉bw imbinarize(vein_img, adaptthresh(vein_img, 0.6, NeighborhoodSize, 51)); bw bwareaopen(bw, 30); bw2 imopen(bw, strel(line, 3, 0)); % 水平方向消毛刺 bw2 imopen(bw2, strel(line, 3, 90)); % 垂直方向消毛刺 bw2 imclose(bw2, strel(line, 3, 0));逻辑说明开运算是先腐蚀再膨胀能把小于结构元尺寸的凸起直接腐蚀掉。先用水平方向的 3 像素线段结构元消横向毛刺再用垂直方向的消纵向毛刺最后用水平方向的闭运算把开运算可能造成的断口重新接上。参数说明结构元长度 3 的意思是“只删除长度不超过 3 像素的毛刺”。这个值一旦改大到 5 或 7真实静脉的末端也会被当作毛刺腐蚀掉静脉形状会明显变细。所以方案A只适合毛刺普遍比较短的图像优点是快、稳定缺点是参数不能贪。4.3 方案B骨架端点半扫描剪枝能控制删多少当毛刺长度超过 5 像素时方案A基本失效需要先做骨架化再剪枝。骨架化后的静脉是单像素宽的线毛刺表现为一端连着静脉主干、另一端悬空的短枝。剪枝可以迭代地删掉那些不靠近分支点的端点像素skel bwskel(bw); % 骨架化单像素宽 N 8; % 最大删枝长度 for k 1:N ep bwmorph(skel, endpoints); % 找出当前所有端点 bp bwmorph(skel, branchpoints); % 找出当前所有分支点 keep imdilate(bp, strel(disk, 1)); skel(ep ~keep) false; % 删掉不挨着分支点的端点像素 end bw_out imdilate(skel, strel(disk, 1)); % 把骨架还原成有宽度的静脉逻辑说明每一轮迭代只删一层端点像素而且只删那些“8 邻域内没有分支点”的端点像素。如果某个端点的邻域里有分支点说明这条枝很短只剩最后一步保留它。循环 N 次后长度超过 N 像素的短枝会被从末端逐步侵蚀掉长度不超过 N 的真实短分支会保留下来。这个方法的控制力比bwmorph(skel, spur, N)强因为spur有时候会把靠近分支点的细分支整个吞掉。参数说明N 的物理含义是“允许保留的最短分支长度”8 表示小于等于 8 像素的短枝会被删光大于 8 像素的正常分支不受影响。真实静脉分支末端的长度通常在 15 像素以上所以 N 设在 6 到 10 之间比较安全。imdilate(bp, strel(disk, 1))是把分支点向外扩一圈避免端点离分支点只有一个像素时被误删。4.4 两套方案的适用边界我用这套流程的经验是如果二值图的毛刺大多集中在静脉边缘、长度不超过 5 像素直接走方案A速度快且不会误删大分支如果静脉已经做了骨架化、毛刺长度在 5 到 20 像素之间走方案B用 N 控制剪枝力度。还有一个实际项目里常见的需求只想删掉某一方向的毛刺比如图像里手指横放静脉分支大多沿手指方向延伸横向毛刺是噪声。这种情况可以把方案A里的strel(line, 3, 0)单独留下不用垂直方向的第二次开运算毛刺删除会更保守。5. 避坑边界误删、静脉断裂、毛刺误删的排查记录5.1 现象手指边缘一圈被当成背景切掉跑完边界去除后ROI 手指区域明显比原图窄了一圈边缘的渐变过渡带被整体切掉更严重的甚至能看到手指轮廓处一道深色描边。原因固定阈值img 60把边缘渐变区域中稍暗的像素判成了背景导致 mask 收缩到手指内部。逐列边缘跟随后如果没做中值滤波每一列边缘的随机波动也会造成窄边框丢失。解决先对 mask 做imclose(bw, strel(disk, 7))把边缘缺口封住再用imfill补内部黑斑。如果是逐列边缘跟随把up和down曲线的中值滤波窗口从 15 加到 25边缘轮廓的抖动会明显减弱。做这些操作时注意别把背景一起包进来开运算的半径上限不要超过手指宽度的 5%。5.2 现象静脉纹路断裂成碎线分割出来的静脉二值图里原本连续的一条静脉变成三五段短线段段与段之间有小空隙骨架化之后更是碎成一堆短枝。原因静脉提取时结构元半径太大把细静脉段当成背景抹掉了或者adaptthresh灵敏度太低静脉中心最暗的部分能通过阈值但靠近边缘的渐变区域被判成背景。我在调参时经常遇到这两种原因的叠加形态学上表现为静脉主干存在但全线断裂。解决把结构元半径从 12 降到 9 或 10同时把灵敏度从 0.6 降到 0.5。如果断裂仍然存在在分割之后加一步闭运算imclose(bw, strel(line, 7, 0))这个操作能沿手指方向把断口接上但代价是会把并行的两条静脉粘连所以闭运算结构元长度别超过静脉宽度的两倍。5.3 现象毛刺削完真静脉跟着变淡用开运算去毛刺后整条静脉的宽度明显变窄细分支甚至直接消失。如果用了方案B还会出现静脉主干局部消失的断层。原因方案A的imopen结构元尺寸大于真实静脉末梢宽度开运算是先腐蚀静脉末梢在腐蚀阶段就被完全删掉了后续膨胀也救不回来。方案B的 N 如果超过 10会把一些正常的短分支当成毛刺删掉。解决开运算的结构元长度从 3 降到 2或者改用“先bwareaopen删除面积小于 20 像素的孤立块再做骨架剪枝”避免动静脉主体。方案B 的 N 控制在 5 到 8 之间并且剪完要拿原二值图和剪枝结果做一次视觉对比确认静脉没有断层。5.4 现象MATLAB 里 imfill、bwskel 报错结果全黑这是 MATLAB 大作业里最常见的翻车现场imfill(bw, holes)报错“Expected input number 2, holes, to match a string”或者imbinarize之后变量类型是 logical但imopen的结果变成了全黑。再常见的还有img 60在 uint8 和 double 之间混用导致阈值判断结果全部为假。原因函数期望输入类型和实际类型不匹配。imfill的 holes 参数要求输入是二值图如果你传的是灰度图或者 double 类型MATLAB 的参数解析会直接报错。bwskel要求输入是 logical 类型imbinarize的输出默认是 logical但如果你用img 60之后又乘了系数类型就变成了 double。解决进入形态学阶段前统一做一次islogical(bw)断言imfill之前执行bw logical(bw)。灰度图阈值操作之前先im2double(img)再把阈值改成 0 到 1 之间的浮点数比如img 0.25。这类类型问题属于纯踩坑多写几条断言能让后面调试少一大半时间。6. 验证管线效果用端点统计与连通域指标判断要不要返工处理完图像后光靠肉眼很容易被表面效果欺骗我习惯用四个量化指标来确认整套流程没有跑偏指标计算方式合理范围超限含义连通域数量numel(regionprops(bw, Area))20 到 80 个太多说明静脉断裂严重骨架端点数量sum(bwmorph(bwskel(bw), endpoints))30 到 120 个端点爆炸说明毛刺没去干净平均静脉宽度距离变换后取静脉区域均值3 到 8 像素宽度过小说明开运算削太多毛刺删除比例剪枝前后骨架像素差÷ 剪枝前像素5% 到 15%比例超过 20% 说明误删风险高对应到代码里可以直接在 MATLAB 中这样算stats regionprops(bw, Area); num_cc numel(stats); skel bwskel(bw); num_ep sum(bwmorph(skel, endpoints), all); dist bwdist(~bw); avg_width 2 * mean(dist(bw)); % 距离值×2 近似静脉宽度我的习惯是每次调完参数先打印这四个数值再叠加显示原始图、二值图和骨架图。如果连通域数量超过 100回到静脉提取阶段降灵敏度如果端点数量超过 150回到剪枝阶段加大 N如果平均宽度小于 3 像素说明形态学结构元开太大了。这套验证流程的唯一缺点是要手动记参数组合对应的指标值我为此翻过几次车后来老老实实把每次调参的指标记录成一行日志比对起来效率高很多。另外给一个判断技巧把剪枝前后的骨架图叠在同一个窗口里用红色显示被删除的像素。如果红色像素集中在真实静脉末端附近而不是分布在静脉边缘说明 N 值可能太大需要回退。这个技巧救过我好几次比盯着指标数字更直观。希望这套从边界去除到静脉提取再到去毛刺的落地流程能帮到你少走我走过的那几段弯路。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

大模型预训练数据集构建实战:从数据清洗到LlamaFactory对接的完整流程 2026/10/2 20:03:36

大模型预训练数据集构建实战:从数据清洗到LlamaFactory对接的完整流程

预训练数据集这件事,很多人以为就是"把一堆文本打包成jsonl",真上手才发现坑远比想象的多。我见过太多团队在微调阶段反复调参却收效甚微,最后回头一查,问题根本不在模型和超参上,而是预训练数据本身的质量和…

阅读更多 →
海康摄像头预览取流URL获取指南:RTSP/ISAPI/SDK/OpenAPI全攻略 2026/10/2 20:03:29

海康摄像头预览取流URL获取指南:RTSP/ISAPI/SDK/OpenAPI全攻略

做海康设备开发的人,十个有九个会被同一个问题卡住:明明摄像头画面在浏览器里看得好好的,可一到自己写代码拉视频流,就不知道该调哪个接口、拿哪个地址。尤其是项目里只需要一个“预览取流的URL”交给播放器去拉流时,很…

阅读更多 →
Java开源物联网平台核心设计与实践:从设备接入到数据存储 2026/10/2 20:03:23

Java开源物联网平台核心设计与实践:从设备接入到数据存储

做Java后端这些年,被问得最多的一个问题,就是“物联网平台到底是不是伪需求”。说实话,刚入行时我也觉得IoT平台无非是把设备数据收上来、存起来、做几个报表。直到我自己动手维护过一套设备接入规模过万的Java开源物联网平台,才明…

阅读更多 →
openrig开放框架机箱:从图纸到整机的DIY搭建全攻略 2026/10/2 20:03:10

openrig开放框架机箱:从图纸到整机的DIY搭建全攻略

直接开工。做DIY硬件的老哥们应该都有同感:一套设备玩久了,最难熬的不是性能不够,而是机箱理线、散热风道、扩展位这些破事反复折腾。如果你想把手上的显卡、主板、电源这些零件,装进一套真正按自己需求设计、还能随时拆改的开放框…

阅读更多 →
AI视频生成API异步接入指南:从任务提交到结果回收的完整方案 2026/10/2 20:03:03

AI视频生成API异步接入指南:从任务提交到结果回收的完整方案

做AI视频类的应用时,最磨人的往往不是“怎么生成视频”,而是“生成之后怎么把结果拿回来”。视频生成和文本聊天完全是两套交互逻辑——你发一个请求过去,对面不可能立刻把mp4文件吐给你,通常几十秒甚至几分钟之后才能出结果。这中…

阅读更多 →
Vue实现组织架构图:vue-tree-chart自定义节点与右键菜单实战 2026/10/2 20:03:03

Vue实现组织架构图:vue-tree-chart自定义节点与右键菜单实战

做后台管理系统,组织架构图几乎是躲不开的模块。权限管理里要展示部门层级,用户管理模块里要体现汇报关系,甚至不少审批流程也要把组织架构作为角色和负责人的筛选维度。Vue 生态里能渲染树形组件的库一抓一大把,但想做成“从上到…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉