简介面向MATLAB图像处理课程设计、计算机视觉入门学习者与初级项目实践者的车牌识别项目采用模板匹配完成车牌定位与字符识别可用于智能停车、交通管理等场景的教学演示与课程作业复现。包内围绕主流程调度、车牌预处理与分割、单字符切割、模板匹配识别及GUI交互配置等模块组织以.m脚本和.fig界面文件为主文件总数显示为0类型明细暂缺压缩包约156KB。已有2047人学习说明其作为模板匹配教学案例具有一定参考度。读者可据此梳理从图像预处理、车牌分割到字符逐个匹配的完整链路理解相似度比较与最佳匹配选取的实现思路并借助GUI完成图片上传与结果查看适合作为课程设计原型和算法入门拆解材料。1. 从一张地下车库抓拍图说起模板匹配凭什么还能用在车牌识别上一张地下车库的抓拍图车灯过曝、车牌轻微倾斜、背景里还横着半块广告牌这种图丢进任何一条识别链路都会让人心里打鼓。基于 MATLAB 模板匹配的车牌识别恰恰是为这种“不想上模型、又要有可解释结果”的场景准备的把车牌从背景里框出来切成单个字符再拿预先做好的字符模板逐个比对打分输出置信度最高的一类。它不需要训练不需要显卡一套脚本加一个模板库就能跑代价是模板库要自己攒光照和倾斜一变就得回头调参数。适合做课程设计、产线小工具、算法基线以及那些需要对每个识别结果说清楚“为什么是它”的场合。下面按定位、分割、建库、匹配、排查、验证六步走一遍。2. 车牌定位颜色阈值和形态学闭运算的先后顺序2.1 蓝底车牌的 HSV 阈值怎么定定位这一步决定了后面所有环节的上限。车牌框歪了、缺了一角字符分割再精巧也救不回来。工程上最稳的起手式不是深度学习而是颜色加形状国内常见蓝底白字车牌底色在 HSV 空间里有相当集中的分布先把蓝色区域抠出来再用宽高比筛一遍绝大多数干净场景就能拿到候选框。不用 RGB 而用 HSV理由很实际。RGB 三个通道都随光照强度一起变同一块蓝底在正午和地库里三通道数值能差出一倍HSV 把色调 H 单独拎出来亮度变化主要落在 V 上H 相对稳定。蓝底车牌的 H 在 MATLAB 的rgb2hsv输出里乘 360 之后通常落在 200 到 250 之间饱和度 S 不会太低明度 V 在正常曝光下也不会贴地。% 读图并转到 HSV 空间H 换算成 0-360 度便于设阈值 I imread(car_01.jpg); hsv rgb2hsv(I); H hsv(:,:,1) * 360; S hsv(:,:,2); V hsv(:,:,3); % 蓝色底色掩膜H 卡区间S 和 V 设下限过滤灰白区域 mask (H 200 H 250) (S 0.35) (V 0.20); % 先开运算去掉零散噪点再闭运算把字符和边框连成整块 mask imopen(mask, strel(rectangle, [3 3])); mask imclose(mask, strel(rectangle, [7 21])); mask imfill(mask, holes);这段代码里三个参数最值得动手调。S 0.35是饱和度下限定得太低灰色路面和白色车体也会被拉进来定得太高阴天或逆光下蓝底褪色车牌又漏掉。V 0.20管的是暗部夜间补光过曝的图 V 会顶到 1但底色反而偏白这时单靠颜色会失效得靠下一节的边缘通道兜底。闭运算的[7 21]是竖向 7、横向 21 的长条结构元因为车牌上的字符是横向排布的横向多连一点才能把“X 1 2 3 4 5”连成一个连通域这个尺寸跟你的图像分辨率强相关图越小结构元要同比缩小。提示阈值不要照抄。拿二十张自己场景的图把每张的 H、S、V 在车牌区域取中位数打印出来看分布的重叠区在哪再定区间比任何教程给的数字都准。2.2 边缘通道与形态学闭运算的候选框筛选颜色通道在逆光、夜间、车牌脏污时经常整块丢失所以我一般同时跑一条边缘通道两条结果取并集再做筛选。边缘通道的思路是车牌区域字符密集Sobel 或 Canny 响应强用横向长条的结构元做闭运算能把字符之间的边缘连成一个矩形块而路面、车身这种大面积平滑区域几乎不产生响应。% 灰度化后做 Sobel 边缘横向结构元闭运算连成块 gray rgb2gray(I); bwE edge(gray, sobel, 0.12); bwE imclose(bwE, strel(rectangle, [5 25])); bwE imfill(bwE, holes); bwE bwareaopen(bwE, 400); % 两路掩膜合并交给连通域筛选 cand mask | bwE; cand imclose(cand, strel(rectangle, [5 15])); cand bwareaopen(cand, 600);edge的第三个参数是阈值0.12 是我在 720p 抓拍图上常用的起点噪声大的图往上抬到 0.18纹理弱的图降到 0.08。bwareaopen的 400 是面积下限用来干掉路灯、反光条这类小块响应。两路合并之后再做一次轻量闭运算是为了把颜色通道和边缘通道各自漏掉的一半拼起来。拿到候选掩膜下一步是按几何约束筛框。regionprops的BoundingBox返回[x y w h]直接算宽高比和面积占比stats regionprops(cand, BoundingBox, Area, Extent); boxes cat(1, stats.BoundingBox); areas cat(1, stats.Area); ratio boxes(:,3) ./ boxes(:,4); % 宽高比 ext cat(1, stats.Extent); % 连通域填充率 keep ratio 2.2 ratio 4.8 ... % 车牌宽高比经验区间 areas 800 areas 30000 ...% 面积上下限 ext 0.45; % 太稀疏的框不要 boxes boxes(keep, :);宽高比 2.2 到 4.8 覆盖了单层蓝牌和部分新能源牌的形变区间面积上下限要按你的图像分辨率换算我给的数字对应 1280×720 左右的图。Extent是连通域面积与外接矩形面积之比车牌框里字符和底色填得比较满这个值通常在 0.6 以上而树枝、栏杆这类细长目标填充率很低用它能把误检压下去一截。2.3 定位框外扩、裁剪与尺寸归一筛完之后如果还剩多个候选按面积从大到小排取第一个或者取宽高比最接近 3.14 的那个。真实车牌框经常贴得太紧字符的上下边缘被切掉一两个像素所以裁剪时统一向外扩 5 到 8 个像素再做边界保护。% 取面积最大的候选框向外扩 6 像素后裁剪 [~, idx] max(areas(keep)); b boxes(idx, :); pad 6; x1 max(1, round(b(1)) - pad); y1 max(1, round(b(2)) - pad); x2 min(size(I,2), round(b(1) b(3)) pad); y2 min(size(I,1), round(b(2) b(4)) pad); plate I(y1:y2, x1:x2); % 统一到固定宽度后续分割参数才好写死 plate imresize(plate, [80 240]);外扩 6 像素是个折中扩太少字符边缘缺失会让二值化后的笔画断开扩太多车牌边框和车身会被带进来投影法分割时多出两三个假波峰。统一缩放到 80×240 也不是随便定的它让后面所有分割阈值、结构元尺寸、模板尺寸都变成常量换一张分辨率不同的图不用重调一遍。这一步的代价是引入了插值模糊imresize默认双三次对二值化影响不大但如果你的原图本身就很糊建议改成bilinear减少振铃。到这里定位链路就闭环了HSV 掩膜和边缘掩膜各自出候选合并后按宽高比、面积、填充率筛最后外扩裁剪加缩放。这套参数在我手上的干净抓拍图上召回率能到九成以上剩下的失败基本集中在夜间过曝和车牌严重污损两类那属于另一条技术路线要解决的问题了。3. 字符分割垂直投影为什么会在第二刀翻车3.1 灰度化、去噪与二值化的三个阈值分割的目标是把 80×240 的车牌条切成 7 个字符块省份汉字加 6 位字母数字每个块单独归一化后送进匹配器。这一步最常用的方法是垂直投影字符是亮的、底色是暗的把二值图按列求和字符所在列的和值高字符间隙的和值低找波谷就找到了切分点。前提是二值图得干净。蓝底白字车牌灰度化之后白字灰度在 200 以上蓝底在 80 到 120 之间理论上 Otsu 就能分开。实际翻车最多的是两种情况一是车牌表面有反光白字和反光斑连成一片二是边框没去干净左右两条竖边在投影图上形成两个巨大的假峰把真正的字符峰淹掉。% 灰度化 对比度拉伸 中值滤波压噪 g rgb2gray(plate); g imadjust(g, stretchlim(g, 0.02), []); g medfilt2(g, [3 3]); % Otsu 全局阈值白字为前景 bw imbinarize(g, global); % 去掉贴边的细长连通域多数是车牌边框残留 bw imclearborder(bw); bw bwareaopen(bw, 30);stretchlim的 0.02 是百分位裁剪把最暗和最亮的 2% 像素截掉再做拉伸能明显改善逆光图的对比度。medfilt2用 3×3 窗口窗口再大就把细笔画磨没了。imclearborder专门对付贴边连通域车牌左右边框通常和图像边界相连这一步能清掉大半代价是如果某个字符恰好贴边也会被一起清掉所以裁剪阶段的外扩要留够。注意如果整张图的光照很不均匀比如一半在阴影里一半在阳光下全局 Otsu 会切出半张黑半张白的二值图。这时换成imbinarize(g,adaptive,ForegroundPolarity,light,Sensitivity,0.45)用局部窗口算阈值代价是噪点变多后面要补一次开运算。3.2 垂直投影的波谷判定与宽度过滤二值图干净之后投影就很好做了。按列求和得到一条曲线字符区域的列和值高间隙的列和值接近零。判定切分点不能简单用“和值大于零”因为噪点会让间隙列也有零星响应所以设一个相对阈值最大列和值的 15% 到 25%。% 垂直投影按最大值的比例设分割阈值 proj sum(bw, 1); thr 0.18 * max(proj); isChar proj thr; % 差分找上升沿和下降沿得到每段的起止列 d diff([0 isChar 0]); starts find(d 1); ends find(d -1) - 1; widths ends - starts 1; % 按字符宽度过滤太窄是噪点太宽是两个字粘在一起 valid widths 6 widths 30; starts starts(valid); ends ends(valid);0.18这个系数决定了切分的松紧。调高字符内部的细笔画会被当成间隙切断一个“8”切成两半调低两个相邻字符之间的窄缝被填平变成一块。字符宽度 6 到 30 像素对应 240 宽的车牌条正常单字符宽度在 18 到 26 之间汉字略宽。如果过滤后发现有效段超过 7 个说明有噪点被当成字符按宽度从大到小取前 7 个少于 7 个说明有粘连得回头检查二值化。粘连是投影法最典型的翻车点。两个字符中间那列如果因为模糊或污渍导致和值没有降到阈值以下就会被合并成一段宽度直接翻倍。工程上的补救办法有两种一是对超宽段做二次投影把阈值再抬高 10% 重切二是对超宽段直接按宽度均分虽然粗暴但对固定字体的车牌意外地有效。% 对超宽段做二次切分抬高阈值重投影失败则均分 for k 1:numel(starts) w ends(k) - starts(k) 1; if w 30 sub bw(:, starts(k):ends(k)); p2 sum(sub, 1); t2 0.30 * max(p2); cut find(p2 t2, 1, first); if isempty(cut) cut round(w / 2); % 找不到谷底就均分 end % 用 cut 把这一段拆成两段写回 starts/ends end end这段二次切分的逻辑不复杂重点在于“先抬阈值找谷底找不到再均分”这个兜底顺序。抬阈值能把大部分粘连切开均分只在前者失败时兜底不至于把本来正常的一段硬切成两半。3.3 倾斜校正与字符归一化到 40×20车牌在抓拍图里几乎不可能完全水平倾斜 3 到 5 度很常见。倾斜对定位影响不大对分割是致命的投影的波谷会随着倾斜变宽变浅本来清晰的一条缝变成一片缓坡阈值法切不准位置字符块里会带上邻居的半条笔画。校正在二值图上做用 Radon 变换扫角度。把二值图在 -8 到 8 度之间做投影投影能量最集中的角度就是车牌长边的垂直方向据此反推倾斜角。% 在 ±8 度内做 Radon 扫描取能量最集中的角度 theta -8:0.25:8; R radon(bw, theta); energy sum(R .^ 2, 1); [~, mi] max(energy); tilt theta(mi); % 反向旋转校正crop 保证输出尺寸不变 if abs(tilt) 0.5 bw imrotate(bw, tilt, bilinear, crop); end这里的正负号跟图像坐标系有关第一次用务必拿一张已知倾斜方向的图校准一次别直接照抄。crop参数保证旋转后尺寸不变避免后续按固定坐标裁剪时越界。校正完再跑一遍 3.2 的投影切分准确率会明显不一样这是我自己踩过坑之后固定下来的顺序先校正再投影不要颠倒。切出来的每个字符块尺寸不一送进模板匹配之前必须归一化。统一到 40 高、20 宽用双三次插值同时做一次居中把字符的外接矩形缩放到刚好填满 36×18再贴到 40×20 的画布中央四周留 2 像素白边。% 单个字符块归一化紧致裁剪后缩放并居中到 40x20 function ch norm_char(bwImg) [r, c] find(bwImg); if isempty(r), ch false(40, 20); return; end crop bwImg(min(r):max(r), min(c):max(c)); crop imresize(crop, [36 18]); ch false(40, 20); ch(3:38, 2:19) crop; end居中这一步看起来多余实际上直接决定了匹配分数可不可比。不居中的话同一个字符在不同图里可能偏左偏右corr2算出来的相关系数会凭空掉一截阈值就没法统一设了。缩放比例用[36 18]而不是直接[40 20]是为了留边防止旋转或插值把笔画推到画布外面被截断。4. 模板库与匹配打分corr2、SSD 和多模板投票怎么选4.1 模板库的字符集、样本数和切割规范模板匹配的上限由模板库决定这句话怎么强调都不过分。字符集先定清楚数字 0 到 9 共 10 类字母去掉 I 和 O容易和 1、0 混淆共 24 类两者合计 34 类省份简称汉字单独一套31 类。如果项目只要求识别后 6 位汉字那套可以先不做能省掉一大半工作量因为汉字笔画复杂模板匹配的准确率天然比字母数字低一截。每类准备多少张模板我的经验是每个字符 15 到 30 张覆盖不同光照、不同字体粗细、轻微形变和 ±3 度的残余倾斜。来源就是你自己场景里的真实车牌切割、归一化到 40×20人工标注文件名。不要拿电脑字体渲染出来的图当模板渲染图和实拍图在笔画边缘的模糊程度、反光分布上差得太远用渲染模板去匹配实拍字符分数分布会整体偏移一大截。模板文件命名要能直接解析出类别比如tpl_A_003.png加载时按类别分组存进 cell 数组% 按文件名前缀加载模板分组成 cellclasses{k} 存第 k 类的所有模板 files dir(fullfile(templates, *.png)); labels strings(numel(files), 1); for k 1:numel(files) [~, name] fileparts(files(k).name); labels(k) extractBetween(name, tpl_, _); end uniq unique(labels); classes cell(numel(uniq), 1); for k 1:numel(uniq) idx find(labels uniq(k)); classes{k} cellfun((f) imread(fullfile(templates, f)), ... {files(idx).name}, UniformOutput, false); end存成 cell 的嵌套结构而不是三维数组是因为每类模板数量不一样三维数组得补齐浪费内存还容易在索引时出错。加载完之后建议打印一下每类的模板数少于 10 张的类别要补样本否则那一类的匹配分数会明显偏低形成系统性误判。4.2 归一化互相关与 SSD 的取舍单个字符和单张模板都是 40×20 的二值图比对方式无非两类逐像素差值的平方和SSD和零均值归一化相关系数corr2。两者的差别在于对亮度变化的敏感度。SSD 直接算对应像素差二值图下等价于汉明距离对笔画粗细、边缘偏移非常敏感。字符稍微粗一点SSD 就涨一大截所以它适合模板和待测样本来自同一批设备、同一套预处理参数的场景。corr2先各自减去均值再算相关系数对整体亮度偏移不敏感笔画粗细变化的影响也被摊薄代价是相似字符之间的区分度会下降比如“8”和“B”的相关系数经常只差 0.02。% 单个字符与某一类所有模板逐一比对返回该类的最高分 function s score_class(ch, tpls, mode) s -inf; for k 1:numel(tpls) t logical(tpls{k}); if ~isequal(size(ch), size(t)) t imresize(t, size(ch)); % 尺寸兜底正常不该走到这 end switch mode case corr v corr2(double(ch), double(t)); case ssd v -sum((double(ch(:)) - double(t(:))).^2); % 取负越大越好 end s max(s, v); end endmode参数留着切换实际项目里我会先用corr跑一遍看混淆矩阵如果相似字符对8/B、0/D、5/S、2/Z的误判占比超过两成再切到ssd对比选整体准确率高的那个。尺寸兜底那行是防御性代码正常流程里所有模板和字符都归一化到 40×20走不到但模板库手工维护难免混进一张尺寸不对的图corr2遇到尺寸不一致会直接报错加一行兜底能省掉排查时间。4.3 多模板打分、Top-K 候选与拒识阈值一类多模板的合并策略很简单取最大值。同一个字符在不同光照下的样子差异很大但只要模板库覆盖到了总有一张能对上取最大就是把“最像的那张”作为该类的得分。34 类各算一个最高分排序取第一就是识别结果。光有结果不够还得有置信度。我一般同时输出 Top-3 和第一、第二名的分差% 对所有类别打分排序输出 Top-3 和首两名分差 scores zeros(numel(classes), 1); for k 1:numel(classes) scores(k) score_class(ch, classes{k}, corr); end [sorted, order] sort(scores, descend); top3 order(1:3); margin sorted(1) - sorted(2); % 分差越小越可疑margin是这套流程里最有用的一个数。第一名和第二名分差小于 0.05 时基本可以判定为相似字符混淆这时与其硬给一个结果不如标记为“待复核”交给人工或者第二级特征笔画数、孔洞数再判一次。拒识阈值定在多少合适拿你的验证集跑一遍把分差和是否正确的关系画出来找一个既能把错误挡掉、又不会拒掉太多正确样本的点通常落在 0.04 到 0.08 之间。多模板带来的一个副作用是计算量。34 类、每类 20 张模板一个字符要算 680 次corr27 个字符就是 4760 次corr2内部是双层循环MATLAB 里跑起来并不快。优化办法是把模板展平成矩阵一次性做矩阵乘法算相关系数能把耗时压掉一个数量级但那是后话先跑通再优化别一上来就为了性能把代码写得没法调试。5. 排查模板匹配车牌识别最常见的五个翻车点5.1 定位与二值化阶段的两个坑第一个坑夜间和逆光图整块定位丢失。现象是regionprops筛完之后boxes为空代码在取最大值那行报索引越界。原因是 HSV 阈值里的V 0.20和S 0.35在过曝图里同时失效——补光灯把蓝底照得发白S 掉到 0.1 以下颜色通道整个空掉边缘通道那边因为过曝字符和底色的梯度也被压平Sobel 响应弱到过不了阈值。解决办法不是把阈值往下调那样误检会爆炸而是给边缘通道单独降门槛把edge的阈值从 0.12 降到 0.06同时把闭运算结构元从[5 25]放大到[7 31]靠形态学把断掉的边缘重新连起来。更稳的做法是对图像先做一次imadjust或 CLAHE 局部增强再进边缘通道但会增加一道预处理看你的实时性要求。第二个坑二值化后车牌边框残留投影多出两个假峰。现象是分割出来的有效段有 9 到 10 个左右两边各多一块窄条宽度在 6 到 10 像素之间刚好卡在宽度过滤的下限附近没被筛掉。原因是imclearborder只能清掉与图像边界相连的连通域车牌裁剪时外扩了 6 像素边框被包在图像内部imclearborder管不着。解决分两步一是在二值化之后加一次形态学开运算结构元用strel(rectangle,[2 2])把细边框磨掉注意窗口不能大大了字符笔画也断二是在宽度过滤里把下限从 6 提到 10边框条的宽度通常不超过 8正常字符最窄也有 12 以上这个区分度是够的。提示这两个坑的共同点是“参数在干净图上没问题换一批图就崩”。所以调参时一定要拿至少三类图白天、夜间、逆光各十张一起跑只在单类图上调到最优上线必翻车。5.2 分割与匹配阶段的三个坑第三个坑corr2报“矩阵尺寸不一致”。现象是跑批量测试时中途崩掉报错指向corr2那一行。原因是有张模板图的尺寸不是 40×20——手工切割模板时imresize的目标尺寸写错或者某张图保存时被别的工具重新编码过。这类问题最烦的地方是它只在特定图片上触发跑前几十张都正常很容易误以为是数据问题。解决是在加载模板时加一道断言尺寸不对直接打印文件名并跳过而不是等到匹配阶段才崩% 加载时校验尺寸不合格的模板打印文件名后剔除 for k 1:numel(classes) ok cellfun((t) isequal(size(t), [40 20]), classes{k}); if any(~ok) fprintf(尺寸异常模板第 %d 类共 %d 张\n, k, sum(~ok)); classes{k} classes{k}(ok); end end第四个坑相似字符系统性混淆8 认成 B、0 认成 D。现象是混淆矩阵里这两对占错误总数的六成以上而且分差普遍很小。原因是二值化之后字母和数字的拓扑结构高度相似corr2又是全局相关区分不了局部差异。解决办法有两个层次轻量的是加结构特征做二次判决统计字符的孔洞数bweuler或regionprops的EulerNumber和笔画端点8 有两个孔洞、B 也是两个这一招对 8/B 无效但对 0/D 有效0 一个孔洞、D 也是一个还是无效真正有效的是扩模板库专门针对易混字符补样本把不同字体、不同粗细的 8 和 B 都收进去让类内方差覆盖住类间差异同时把拒识阈值调紧分差小于 0.06 的直接标待复核。第五个坑倾斜导致字符切分整体错位一格。现象是识别结果整体右移或左移一位比如真实是“X12345”输出成“12345X”或者“XX1234”。原因是没做倾斜校正或者校正角度算反了符号投影波谷位置整体偏移第一个字符块里混进了边框最后一个字符被挤出有效宽度。判断方法很直接把分割结果的可视化图打出来看如果每个字符块里都带着邻居的半条边就是错位。解决就是回到 3.3 的 Radon 校正并且用一张已知倾斜 3 度的合成图验证符号方向别靠猜。6. 把“看着还行”变成可测量验证集、混淆矩阵与拒识阈值调通流程之后最危险的状态是“随手拿几张图跑看起来都对”。模板匹配的参数多阈值之间互相耦合凭肉眼判断很容易把过拟合当成调好了。我现在的习惯是先固定一个验证集再动手调参200 到 300 张图覆盖白天、夜间、逆光、倾斜、污损五类每张人工标注车牌框位置和真实字符序列存成 CSV。指标分四级统计缺一级都会漏掉问题指标计算方式我一般能到的水平低于这个值先查什么定位命中率预测框与标注框 IoU 0.5 记为命中88% 到 94%夜间样本的颜色阈值分割正确率切出 7 段且边界与标注偏差 3 像素85% 到 92%倾斜校正和宽度过滤单字符准确率逐字符比对含汉字92% 到 97%相似字符的模板覆盖整牌准确率7 位全对才算对75% 到 88%前三级里最弱的那一环整牌准确率永远明显低于单字符准确率这是乘法效应7 位里每位 95%整牌就只有 70%。所以优化的时候不要盯着单字符准确率要看整牌并且优先修最弱的那一环。定位命中率不到 90% 时去调匹配阈值纯属白费力气。混淆矩阵用confusionmat直接算重点看两件事对角线以外最大的那格是哪两个类在混以及被拒识的样本里正确结果排第二的比例。前者决定要不要补模板后者决定拒识阈值是松了还是紧了。% 统计混淆矩阵与拒识率gt 和 pred 都是 categorical cm confusionmat(gt, pred); acc sum(diag(cm)) / sum(cm(:)); % 按分差阈值扫描拒识率与错误率的关系 for t 0.02:0.01:0.10 rejected margin t; errRate sum(~rejected ~correct) / sum(~rejected); rejRate sum(rejected) / numel(rejected); fprintf(阈值 %.2f拒识率 %.3f剩余错误率 %.3f\n, t, rejRate, errRate); end这段扫描跑完你会看到一条典型的权衡曲线阈值从 0.02 往上抬拒识率线性涨剩余错误率快速下降然后趋缓。拐点通常在 0.05 到 0.07 之间取拐点稍右一点的位置既能把大部分相似字符混淆挡下来又不会拒掉太多正常样本。这个阈值跟你的模板库质量强相关模板补得越全可以放得越松。最后说一个我自己交过学费的地方。早期做这套东西的时候我把模板库和测试集从同一批图里切准确率刷到 96%换一批新图直接掉到 71%。后来固定了“模板图绝不进测试集”的规矩哪怕某一类模板不够也去补新图而不是从测试集里挪。模板匹配这套方法本身不复杂难的是把数据边界守干净。希望帮到你。本文还有配套的精品资源点击获取