资讯动态

OpenCV形态学操作全解析:腐蚀膨胀到顶帽黑帽实战

发布时间:2026/10/15 12:03:14 来源:尧图企业网站定制
1. 形态学操作到底在图像里干了什么很多人第一次接触OpenCV的形态学操作脑子里冒出来的第一个问题就是这玩意儿跟滤波有什么区别我当初也是这么想的。后来在做一个工业质检的小项目时需要从一张背景噪声很重的金属表面图像里把划痕提取出来用高斯滤波、中值滤波折腾了一整天边缘全糊了划痕反而更看不清。后来换了个思路用形态学的顶帽运算几行代码就把问题解决了。从那以后我才真正理解形态学操作的本质不是平滑或锐化而是根据像素邻域的几何结构去改造图像的形状。说白了滤波是加权平均或者排序取中值它关心的是像素值的大小关系形态学关心的是像素的空间结构——哪些像素连在一起、哪些是孤立的、哪些区域比结构元素小、哪些比结构元素大。这个思维方式的转变非常关键因为一旦你理解了这一点你就会知道什么时候该用形态学什么时候该用滤波。形态学操作最核心的两个基础运算是腐蚀和膨胀。腐蚀的效果是让亮区域前景缩小膨胀的效果是让亮区域扩大。听起来很简单对吧但就是这两个看似简单的操作通过不同的组合和顺序能衍生出开运算、闭运算、形态学梯度、顶帽、黑帽等一系列强大的工具。这些工具在去噪、分割、边缘检测、缺陷检测、文字提取等场景里几乎是标配。这篇文章我会从底层原理讲起把每个操作的数学逻辑、适用场景、参数调优方法、以及我在实际项目中踩过的坑全部摊开来讲。不管你是刚学OpenCV的新手还是已经用过形态学但总觉得调参靠玄学的老手应该都能从里面找到有用的东西。文章里所有的代码都是Python OpenCV可以直接复制运行我会尽量把每个参数为什么这么设讲清楚。2. 腐蚀与膨胀形态学的两块基石2.1 结构元素形态学操作的模具在讲腐蚀和膨胀之前必须先搞清楚结构元素这个概念。你可以把结构元素想象成一个模具或者探针它在图像上滑动每滑到一个位置就和该位置的像素邻域做运算。结构元素的形状和大小直接决定了操作的效果。OpenCV里用cv2.getStructuringElement()来创建结构元素最常用的三种形状import cv2 import numpy as np # 矩形结构元素 5x5 kernel_rect cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) # 椭圆结构元素 5x5 kernel_ellipse cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) # 十字形结构元素 5x5 kernel_cross cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5)) print(矩形:\n, kernel_rect) print(椭圆:\n, kernel_ellipse) print(十字:\n, kernel_cross)矩形结构元素就是全1矩阵十字形是只有中心行和中心列为1椭圆形则是根据椭圆方程生成的近似形状。选哪种形状取决于你要处理的目标的几何特征。比如你要处理的是圆形细胞用椭圆结构元素效果最好要处理的是水平或垂直的线条十字形更合适如果目标形状不规则矩形是最通用的选择。结构元素的大小也非常关键。3x3适合处理细小的噪声点5x5适合处理中等大小的目标7x7以上就会对图像产生比较剧烈的改变。我个人的经验是先用3x3试效果不够再逐步加大每次加2。不要一上来就用很大的核那样很容易把有用的细节一起干掉。2.2 腐蚀的数学逻辑与实战效果腐蚀的运算规则是这样的结构元素在图像上滑动当结构元素完全覆盖的所有像素都为前景白色值为255时中心像素才保留为前景否则变为背景黑色0。用数学语言说就是取邻域内的最小值。img cv2.imread(test.png, 0) # 灰度图读取 _, binary cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 3x3矩形核腐蚀 kernel cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) eroded cv2.erode(binary, kernel, iterations1) # iterations参数控制腐蚀次数次数越多腐蚀越狠 eroded_3 cv2.erode(binary, kernel, iterations3)腐蚀的直观效果就是亮区域变小暗区域变大。如果你处理的是一张白底黑字的文字图像腐蚀会让黑色文字变粗如果是黑底白字腐蚀会让白色文字变细。腐蚀最典型的应用场景是去除小的白色噪声点。假设你的二值图像上有很多孤立的白色噪点每个噪点只有1到2个像素大小用一个3x3的核腐蚀一次这些噪点就全部消失了因为3x3的结构元素无法被1到2个像素完全覆盖。但要注意腐蚀同时也会让真正的前景目标缩小一圈所以如果你的目标本身就很细比如细线腐蚀可能会把它直接干掉。注意腐蚀操作对二值图效果最直观但它同样适用于灰度图。在灰度图上腐蚀就是取邻域最小值效果是图像整体变暗亮细节被削弱。2.3 膨胀与腐蚀对称的另一面膨胀的运算规则和腐蚀正好相反只要结构元素覆盖的邻域内存在前景像素中心像素就变为前景。数学上是取邻域内的最大值。# 膨胀操作 dilated cv2.dilate(binary, kernel, iterations1) # 膨胀也可以多次迭代 dilated_3 cv2.dilate(binary, kernel, iterations3)膨胀的效果是亮区域扩大暗区域缩小。它最典型的用途是填补前景目标内部的空洞和小裂缝。比如你做阈值分割之后目标内部可能有一些因为光照不均导致的黑色小洞用膨胀操作就能把这些洞填上。膨胀还有一个很实用的场景连接断开的区域。如果你的目标被分成了几段不连续的区域用一个合适大小的结构元素膨胀就能把它们连成一体。这个在文字识别里特别常用——有些字符因为扫描质量不好会断裂膨胀一下就能恢复连通性。腐蚀和膨胀是一对逆运算但它们不是可逆的。先腐蚀再膨胀和先膨胀再腐蚀得到的结果完全不同这就引出了后面要讲的开运算和闭运算。2.4 腐蚀膨胀的调参经验在实际项目里调腐蚀和膨胀的参数我总结了几个实用的判断方法第一看目标的尺寸。如果你的目标最小宽度是10个像素那结构元素的大小不要超过这个值否则目标会被完全腐蚀掉。一般取目标最小宽度的1/3到1/2比较安全。第二看噪声的尺寸。如果噪声点最大是3个像素用3x3的核腐蚀一次就够了。如果噪声更大要么加大核要么增加迭代次数。但增加迭代次数比加大核更温和因为它是一步一步来的你可以观察到中间结果。第三iterations参数慎用大值。iterations2的效果不等于用5x5的核虽然有些情况下相似但迭代会在每次操作后重新计算对图像结构的破坏是累积的。我一般iterations不超过3超过3的话宁可换更大的核。3. 开运算与闭运算组合拳的威力3.1 开运算先腐蚀后膨胀的妙用开运算的定义很简单先腐蚀再膨胀。用同一个结构元素先腐蚀掉小的噪声和毛刺再膨胀恢复目标的大致尺寸。# 开运算 opened cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) # 等价于 eroded cv2.erode(binary, kernel) opened_manual cv2.dilate(eroded, kernel)为什么开运算这么有用因为腐蚀会去掉小噪声但也会让目标缩小膨胀会把目标恢复回来但不会恢复已经被腐蚀掉的噪声。所以开运算的净效果就是去掉比结构元素小的亮区域保留比结构元素大的亮区域且大致保持大区域的尺寸不变。开运算最经典的应用是去除背景中的小白点噪声。比如你在做缺陷检测背景上有很多灰尘颗粒造成的小白点用开运算就能干净地去掉它们而真正的缺陷区域因为面积大会被保留下来。还有一个场景是分离粘连的物体。如果两个目标之间只有很细的连接开运算可以把这个连接切断让两个目标分开。这个在细胞计数里非常常用——细胞之间有时候会粘连开运算可以帮你把它们分开。3.2 闭运算先膨胀后腐蚀的适用场景闭运算是开运算的反操作先膨胀再腐蚀。它用来填充目标内部的小孔洞和裂缝同时保持目标的大致尺寸。# 闭运算 closed cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)闭运算的典型应用是填充前景区域内部的黑色小洞。比如你做了一个阈值分割目标区域内部因为反光或者纹理原因出现了一些黑色小孔闭运算可以把这些孔填上。另一个常见用途是连接邻近的断裂区域。如果目标因为噪声被分成了几段闭运算可以通过先膨胀把它们连起来再腐蚀恢复尺寸。3.3 开闭运算的先后顺序为什么不能反很多人会问既然开运算是先腐蚀后膨胀闭运算是先膨胀后腐蚀那我能不能反过来用答案是不能顺序反了效果完全不同。先腐蚀后膨胀开运算的净效果是去掉小亮区域先膨胀后腐蚀闭运算的净效果是去掉小暗区域。这两个操作针对的是完全不同的问题。如果你用闭运算去噪你会发现噪声不但没去掉反而可能被放大了。我当初就犯过这个错误。在一个项目里二值化之后背景有很多小白点我随手用了闭运算结果小白点膨胀之后和旁边的目标连在一起了腐蚀之后反而变成了更大的噪声块。后来换成开运算问题立刻解决。所以一定要根据你要去掉的是亮噪声还是暗噪声来选择。3.4 开闭运算的核大小选择策略开闭运算的核大小选择比单纯的腐蚀膨胀更讲究因为你要同时考虑去掉什么和保留什么。我的经验法则是核的大小要大于你要去掉的噪声尺寸小于你要保留的目标尺寸。比如噪声点直径2到3像素目标最小宽度15像素那核的大小取5x5到7x7之间比较合适。如果噪声和目标尺寸差距不大那就很难用单一的形态学操作解决需要考虑多尺度方法或者换其他思路。这种情况下强行调参只会顾此失彼。4. 形态学梯度、顶帽与黑帽进阶工具4.1 形态学梯度提取目标轮廓形态学梯度的定义是膨胀图减去腐蚀图。膨胀让亮区域扩大腐蚀让亮区域缩小两者相减剩下的就是亮区域边缘的那一圈。# 形态学梯度 gradient cv2.morphologyEx(binary, cv2.MORPH_GRADIENT, kernel)形态学梯度的效果类似于边缘检测但它和Canny、Sobel这些算子有本质区别。Canny和Sobel是基于像素值的变化率梯度而形态学梯度是基于形状的膨胀腐蚀差。形态学梯度得到的边缘更粗但更连续不容易断裂。在实际项目里形态学梯度常用于提取目标的粗略轮廓然后再配合其他方法做精细定位。比如在工业检测里先用形态学梯度找到产品的大致边缘再用亚像素边缘检测做精确定位。4.2 顶帽运算从暗背景中提取亮目标顶帽运算的定义是原图减去开运算结果。开运算去掉了比结构元素小的亮区域那么原图减去开运算剩下的就是那些被去掉的小亮区域。# 顶帽运算 tophat cv2.morphologyEx(gray_img, cv2.MORPH_TOPHAT, kernel)顶帽运算最强大的场景是从光照不均匀的背景中提取亮目标。比如你要从一张背景亮度渐变很大的图像里提取亮斑直接阈值分割肯定不行因为背景亮度本身就在变化。但顶帽运算可以先把背景估计出来通过开运算然后减掉剩下的就是亮目标。我前面提到的金属表面划痕检测用的就是顶帽运算。划痕是亮线背景虽然不均匀但整体比划痕暗顶帽运算之后划痕非常清晰再做一个简单的阈值就提取出来了。4.3 黑帽运算从亮背景中提取暗目标黑帽运算是顶帽的对称操作定义是闭运算结果减去原图。闭运算填充了暗的小区域闭运算减去原图剩下的就是那些被填充的暗区域。# 黑帽运算 blackhat cv2.morphologyEx(gray_img, cv2.MORPH_BLACKHAT, kernel)黑帽运算用于从亮背景中提取暗目标。比如白纸上的黑色文字、亮背景上的暗缺陷等。它的原理和顶帽完全对称只是针对的极性不同。4.4 顶帽黑帽的核大小与目标尺寸的关系顶帽和黑帽的核大小选择有一个非常明确的准则核的大小必须大于你要提取的目标尺寸。因为开运算顶帽的基础会去掉比核小的亮区域如果你要提取的亮目标比核还大它就不会被开运算去掉顶帽结果里也就没有它。这个准则和开闭运算正好相反。开闭运算的核要大于噪声小于目标顶帽黑帽的核要大于目标。我当初在这里也迷糊过后来画了个图才理清楚顶帽提取的是比核小的亮目标所以核必须比目标大。举个例子你要提取宽度3到5像素的亮划痕核的大小至少取7x7或者9x9。如果取3x3划痕比核大开运算去不掉它顶帽结果就是一片黑。5. 形态学操作的实战组合与调参心得5.1 一个完整的缺陷检测流程我拿一个模拟的工业缺陷检测场景来串一遍完整的流程。假设有一张金属表面图像上面有一些亮色划痕缺陷背景有轻微的不均匀光照和随机噪声。import cv2 import numpy as np # 读取图像 img cv2.imread(metal_surface.png, 0) # 第一步高斯滤波去随机噪声 blurred cv2.GaussianBlur(img, (5, 5), 0) # 第二步顶帽运算提取亮划痕 kernel_tophat cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15)) tophat cv2.morphologyEx(blurred, cv2.MORPH_TOPHAT, kernel_tophat) # 第三步阈值分割 _, binary cv2.threshold(tophat, 30, 255, cv2.THRESH_BINARY) # 第四步开运算去小噪声 kernel_open cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) cleaned cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel_open) # 第五步闭运算连接断裂的划痕 kernel_close cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) final cv2.morphologyEx(cleaned, cv2.MORPH_CLOSE, kernel_close)这个流程里每一步都有明确的目的高斯滤波去掉随机噪声顶帽运算消除不均匀光照的影响并突出亮划痕阈值分割二值化开运算去掉残留的小噪点闭运算把断开的划痕连起来。每一步的参数都需要根据实际图像调整没有万能参数。5.2 参数调优的排查思路当你发现形态学操作效果不好的时候不要盲目调参按下面的顺序排查问题现象可能原因排查方法目标被完全消除核太大或腐蚀次数太多减小核尺寸或iterations噪声去不干净核太小增大核尺寸但注意不要超过目标尺寸目标断裂腐蚀过度减少腐蚀次数或改用闭运算目标粘连膨胀过度减少膨胀次数或改用开运算顶帽结果全黑核比目标小增大核尺寸到大于目标边缘太粗结构元素太大换更小的核或换形状这个表格是我在实际项目中总结出来的基本上90%的调参问题都能在里面找到方向。5.3 形态学操作的性能优化形态学操作的计算量其实不小特别是大核的情况下。OpenCV内部对形态学操作做了优化但如果你在视频流或者高分辨率图像上跑还是要注意性能。第一个优化点是能用小核就不用大核。3x3的核比15x15的核快很多。如果小核能达到效果就不要用大核。第二个优化点是减少迭代次数。iterations3比iterations1慢三倍如果能用大一点的核一次搞定就不要迭代三次。第三个优化点是在二值图上操作。形态学在二值图上的计算量比灰度图小因为二值图只有0和255两个值。如果可能先二值化再做形态学。第四个优化点是用cv2.morphologyEx而不是手动组合。OpenCV对morphologyEx做了专门的优化比你自己先erode再dilate要快。5.4 常见误区与避坑指南误区一形态学可以替代滤波。形态学和滤波解决的是不同问题不能互相替代。滤波去随机噪声形态学处理形状结构。正确的做法是先滤波再形态学。误区二核越大效果越好。核越大操作越暴力越容易误伤有用信息。我见过有人用31x31的核做开运算结果整个图像变成了一片黑。误区三形态学只适用于二值图。形态学同样适用于灰度图和彩色图。在灰度图上腐蚀取邻域最小值膨胀取邻域最大值效果是图像变暗或变亮。彩色图则是对每个通道分别操作。误区四结构元素形状无所谓。形状很重要。处理圆形目标用椭圆核处理矩形目标用矩形核处理线条用十字核。形状选错了效果会差很多。误区五一次操作就能解决所有问题。实际项目里往往需要多次不同参数的形态学操作组合甚至需要和其他图像处理技术配合。不要指望一个操作搞定一切。6. 从灰度图到彩色图形态学的扩展应用6.1 灰度形态学的实际价值前面大部分例子都是基于二值图的但灰度形态学在实际项目里同样重要。灰度腐蚀是取邻域最小值灰度膨胀是取邻域最大值。这两个操作在灰度图上的效果是局部变暗或变亮。灰度形态学最常用的场景是去除不均匀背景。比如你要从一张有渐变背景的图像里提取目标可以用一个比目标大的结构元素做灰度开运算得到背景估计然后用原图减去背景估计剩下的就是目标。这个方法和顶帽运算原理一样但顶帽运算本身就是灰度形态学的一种应用。# 灰度开运算估计背景 kernel_bg cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (51, 51)) background cv2.morphologyEx(gray_img, cv2.MORPH_OPEN, kernel_bg) # 原图减背景 foreground cv2.subtract(gray_img, background)这里核的大小要大于目标尺寸这样才能保证开运算只保留背景不保留目标。51x51的核适合处理尺寸在30像素以下的目标。6.2 彩色图像形态学的处理策略OpenCV的形态学操作可以直接用在彩色图上它会对每个通道分别处理。但这样做有一个问题三个通道的处理结果可能不一致导致颜色偏移。# 直接对彩色图做形态学 color_img cv2.imread(test.png) kernel cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) color_eroded cv2.erode(color_img, kernel)更稳妥的做法是先把彩色图转换到合适的色彩空间只对特定通道做形态学。比如在HSV空间里只对V通道亮度做形态学H和S通道保持不变这样就不会出现颜色偏移。hsv cv2.cvtColor(color_img, cv2.COLOR_BGR2HSV) h, s, v cv2.split(hsv) # 只对V通道做形态学 v_processed cv2.morphologyEx(v, cv2.MORPH_OPEN, kernel) # 合并回去 hsv_processed cv2.merge([h, s, v_processed]) result cv2.cvtColor(hsv_processed, cv2.COLOR_HSV2BGR)这个策略在肤色检测、火焰检测等场景里非常实用。6.3 形态学与轮廓分析的配合形态学操作经常和轮廓分析配合使用。典型的流程是形态学去噪 → 阈值分割 → 形态学清理 → 轮廓提取 → 轮廓筛选。# 形态学清理 cleaned cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) # 提取轮廓 contours, _ cv2.findContours(cleaned, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 按面积筛选 valid_contours [c for c in contours if cv2.contourArea(c) 100]形态学在这里的作用是让轮廓更干净、更完整。如果二值图上有噪声轮廓提取会得到很多小轮廓如果目标有断裂轮廓会不完整。形态学操作可以解决这些问题让后续的轮廓分析更可靠。7. 我在实际项目里踩过的那些坑7.1 核形状选错导致目标变形有一次做一个圆形目标检测的项目我随手用了矩形结构元素做开运算。结果发现圆形目标被削成了近似八边形边缘变得很不自然。后来换成椭圆结构元素问题立刻消失。结构元素的形状应该和目标形状匹配这个教训我记了很久。7.2 迭代次数过多导致目标消失还有一次处理细线目标我用3x3的核腐蚀了5次结果细线直接消失了。当时我以为是核的问题换了各种核都不行。后来才意识到是迭代次数太多每次腐蚀细线都会变细5次之后宽度不够就断了。对于细目标腐蚀次数一定要克制宁可换更小的核也不要多次迭代。7.3 顶帽运算核太小导致提取失败顶帽运算的核必须大于目标尺寸这个我前面强调过。但我自己当初就犯过这个错误。处理宽度10像素的亮线时我用了7x7的核结果顶帽结果几乎全黑。后来把核换成15x15亮线立刻清晰可见。顶帽和黑帽的核大小是下限约束不是上限约束这一点和开闭运算正好相反。7.4 忽略图像边界导致边缘伪影形态学操作在图像边界处会有特殊处理。OpenCV默认使用BORDER_CONSTANT边界外的像素被认为是0。这会导致图像边缘出现伪影——腐蚀时边缘变黑膨胀时边缘变白。如果目标靠近图像边缘这个伪影会影响结果。解决办法是先用cv2.copyMakeBorder给图像加一圈边框处理完再裁掉。边框的宽度要大于结构元素的半径。# 加边框 border_size 10 padded cv2.copyMakeBorder(binary, border_size, border_size, border_size, border_size, cv2.BORDER_CONSTANT, value0) # 形态学操作 processed cv2.morphologyEx(padded, cv2.MORPH_OPEN, kernel) # 裁掉边框 result processed[border_size:-border_size, border_size:-border_size]这个技巧在处理靠近边缘的目标时非常有用我现在的项目里基本都会加上这一步。7.5 在错误的阶段做形态学形态学操作应该放在流程的哪个阶段这个问题没有标准答案但有一个原则去噪类的形态学操作放在阈值分割之后背景估计类的形态学操作放在阈值分割之前。开运算去噪通常放在二值化之后因为二值图上的噪声更明确。顶帽运算提取亮目标通常放在二值化之前因为它需要灰度信息来估计背景。如果把顶帽放在二值化之后信息已经损失了效果会大打折扣。我见过有人在二值化之后做顶帽运算然后抱怨效果不好。这就像把苹果榨成汁之后再想削皮顺序错了怎么做都不对。8. 形态学操作的边界与替代方案形态学操作虽然强大但它不是万能的。有些场景下形态学会失效需要换其他方法。场景一目标和噪声尺寸接近。如果噪声和目标的大小差不多形态学很难在去掉噪声的同时保留目标。这时候需要考虑基于连通域分析的方法或者基于深度学习的分割方法。场景二目标形状复杂且不规则。形态学基于结构元素结构元素的形状是固定的。如果目标形状非常复杂单一结构元素很难适配。这时候可以考虑多尺度形态学或者用多个不同形状的结构元素组合。场景三需要亚像素精度。形态学操作是像素级的精度有限。如果需要亚像素级别的边缘定位形态学梯度只能作为粗定位精定位还需要用亚像素边缘检测算法。场景四实时性要求极高。形态学操作虽然不算慢但在高分辨率视频流上仍然可能成为瓶颈。如果实时性要求极高可以考虑用GPU加速或者用更简单的替代方案。了解这些边界不是为了否定形态学的价值而是为了在正确的场景用正确的工具。形态学操作在图像预处理、目标提取、缺陷检测等场景里仍然是首选方案它的简洁和高效是其他方法很难替代的。9. 一些让形态学更好用的小技巧最后分享几个我在实际项目里总结的小技巧都是些不起眼但很实用的东西。技巧一用cv2.getStructuringElement而不是手动构造核。手动构造容易出错而且OpenCV的内置函数对椭圆核做了优化生成的形状更规整。技巧二调试时把中间结果都显示出来。形态学操作是链式的每一步都会影响后续结果。用cv2.imshow或者保存中间图像能帮你快速定位是哪一步出了问题。技巧三用轨迹条实时调参。OpenCV的cv2.createTrackbar可以让你在运行时动态调整核大小和迭代次数比反复改代码重新运行快得多。这个在调参阶段能省大量时间。def update(val): ksize cv2.getTrackbarPos(ksize, result) * 2 1 kernel cv2.getStructuringElement(cv2.MORPH_RECT, (ksize, ksize)) result cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) cv2.imshow(result, result) cv2.namedWindow(result) cv2.createTrackbar(ksize, result, 1, 15, update) cv2.imshow(result, binary) cv2.waitKey(0)技巧四保存参数组合。调好一组参数之后把核形状、核大小、迭代次数、操作类型都记下来。下次遇到类似场景可以直接用不用从头调。技巧五形态学操作之前先做直方图均衡化。如果图像对比度低形态学操作的效果会打折扣。先做直方图均衡化或者CLAHE让目标更突出形态学操作会更有效。这些技巧看起来简单但在实际项目里能帮你省下大量试错时间。形态学操作本身不难难的是知道在什么场景用什么操作、参数怎么设。希望这篇文章能帮你建立起这个判断力。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑