别再瞎调相机了!用 C# + OpenCV 搞定单目视觉定位

手头有个机械臂抓取或者移动端避障的项目,要用普通摄像头测出目标的三维坐标,你是不是心里直犯嘀咕?“这玩意儿是不是得套什么高深的三维重建算法?”“那些矩阵公式看得我脑壳疼,到底怎么落地?”

别慌,今天咱们不扯那些让人昏昏欲睡的纯数学公式。作为在工业视觉里摸爬滚打了十几年的老油条,我今天就带大家用 C# 和 OpenCvSharp 库,手把手把这个看起来高大上的“单目定位”给彻底扒光。

咱们的目标很简单:拿个几块钱的普通摄像头,贴个打印出来的二维码(ArUco 标志),就能精准实时输出它在三维空间里的具体坐标(X, Y, Z)和旋转角度。

整套方案分为两步走。相信我,只要你跟着敲一遍,你会发现:原来单目定位,真的一点都不神秘!


️ 第一阶段:磨刀不误砍柴工——棋盘格内参标定

很多刚入行的小伙伴,一上来就急着用摄像头测距离,结果发现离得近还算凑合,稍微放远一点或者拿到画面边缘,那数据就飘得没法看。

为什么?因为畸变

市面上几十块钱的摄像头,那镜片多多少少都有点像“哈哈镜”——中间鼓、四周缩(径向畸变),或者镜头装得不那么正(切向畸变)。

要想让计算机看懂真实的世界,我们必须先摸清这颗摄像头的“脾气”。这个摸底的过程,就叫相机标定(Calibration)。我们需要拿到两样东西:


步骤 1:采集标定图像(拒绝死板,手动抓拍)

别去网上随便下一些来路不明的图。咱们自己写个小程序,一边看着实时画面,一边变换各种角度,抓拍 15 - 20 张清晰的棋盘格照片。

避坑指南: 棋盘格规格一定要数清楚!比如我们常用 9x6 的内角点棋盘格(注意:是内角点,即黑白格交叉的内交点个数,而不是最外圈的格子数!一个 10x7 格子的纸,内角点正好是 9x6)。

图像采集源码:

1using System;
2using System.IO;
3using OpenCvSharp;
4 
5class CollectCalibrationImages
6{
7    static void Main()
8    {
9        int count = 0;
10        string saveDir = "calib_images";
11        Directory.CreateDirectory(saveDir);
12 
13        using var cap = new VideoCapture(0); // 打开默认摄像头
14        if (!cap.IsOpened())
15        {
16            Console.WriteLine("摄像头打不开,是不是被别的程序占用了?");
17            return;
18        }
19 
20        using var frame = new Mat();
21        using var display = new Mat();
22 
23        // 9x6的内角点,这玩意儿数错了后面一步都走不通!
24        var patternSize = new Size(9, 6);
25 
26        Console.WriteLine("【提示】把棋盘格放到摄像头前。检测到后按【空格】保存,按【ESC】退出。");
27 
28        while (true)
29        {
30            cap.Read(frame);
31            if (frame.Empty()) continue;
32            frame.CopyTo(display);
33 
34            Point2f[] corners = null;
35            // 粗略检测棋盘格角点
36            bool found = Cv2.FindChessboardCorners(frame, patternSize, out corners);
37 
38            if (found)
39            {
40                // 帮我们画出彩色的角点连接线,很直观
41                Cv2.DrawChessboardCorners(display, patternSize, corners, found);
42                Cv2.PutText(display, "Detected! Press SPACE to save.", new Point(10, 30),
43                            HersheyFonts.HersheySimplex, 0.8, Scalar.Green, 2);
44            }
45            else
46            {
47                Cv2.PutText(display, "No Chessboard Found", new Point(10, 30),
48                            HersheyFonts.HersheySimplex, 0.8, Scalar.Red, 2);
49            }
50 
51            Cv2.PutText(display, #34;Saved: {count} pics", new Point(10, 65),
52                        HersheyFonts.HersheySimplex, 0.7, Scalar.Yellow, 2);
53 
54            Cv2.ImShow("Collector", display);
55            int key = Cv2.WaitKey(1);
56 
57            if (key == 27) break;  // ESC 键退出
58 
59            if (key == 32 && found) // 空格键保存
60            {
61                string path = Path.Combine(saveDir, #34;calib_{count:D3}.png");
62                Cv2.ImWrite(path, frame); // 存原图,千万别存画了线的图!
63                Console.WriteLine(#34;[成功] 已保存第 {count} 张:{path}");
64                count++;
65            }
66        }
67 
68        Cv2.DestroyAllWindows();
69        Console.WriteLine(#34;
搞定!共收集到 {count} 张高质量标定图,准备下一步!");
70    }
71}

个人经验碎碎念: 拍这个图的时候,千万不要只是直勾勾地对着镜头。你要让棋盘格倾斜一些角度(仰角、俯角、侧角),并且尽量让棋盘格充满画面的各个角落(尤其是边缘)。因为畸变在四周最严重,如果边缘没有点,畸变系数是算不准的。


步骤 2:解算相机内参(计算出物理世界的尺子)

有了这一批照片,我们就可以让 OpenCvSharp 帮我们算矩阵了。我们会把每一个像素点对应的真实 3D 坐标(我们假定棋盘格处于 \(Z=0\) 的平面,每个格子长 25 毫米)塞给算法。

标定解算核心源码:

这个算出来的 camera_params.xml 是我们待会做三维定位的基石。丢了它,后面寸步难行。


第二阶段:终极对决——ArUco 标志实时位姿估计

万事俱备,东风已来!现在,我们可以把一个叫 ArUco 的黑白二维码放到摄像头前面,让系统实时告诉我:这个二维码距离我的镜头到底有多少厘米?它转了多少度?

什么是 ArUco?

简单来说,它是一种专门为了机器视觉定位设计的方形条码。和普通的 QR Code(比如微信付款码)相比,它的检测速度极快,定位精度极高,哪怕在极差的光照下,也能稳定地检测到四个角点。


核心定位代码(精细解读版)

在这段代码中,我们会通过 OpenCV 著名的 SolvePnP(Perspective-n-Point)算法,结合刚刚生成的相机内参,完美解算出标志牌在空间里的三维姿态。


为什么说这套方案比直接测距靠谱得多?

在以前,很多小伙伴会说:“我用像素占比算测距不行吗?物体近了像素大,远了像素小。”

这在某些极度局限的场景下或许能用,但它的硬伤太明显了:


互动时刻

大家在调试相机标定时,遇到过最恶心的问题是什么?

欢迎在评论区里留言聊聊你们在视觉项目里踩过的坑,咱们一起研究研究。


今日份技术总结

觉得有用的话,欢迎微信打赏鼓励一下,让我有动力继续输出这类实战内容。完整源码结构已在各节逐一呈现,可结合项目实际直接落地;如需完整源码,可在公众号聊天窗口获取。

#C#开发 #OpenCV #三维视觉 #机器视觉 #工业自动化

展开阅读全文

更新时间:2026-07-09

标签:数码   定单   相机   棋盘   内角   畸变   摄像头   手把   视觉   内参   像素   实时   源码

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight All Rights Reserved.
Powered By 61893.com 闽ICP备11008920号
闽公网安备35020302034903号

Top