简介:这是一份基于Python与OpenCV的硬币检测与识别项目资源,面向计算机视觉初学者和OpenCV实战学习者,可解决照片中硬币的自动计数与总价值估算问题,适合用来入门图像处理或完成课程设计。压缩包共13个文件,由12张jpg图像和1个py脚本组成,整体约7.39MB;其中图像部分包括原始照片、模板图像、测试图像和检测结果图,py脚本则是完整的检测识别程序,便于直接运行和对照调试。目前已有2242人学习下载,实践参考价值较高,尤其适合需要在实验中快速验证算法的开发者和学生。通过学习,读者可以掌握图像预处理、边缘检测、圆形目标定位、特征匹配与小物体计数等常用技术路线,理解从图像输入到价值判断的完整流程;也能基于这套代码进一步扩展,用于其他圆形物体识别场景。 先聊点实际的。我当初做这个硬币检测与识别项目,起因是帮朋友写一个"自动数零钱"的小工具——就是拍一张照片,程序自己告诉我里面有多少钱。听起来挺简单对吧?不就是找圆、看大小、算面值嘛。真动手之后才发现,"找圆"这一步就够喝一壶的:反光、阴影、硬币挨得太近、背景乱七八糟,全是坑。而"看大小算面值",还得先解决像素和真实尺寸之间怎么换算的问题。这篇文章就把我完整跑通的思路、代码和踩坑记录都摊开讲,给正在做 python-opencv 硬币检测识别的同学一个可以直接参考的路径。
先说清楚一件事:检测和识别是两个环节。检测负责定位,告诉你图像里第几个位置有一枚硬币,半径是多少像素;识别负责分类,告诉你这枚硬币是1元、5角还是1角。两个环节的错误是会叠加的:圆没找准,后面面值必错;圆找准了但分类逻辑太糙,照样数错钱。所以每一步都得稳。
1. 先拆开"找硬币"和"认面值":这个项目的第一道坎
1.1 检测和识别是两件事
很多人一上来就搜"硬币识别",然后指望一个函数把结果全吐出来,这其实是把两个问题搅在一起了。
检测环节说白了就是目标定位。OpenCV 里典型的做法有两种:一是用 HoughCircles 做圆形检测,二是用 findContours 找轮廓再拟合圆。我不太建议一上来就上深度学习,原因很简单:硬币是高度规矩的圆形物体,传统图像处理在受控环境下完全够用,而且可解释性强,出了问题你能看到是边缘断了还是阈值错了,深度模型给不了这种可调试性。
识别环节则是另一套逻辑。硬币的面值判断依据有三个维度,按可靠程度排序:物理尺寸、颜色、表面图案/文字。物理尺寸最可靠,因为人民币硬币的直径是官方固定的,只要知道像素和真实尺寸的换算比例,量一下半径就能确定面值范围。颜色是第二可靠的维度,5角是金黄色,1元和大部分1角是银白色。最不可靠的是图案识别——硬币表面磨损、反光、角度变化都会严重影响模板匹配或OCR的效果,所以我把图案识别放在了最后的扩展方案里,而不是主方案。
1.2 识别依据:尺寸、颜色、图案的优先级
拿我国目前常见的硬币来说,直径参数大致是:
| 面值 | 直径 | 材质颜色 | 备注 |
|---|---|---|---|
| 1元 | 25.0mm | 钢芯镀镍,银白色 | 新版硬币 |
| 5角 | 20.5mm | 钢芯镀铜合金,金黄色 | 新版硬币 |
| 1角 | 19.0mm | 不锈钢,银白色 | 2019年新版 |
注意这里有个容易踩的坑:1角和5角的直径只差1.5mm,在普通分辨率图像里可能只差十个像素左右,单纯靠半径阈值很容易混淆,所以我后面增加了一道颜色校验逻辑,专门区分这两种面值。
把识别依据排个优先级:先看尺寸,尺寸落在模糊区间的再用颜色兜底。图案文字识别这种重方案,只有在硬币版本特别多、或者必须识别年份版别的需求出现时,才值得上。
1.3 传统CV还是深度学习?我为什么选了前者
我当时考虑过两套方案:一套是本文讲的传统方法,另一套是用 YOLO 之类的目标检测模型直接检测并分类硬币。
选传统方法的核心原因是工程量匹配。我需要处理的场景非常固定:硬币平铺在深色底板上,相机固定在正上方固定高度拍摄。在这个前提下,硬币就是一个标准圆,尺寸是已知的,颜色是明确的,传统CV可以做到又快又稳。深度学习的优势在复杂场景——硬币随意堆叠、任意姿态、光照剧烈变化、背景杂乱——那种场景下 YOLO 的鲁棒性确实碾压传统方法。但代价是:你需要标注几百张图片、训练模型、调参数,还要面对新的误检方式。对一个"数零钱"的需求来说,性价比太低了。
如果你的场景不再满足"平铺、正拍、背景可控"这几个条件,别硬用传统方法,换检测模型是更明智的选择。这是后话,我放到最后一节展开。
2. 拍摄环境没你想的那么随便:背景、光源和镜头位置
2.1 环境依赖安装
这部分最简单,直接在 Python 环境里装 opencv-python 和 numpy 就行:
pip install opencv-python numpy如果需要读取中文路径下的图片,建议加装 opencv-contrib-python 并配合 imdecode 读取,这个坑我后面细说。版本方面我用的是 OpenCV 4.x,API 和 3.x 差别不大,老代码基本能直接跑。
2.2 用底板和光源把"变量"锁死
我第一版代码是在办公桌上随手拍的,结果硬币和木质桌面的纹理混在一起,Canny 边缘检测出来的全是木纹线,Hough 找圆找出来一堆乱七八糟的结果。后来我找了个深色的纯色鼠标垫当底板,误检率立刻大幅下降。
这里有个原则:图像处理项目里,能通过控制拍摄环境解决的问题,不要留给算法硬扛。底板的颜色最好和硬币颜色有明显区分。深色底配银色硬币效果最好,因为银白色硬币在暗背景下边缘对比度极高。如果你要重点处理金色5角,深蓝或黑色的背景也比浅色背景更合适。
光源方面,均匀光比强光更重要。我当时用了一盏普通台灯从侧上方照明,结果每枚硬币靠近光源的一半亮、另一半有阴影,Canny 只能检出半圈边缘,圆检测全都偏了。后来我把光源改成漫反射环境光(散射光均匀照明),或者在拍摄时尽量让房间整体明亮、避免单一强光源直射,效果就好了很多。
2.3 相机镜头要垂直于桌面
镜头的拍摄角度会影响硬币成像形状。硬币本身是圆形的,但如果相机没有正对桌面,圆会变成椭圆,HoughCircles 的半径检测就会飘,面值判断自然出错。
我的建议是:镜头光轴尽量垂直于桌面,固定高度拍摄。如果实在做不到完全垂直,那就保持固定角度,然后用一个已知尺寸的标定物做换算——标定物能帮你直接把像素和实际毫米数的比例定死,拍摄角度造成的系统误差在换算后会稳定在一个固定范围内,反而不影响分类。
3. 从噪声到干净边缘:预处理与候选圆提取
3.1 灰度化、滤波与光照均衡
预处理的目标很纯粹:让硬币的边缘尽量干净地被检测出来,同时让背景纹理的干扰降到最低。
第一步是把 BGR 图像转成灰度图。第二步是滤波。我实测下来,高斯滤波核大小取 (9, 9),sigma 取 2,对硬币这类大目标来说去噪效果和边缘保留之间的平衡最好。中值滤波也可以,它对椒盐噪声更有效,但边缘会偏钝一点,看你的图像情况。
如果你拍摄的光照不均匀,可以加一步光照均衡处理。当时我的照片左侧亮右侧暗,硬币边缘在暗侧几乎断了。解决办法是用形态学的黑帽/顶帽变换分离出光照分量,或者直接对灰度图做高斯模糊后与原图相减。OpenCV 里最简单粗暴的写法:
blurred = cv2.GaussianBlur(gray, (31, 31), 0) equalized = cv2.subtract(gray, blurred)这行代码的效果是:把缓慢变化的光照背景去掉,只保留局部变化的高频信息,硬币边缘的对比度会被拉回来。很实用,尤其是在环境光不受控的场合。
3.2 Canny边缘检测的参数门道
Canny 的阈值是新手最容易卡住的地方。它有两个阈值:高阈值和低阈值。高于高阈值的像素一定被当成边缘,低于低阈值的肯定丢弃,介于两者之间的,只有与强边缘相连才会被保留。
我的经验是,高阈值和低阈值的比例放在 1:2 到 1:3 之间比较合适。比如高阈值 100、低阈值 50,或者 150、60。硬币场景下,我常用(100, 200)这个组合,边缘干净、断点少。阈值设太低,木纹、阴影边缘全进来,Hough 投票就乱了;阈值设太高,硬币边缘断成碎片,圆检测可能直接失败。参数的直觉不是"调大或调小",而是想清楚你当前图像的问题是哪一种,再决定往哪边调。
3.3 HoughCircles vs 轮廓拟合
这是硬币定位的核心环节,我两种方法都写了,因为实际使用中它们互补。
方案一:HoughCircles
circles = cv2.HoughCircles( gray_gaussian, cv2.HOUGH_GRADIENT, dp=1.2, minDist=50, param1=100, param2=60, minRadius=20, maxRadius=60 )HoughCircles 的核心思想是:每个边缘点都可以在所有候选圆心位置投票,投票数大于阈值的圆心和半径组合才会被保留。所以:
dp=1.2:累加器分辨率,一般取 1~2 即可,越大越快但可能丢小圆。minDist:两个圆心之间的最小距离。如果比硬币直径的像素值还小,同一枚硬币会被检出好几个重叠圆。这个参数是我踩坑最多的,后面细讲。param1:内部 Canny 的高阈值。注意 HoughCircles 内部会自己做一次 Canny,所以如果你在外部已经做过预处理,这里的高阈值不用太小,我的经验是 100 左右起步。param2:累加器投票阈值。越小检出的圆越多,误检也越多;越大越严格,但可能漏掉边缘不太完美的硬币。60 到 80 是比较常用的区间。minRadius/maxRadius:候选圆的半径范围。一定要尽量量准。我在代码里加了一个预处理步骤:先用轮廓分析预估硬币的像素半径,再把这个范围喂给 HoughCircles,误检率直接下降一大截。
方案二:轮廓分析 + 圆形度校验
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: area = cv2.contourArea(cnt) if area < 500: continue perimeter = cv2.arcLength(cnt, True) circularity = 4 * np.pi * area / (perimeter * perimeter) if circularity < 0.8: continue (x, y), radius = cv2.minEnclosingCircle(cnt)轮廓法的核心是先用 OTSU 自动阈值把图像转成二值图,然后找外轮廓,用圆形度公式过滤掉非圆形状。圆形度的定义是4π × 面积 / 周长²,完美圆的圆形度是 1,一般大于 0.8 的都可以认为接近圆。
这两个方案怎么选?如果硬币之间离得比较开、图像干净,HoughCircles 效率高;如果硬币有轻微遮挡、边缘有缺失,或者背景中有大量非圆物体,轮廓法更稳。我最终的项目里是两套都跑,Hough 结果优先,轮廓法做兜底,两个结果用圆心坐标合并去重。
4. 用一枚1元硬币标定像素比,再把半径换算成面值
4.1 标定:像素是怎么变成毫米的
要判断面值,光知道半径的像素值没用,因为照片的像素量和拍摄距离直接相关。我一开始犯过这个错:直接在测试图上量出 1 元硬币半径大约 30 像素,就拿"半径 30 以上是 1 元"去套所有照片,换一个拍摄距离全变了。
正确做法是做一个标定:在拍摄画面里放一枚已知尺寸的硬币(我用 1 元,直径 25mm),检测到它的像素直径后,算出比例:
scale = ref_diameter_px / 25.0 # 单位:像素/毫米把每枚硬币的像素直径除以 scale,就得到真实直径毫米数。后面只要拍摄条件不变,这个比例就不用重新算。
标定有两种思路:第一种是把参考硬币放在画面内,自动检测并计算 scale;第二种是拍一张空白背景带标定物的图,预先测好 scale 写死在配置里。我用的第二种——因为我的相机是固定安装的,拍一次标定图就够了,把 scale 存成配置文件,后续所有图片共用同一个比例,逻辑更简单。如果你的拍摄距离每次都会变,那就必须走第一种,让标定逻辑随图片走。
4.2 直径阈值表与分类逻辑
拿到毫米直径后,分类逻辑就清晰了。我实测的直径分布大概是:
| 真实面值 | 实测直径范围(mm) | 中间阈值 |
|---|---|---|
| 1角 | 18.5 ~ 19.5 | 19.8 |
| 5角 | 20.0 ~ 21.0 | 21.5 |
| 1元 | 24.5 ~ 25.5 | 23.0 |
注意一个问题:1角(19mm)和 5角(20.5mm)只差 1.5mm,如果标定稍微偏一点,或者硬币因为拍摄角度有一点形变,这两个就会互相混淆。所以我的逻辑里做了一个双阈值区间设计:
- 直径 > 23mm → 判为 1元
- 直径在 21.0 ~ 23mm 之间 → 判为 5角
- 直径在 19.8 ~ 21.0mm 之间 → 候选:5角/1角,交给颜色判断
- 直径 < 19.8mm → 判为 1角
这个设计比单纯一个阈值稳得多。落在中间模糊带的硬币,再去提取它的颜色特征做二次判断。
4.3 用颜色信息兜底:金色占比判断
5角硬币是金黄色(钢芯镀铜合金),1角硬币是银白色(不锈钢),在 HSV 空间里差异明显。我之前在 BGR 空间直接判断颜色吃了不少苦头,因为光照一变,金色在 BGR 三通道的比值就乱了。换成 HSV 空间后,用色调 H 通道就能轻松区分。
判断逻辑是:把检测到的圆区域裁剪出来,转 HSV 空间,统计 H 值在 10~35 之间、且饱和度 S 比较高(大于 60)的像素占比。如果金色像素在圆区域内占比超过 10%,就判为 5角;否则判为 1角。
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) mask_gold = cv2.inRange(hsv, (10, 60, 60), (35, 255, 255)) gold_ratio = cv2.countNonZero(mask_gold) / (np.pi * radius * radius)这个逻辑在大多数室内光线下都稳定。唯一的坑是硬币反光会产生高光白斑,但白斑的饱和度低,不会被算进金色像素里,所以实际影响不大。反过来,如果环境光偏暖,银白色硬币也可能被照出一点淡金色,所以我只把这个判断放在直径模糊带,不作为第一判断依据——这是不少实现容易搞错的地方:把颜色当成主判断,然后被一个偏黄的灯光坑到怀疑人生。
5. 可直接复用的完整代码:读图、找圆、分类、算总额
下面是我最终落地版本的简化代码,保留了完整的流程图:预处理、候选圆提取、圆形度校验、标定、面值分类、总额累加。你可以直接抄去跑。
import cv2 import numpy as np # ---------- 全局配置 ---------- SCALE_FILE = "scale.txt" # 标定结果文件,单位:像素/毫米 REF_DIAMETER_MM = 25.0 # 标定硬币直径:1元硬币25mm def load_scale(): with open(SCALE_FILE, "r") as f: return float(f.read().strip()) def save_scale(scale): with open(SCALE_FILE, "w") as f: f.write(str(scale)) def read_image(path): # 用imdecode读取,支持中文路径 stream = np.fromfile(path, dtype=np.uint8) return cv2.imdecode(stream, cv2.IMREAD_COLOR) def detect_coins(image, gray, scale): # 方案一:HoughCircles 检测 circles = None if scale is not None: min_r = int(19.0 * scale * 0.85) max_r = int(25.0 * scale * 1.15) circles = cv2.HoughCircles( gray, cv2.HOUGH_GRADIENT, dp=1.2, minDist=int(25.0 * scale * 1.2), param1=100, param2=60, minRadius=min_r, maxRadius=max_r ) detections = [] if circles is not None: circles = np.round(circles[0]).astype("int") for (x, y, r) in circles: detections.append((x, y, r, "hough")) # 方案二:轮廓分析 + 圆形度过滤 blurred = cv2.GaussianBlur(gray, (9, 9), 2) _, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: area = cv2.contourArea(cnt) if area < 1000: continue perimeter = cv2.arcLength(cnt, True) if perimeter <= 0: continue circularity = 4 * np.pi * area / (perimeter * perimeter) if circularity < 0.8: continue (x, y), r = cv2.minEnclosingCircle(cnt) detections.append((int(x), int(y), int(r), "contour")) # 去重:合并两种方案检测到的同一个圆 result = [] for d in detections: x, y, r, source = d duplicate = False for rx, ry, rr, rs in result: if (x - rx) ** 2 + (y - ry) ** 2 < (max(r, rr) * 0.5) ** 2: duplicate = True break if not duplicate: result.append(d) return result def classify_coin(img, x, y, r, scale): # 计算直径(像素) diameter_px = 2 * r diameter_mm = diameter_px / scale # 裁剪圆区域用于颜色判断 mask = np.zeros(img.shape[:2], dtype=np.uint8) cv2.circle(mask, (x, y), r, 255, -1) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) gold_mask = cv2.inRange(hsv, (10, 60, 60), (35, 255, 255)) gold_ratio = cv2.countNonZero(cv2.bitwise_and(gold_mask, gold_mask, mask=mask)) / (np.pi * r * r) # 面值判断:直径优先,颜色兜底 if diameter_mm >= 23.0: return 1.0 elif diameter_mm >= 21.0: return 0.5 elif diameter_mm >= 19.8: return 0.5 if gold_ratio > 0.1 else 0.1 else: return 0.1 def main(): img = read_image("coins.jpg") if img is None: print("图片读取失败") return gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 标定流程:第一次运行时用1元硬币标定 scale = None try: scale = load_scale() except FileNotFoundError: print("未找到标定文件,请在画面正中放置一枚1元硬币,3秒后自动标定...") cv2.imshow("calibration", img) cv2.waitKey(3000) # 这里简化处理:手动用Hough检测画面中1元硬币直径 # 实际场景可以增加人工确认逻辑 ref_circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp=1.2, minDist=50, param1=100, param2=60, minRadius=30, maxRadius=80) if ref_circles is not None: _, _, ref_r = np.round(ref_circles[0][0]).astype("int") scale = (2 * ref_r) / REF_DIAMETER_MM save_scale(scale) print(f"标定完成,scale={scale:.3f} 像素/毫米") else: print("标定失败:未检测到参考硬币") return coins = detect_coins(img, gray, scale) total = 0.0 for (x, y, r, source) in coins: value = classify_coin(img, x, y, r, scale) total += value label = {1.0: "1元", 0.5: "5角", 0.1: "1角"}[value] cv2.circle(img, (x, y), r, (0, 255, 0), 2) cv2.putText(img, f"{label}", (x - 20, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) print(f"检测到 {len(coins)} 枚硬币,总金额:{total:.1f} 元") cv2.imshow("result", img) cv2.waitKey(0) if __name__ == "__main__": main()代码里的detect_coins同时跑两种检测方案,再用去重逻辑合并,这样 Hough 的效率和轮廓法的容错性都能兼顾。分类逻辑就是我上面说的双阈值加颜色兜底。read_image用 imdecode 是为了兼容中文路径——很多同学在 Windows 上图片路径带中文,直接用 cv2.imread 会返回 None,这个问题排查起来非常隐蔽。
6. 我踩过的四个坑:重复圆、断边、误检与面值混淆
6.1 同一枚硬币被重复检测出多个圆
这个问题几乎每个用 HoughCircles 的人都会遇到。表现是:一枚硬币上叠着两三个半径相近的圆,圆心稍微偏移几像素。原因是minDist设得太小了,小于硬币的实际直径像素。
排查方法很简单:把检测到的所有圆都画出来看一眼。修复方法是把minDist调到硬币直径像素的 1.2~1.5 倍。如果你不确定硬币直径像素是多少,先跑一次轮廓分析估算一个平均半径,再去设 minDist。我代码里用int(25.0 * scale * 1.2)就是为了让这个参数自动跟着标定结果走,省得每次换拍摄距离都要重调。
6.2 边缘断成两截导致圆检测失败
硬币迎光面和背光面的边缘灰度差异很大,Canny 只会把对比度够高的部分判成边缘,于是出现半圆边缘。Hough 在这种输入下会漏检或者检出一个偏小的圆。
我最终的修复方案是组合拳:首先用高斯模糊去掉细小噪声,然后用顶帽变换/减背景光照的做法拉平光照,最后把 Canny 的阈值从 (50, 150) 调到 (100, 200)——提高低阈值会减少微小边缘的干扰,让主要边缘更突出。如果你发现硬币边缘本身太弱,调高 Canny 低阈值反而会断得更厉害,这时先检查光照是不是要修,而不是继续加滤波。
6.3 背景纹理被误检成圆
办公室桌面、报纸、木纹板——这些表面都有大量类圆纹理,Hough 会把它们当成硬币。我的解决顺序是:
- 换深色纯色底板,从源头消灭背景纹理。
- 用圆形度过滤,非圆轮廓直接丢弃。
- 限制候选圆半径范围,木纹里那些半圆纹理的半径往往和真实硬币半径差很多,一限制就过滤掉了。
这三步做完,误检率降到了几乎为零。核心思路是:你先用物理知识把搜索空间缩到最小,剩下的交给算法。
6.4 5角和1角直径相近,分类一直在边缘横跳
这个问题在前期最折磨人。1角直径 19mm,5角直径 20.5mm,差距本来就小;如果标定稍有偏差,阈值 19.8mm 附近的硬币就会反复横跳。我最后的处理就是前面说的:设置一个 19.8~21.0mm 的模糊区间,区间内的硬币用金色像素占比来判断。金色占比超过 10% 判 5角,否则判 1角。
在自然室内光下这套逻辑很稳。有一次在暖黄灯光下,银白色的 1 角被照出了明显金色调,金色占比超过了 10%,被误判成 5角。后来我加了一个条件:检测金色区域内像素的平均饱和度是否够高——反光引起的"假金"饱和度普通偏低,而 5角本身的合金颜色饱和度明显更高。两种"金色"从肉眼上你看得出来差别,在 HSV 的 S 通道上更是清清楚楚。
7. 方案升级思路:如果场景变复杂,还是得上模型
我前面反复强调传统方法好用,前提是场景受限。如果你的实际需求变成"一堆硬币随意堆叠在一起""从桌面上杂乱环境下直接识别""需要识别出硬币的年份版别",传统方案的短板就会暴露得很明显。
- 堆叠硬币:Hough 找不到完整圆,轮廓法也会被粘连搞崩溃,这时候需要分水岭算法做粘连分割,或者直接用目标检测模型。
- 复杂背景:圆检测会把大量类圆物体当成候选,过滤逻辑越写越复杂,误差不可控。
- 区分年份版别:尺寸和颜色完全不够用,必须识别正反面的文字图案。硬币表面磨损严重,传统模板匹配基本不可靠,需要用小数据集微调一个 CNN 分类器,或者用现成的 OCR 模型识别图案里的数字。
我的建议是,先用本文这套方法把数据收集和场景规范做起来——控制背景、固定机位、准备标定物,这些工作无论你最后用不用深度学习都是必须的。等你积累了足够多的真实图片,再训练一个轻量目标检测模型去替换传统检测环节,识别的部分用裁剪出来的硬币图像微调分类模型。这条路走起来平滑很多,因为你已经对问题有了足够深的理解,知道模型在哪一步帮到你、哪一步反而会引入新的麻烦。
最后再分享一个我个人的经验:做这类图像处理项目,可视化中间结果比调算法参数更节省时间。我当时把灰度图、光照均衡图、Canny 边缘图、Hough 结果图、轮廓二值图全都用 imshow 弹出来看,一眼就能定位是预处理的问题、检测的问题还是分类阈值的问题。如果只看最终结果调参,你永远在赌运气。另一个小技巧是,标定文件单独存一份,拍摄距离不变就不需要重新标定,但每次跑批量图片前,都先在结果图上随便画一两个圆看看半径是否合理——标定错了,后面全是白算。
本文还有配套的精品资源,点击获取