这几天在做一个双目视觉的东西,要达到深度识别0.1mm以内,没深入过这方面的东西,边学边记录。所以,这一篇代码非常简单和粗鄙,甚至需要你自己修改很多东西才能运行。
使用OPENCV来进行矫正图像,首先要得到两个矩阵:相机矩阵、畸变矩阵。然后使用InitUndistortRectifyMap、Remap函数来处理就可以得到矫正后的图像。
一、软件准备
1、NuGet OpenCV4.1
2、Opencv.org OpenCV4.1
二、编译camera_calibration项目
基本过程如下(请先自行百度各种教程,坑不算多,不过办公室过一遍家里再过一遍之后心累不想说):
0、在A4纸上打印下面这副图像,找一个摄像头,用它拍十几二十张并保存
1、设置环境变量
2、设置工程属性
3、在代码最顶端加上#define _CRT_SECURE_NO_WARNINGS
4、编译,进入程序所在目录,粘贴in_VID5.xml
5、修改in_VID5.xml名为default.xml,并修改
<Square_Size>28</Square_Size>
<Input>"images/VID5.xml"</Input>
<Write_outputFileName>"images/out_VID5.xml"</Write_outputFileName>
PS:28是我打印出来棋盘格每个格子的实际边长(mm)
6、建立images目录,进入目录粘贴VID5.xml
7、修改其内容为类似下面内容
<?xml version="1.0"?>
<opencv_storage>
<images>
images/01.jpg
images/02.jpg
images/03.jpg
images/04.jpg
images/05.jpg
images/06.jpg
images/07.jpg
images/08.jpg
images/09.jpg
images/10.jpg
images/11.jpg
images/12.jpg
images/13.jpg
images/14.jpg
</images>
</opencv_storage>
8、将对应名称的图片放入该文件夹
9、运行程序,成功后会在images下生成out_VID5.xml
祝你顺利!
完成以上的各种工作之后,得到的out_VID5.xml里面就有camera_matrix和distortion_coefficients了,这就是相机矩阵和畸变矩阵,当然里面乱七八糟的误差、外参矩阵、图像角点啥啥还有很多,有兴趣知道都什么意义的可以自己百度一下,我们还是抓紧把狗肉贴到羊头上:
二、用VB.NET来矫正这个摄像头拍出的图像
按国际惯例先上玉照:
这个老古董虽然右上有一个黑斑,但是畸变确实不算大,也不知工业摄像头到了会比这强多少。
1、读取xml:
Dim cameraMatrix As Mat = fs.Item("camera_matrix").ReadMat
Dim distCoeffs As Mat = fs.Item("distortion_coefficients").ReadMat
Dim imageSize As New Size(fs.Item("image_width").ReadInt, fs.Item("image_height").ReadInt)
openCV的API好用到不像话。
2、生成新的相机矩阵
Dim validPixROI As Rect
Dim NewCameraMatrix As Mat = GetOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, validPixROI, 0)
那个byref的rect输出矫正后的图像矩形。
3、计算映射
Dim view, rview, map1, map2 As New Mat
InitUndistortRectifyMap(cameraMatrix, distCoeffs, New Mat(), NewCameraMatrix, imageSize, CV_16SC2, map1, map2)
4、矫正和显示结果
For Each f As String In Directory.EnumerateFiles(My.Application.Info.DirectoryPath & "\image\", "*.jpg")
view = ImRead(f, ImreadModes.Color)
Remap(view, rview, map1, map2, InterpolationFlags.Linear)
pnlLeft.BackgroundImage = ToBitmap(view)
pnlRight.BackgroundImage = ToBitmap(rview)
MsgBox("点击确定继续", MsgBoxStyle.OkOnly)
Next
真的是简单的不能再简单了。晚上SW设计一个工业摄像头的支架并打印出来,明天摄像头到了开始架设PC测试,等有了成果再写一篇整体的内容——初步计划最终是树莓派&C++,所以和VB.NET关系都不大。只是不想在捋思路的时候还想着因为不习惯去吐槽才用的最顺手的VB.NET做测试而已^ ^。尽最大努力半年时间能把整个工程完成。