赞
踩
在机器视觉领域,相机的标定是一个关键的环节,它决定了机器视觉系统能否有效的定位,能否有效的计算目标物。相机标定意义在于将现实世界中的三维物体与相机图像对应的二维物体映射起来,实际上就是透视投影。
针对针孔相机模型, 相机标定,标定的是指内参矩阵和外参矩阵,就可以确定为一的相机模型。
相机坐标系与世界坐标系之间的坐标转换关系称为相机外参,一般由平移和旋转两部分参数组成。求取外参的过程称之为外参标定,外参标定的结果关系到如何引导机器人进行抓取。
相机内部参数(简称内参)只与相机内部属性(如焦距、分辨率、像素尺寸、镜头畸变等)
有关。利用相机内参可以将相机坐标系中的三维空间点变换到图像平面坐标系中,经过镜头畸变等校正过程之后可进一步变换至图像像素坐标系中的二维像素点。求取这一关系的
过程称为相机内参标定。
真实世界中的某点会投影在相机的成像平面上,利用针孔成像原理,空间任意一点Pc与图像点p之间的关系,Pc与相机光心Oc的连线为OcPc,与像面的交点p即为空间点Pc在图像平面上的投影。
该过程为透视投影,利用相似三角形关系可得:
其中f为焦距,z轴方向上s为Pc点到光心的距离,一般称为比例因子。投影关系为写成矩阵形式:
其中,s为比例因子(s不为0),f为有效焦距(光心到图像平面的距离),(x,y,z,1)T是空间点P在坐标系oxyz中的齐次坐标,(x,y,1)T是像点p在图像坐标系OXY中的齐次坐标。
注意:此时投影点p的单位还是mm,并不是pixel,需要进一步转换到像素坐标系。
像素坐标系和图像坐标系都在成像平面上,只是各自的原点和度量单位不一样。图像坐标系的原点为相机光轴与成像平面的交点,通常情况下是成像平面的中点或者叫principal point。图像坐标系的单位是mm,属于物理单位,而像素坐标系的单位是pixel,我们平常描述一个像素点都是几行几列。所以这二者之间的转换如下:
dx和dy表示每一列和每一行分别代表多少mm,即1pixel=dx mm。
光线经过透镜中心会发生弯曲,这种现象称为径向畸变,径向畸变分为枕型畸变与筒形畸变。
径向畸变围绕像素坐标及其泰勒展开式进行矫正。
其中(,)为矫正之后的坐标, (x,y)代表畸变像素坐标, r 代表成像中心距离,
相机畸变除了会产生径向畸变之外而且会产生切向畸变,透镜与成像平面不完全平行造成切向畸变的发生。
切向畸变的矫正公式:
分享一个可以生成各种标定板的网站: https://calib.io/pages/camera-calibration-pattern-generatorSingle Camera Calibrator Apphttps://calib.io/pages/camera-calibration-pattern-generatorSingle Camera Calibrator App
和自定义检测器图案。有关这些图案的细节和包含可打印图案的PDF文件,请参见校准图案。
- import cv2 as cv
-
- print(cv.__version__)
-
- def videoDemo():
- capture = cv.VideoCapture(0)
- n = 0
- while True:
- ret, frame = capture.read()
- n = n + 1
- print(f"num {n} {ret}")
- cv.imshow("Video", frame)
- c = cv.waitKey(50)
- if c == 32:
- cv.destroyAllWindows()
- cv.imwrite("/home/dofbot/camera/pic/borad.png", frame)
- cv.imshow("Video", frame)
- break
-
- if __name__ == '__main__':
- videoDemo()
支持棋盘格、圆圈格在APP中选择Camera Calibrator,如下:
点击 Add Images,导入拍照图片。标定20张左右就够了,然后角度变一下,但不需要变太大,太大了会影响标定效果。标定板最好在视场中心,且占据较大面积。
修改棋盘格大小为27*27mm(我的A4纸测量是这样)
对于标准相机,菜单栏的option里选择三阶径向畸变和斜切:
点击Calibrate,进行相机标定:
右上角是重建平均误差,只要平均误差小于0.5,就可以认为这是相机标定的结果是可靠的。
把相机参数导出来,点击 Export Camera Parameters。点击确定,就可以看到matlab工作区出现了相机参数。点开这个参数,就可以得到相机的各个参数:
为了找到棋盘的图案,使⽤函数 cv2.findChessboardCorners()。还需要传⼊图案的类型⽐如说 8x8 的格⼦或 5x5 的格⼦等。在本例中我们使⽤的9×6 的格⼦。(通常情况下棋盘都是 8x8 或者7x7)。它会返回⻆点,如果得到图像的话返回值类型(Retval)就会是 True。这些⻆点会按顺序排列(从左到右,从上到下)。 在找到这些⻆点之后我们可以使⽤函数 cv2.cornerSubPix() 增加准确度。我们使⽤函数cv2.drawChessboardCorners() 绘制图案。
在得到了这些对象点和图像点之后,我们已经准备好来做摄像机标定了。我们要使⽤的函数是cv2.calibrateCamera()。它会返回摄像机矩阵,畸变系数,旋转和变换向量等。
所有的这些步骤都被包含在下⾯的代码中了:
- import cv2
- import numpy as np
- import glob
-
- # 找棋盘格⻆点
- # 设置寻找亚像素⻆点的参数,采⽤的停⽌准则是最⼤循环次数30和最⼤误差容限0.001
- criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) # 阈值
- #棋盘格模板规格
- w = 9 # 10 - 1
- h = 6 # 7 - 1
- # 世界坐标系中的棋盘格点,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐标,记为⼆维矩阵
- objp = np.zeros((w*h, 3), np.float32)
- objp[:, :2] = np.mgrid[0:w,0:h].T.reshape(-1, 2)
- objp = objp*18.1 # 18.1 mm
-
- # 储存棋盘格⻆点的世界坐标和图像坐标对
- objpoints = [] # 在世界坐标系中的三维点
- imgpoints = [] # 在图像平⾯的⼆维点
- #加载pic⽂件夹下所有的jpg图像
- images = glob.glob('D:\pic\*.png') # 拍摄的⼗⼏张棋盘图⽚所在⽬录
-
- i = 0
- for fname in images:
- img = cv2.imread(fname)
- # 获取画⾯中⼼点
- #获取图像的⻓宽
- h1, w1 = img.shape[0], img.shape[1]
- gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
- u, v = img.shape[:2]
- # 找到棋盘格⻆点
- ret, corners = cv2.findChessboardCorners(gray, (w, h), None)
- # 如果找到⾜够点对,将其存储起来
- if ret == True:
- print("i:", i)
- i = i+1
- # 在原⻆点的基础上寻找亚像素⻆点
- cv2.cornerSubPix(gray,corners, (11, 11), (-1, -1), criteria)
- #追加进⼊世界三维点和平⾯⼆维点中
- objpoints.append(objp)
- imgpoints.append(corners)
- # 将⻆点在图像上显⽰
- cv2.drawChessboardCorners(img, (w, h), corners, ret)
- cv2.namedWindow('findCorners', cv2.WINDOW_NORMAL)
- cv2.resizeWindow('findCorners', 640, 480)
- cv2.imshow('findCorners', img)
- cv2.waitKey(200)
- cv2.destroyAllWindows()
- #%% 标定
- print('正在计算')
- #标定
- ret, mtx, dist, rvecs, tvecs = \
- cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
-
- print("ret:", ret)
- print("mtx:\n", mtx) # 内参数矩阵
- print("dist畸变值:\n", dist) # 畸变系数 distortion cofficients = (k_©,k_ª,p_©,p_ª,k_«)
- print("rvecs旋转(向量)外参:\n", rvecs) # 旋转向量 # 外参数
- print("tvecs平移(向量)外参:\n", tvecs) # 平移向量 # 外参数
- newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (u, v), 0, (u, v))
- print('newcameramtx外参', newcameramtx)
Kinetic:
sudo apt-get install ros-kinetic-usb-cam
Melodic:
sudo apt-get install ros-melodic-usb-cam
其他版本
sudo apt-get install ros-版本名称-usb-cam
进入目录:
- roscd usb_cam
- cd launch
- sudo gedit usb_cam-test.launch
目前主要修改device和width两个参数,可以使用ls /dev/video*
查看系统视频设备。
<launch> <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" > <!-- modify the video device to your device --> <param name="video_device" value="/dev/video0" /> <!-- modify the size of your device --> <param name="image_width" value="1280" /> <param name="image_height" value="720" /> <param name="pixel_format" value="yuyv" /> <param name="camera_frame_id" value="usb_cam" /> <param name="io_method" value="mmap"/> </node> <node name="image_view" pkg="image_view" type="image_view" respawn="false" ou$ <remap from="image" to="/usb_cam/image_raw"/> <param name="autosize" value="true" /> </node> </launch>
roslaunch usb_cam usb_cam-test.launch
/tmp
目录下。ls /dev/video*
选择自己需要显示的设备,再修改launch文件,就可以使用。
查看相机接口信息
v4l2-ctl -d 0 --all
参考相机接口信息修改usb_cam-test.launch文件,文件原内容如下
<launch>
<node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
<param name="video_device" value="/dev/video0" />
<param name="image_width" value="640" />
<param name="image_height" value="480" />
<param name="pixel_format" value="yuyv" />
<param name="camera_frame_id" value="usb_cam" />
<param name="io_method" value="mmap"/>
</node>
<node name="image_view" pkg="image_view" type="image_view" respawn="false" output="screen">
<remap from="image" to="/usb_cam/image_raw"/>
<param name="autosize" value="true" />
</node>
</launch>
运行修改后的launch文件即可
roslaunch usb_cam usb_cam-test.launch
打开标定窗口
一般来说正常安装ros都是包含了camera_calibration,输入下面命令检查一下
rosdep install camera_calibration #All required rosdeps installed successfully
运行前需要根据你的棋盘格修改参数
image
,图像话题的原始数据默认为camera:=/usb_cam
rosrun camera_calibration cameracalibrator.py --size 10x7 --square 0.015 image:=/usb_cam/image_raw camera:=/usb_cam
标定完成后点击Calculate会稍微有点卡顿,不要担心后台正在进行标定,完成后下面的SAVE和COMMIT按钮变为可用状态,点击SAVE即可保存标定完成后的文件。
点击commit即可把标定文件存储到系统的~/.ros/camera_info/xxx.yaml
目录(Ctrl+H 显示隐藏的目)
可以在usb_cam的launch文件中增加以下参数,重新启动usb_cam节点,即可使用该标定参数。
参数值小鱼这里写的是file:///home/dev/.ros/camera_info/ost.yaml
,可打开目录~/.ros/camera_info/
进行查看
<param name="camera_info_url" type="string" value="file:///home/dev/.ros/camera_info/ost.yaml"/>
- source devel/setup.bash
- roslaunch handeye-calib aruco_start_usb_cam.launch
以Intel Realsense彩色相机为例,以下是彩色相机的信息。
- # rostopic echo /right_arm_camera/color/camera_info
- ---
- header:
- seq: 32308
- stamp:
- secs: 1694683940
- nsecs: 530882359
- frame_id: "right_arm_camera_color_optical_frame"
- height: 720
- width: 1280
- distortion_model: "plumb_bob"
- D: [0.0, 0.0, 0.0, 0.0, 0.0]
- K: [911.4010620117188, 0.0, 645.8338623046875, 0.0, 910.145263671875, 347.9687194824219, 0.0, 0.0, 1.0]
- R: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
- P: [911.4010620117188, 0.0, 645.8338623046875, 0.0, 0.0, 910.145263671875, 347.9687194824219, 0.0, 0.0, 0.0, 1.0, 0.0]
- binning_x: 0
- binning_y: 0
- roi:
- x_offset: 0
- y_offset: 0
- height: 0
- width: 0
- do_rectify: False
- ---
- header:
- seq: 32309
- stamp:
- secs: 1694683940
- nsecs: 564413071
- frame_id: "right_arm_camera_color_optical_frame"
- height: 720
- width: 1280
- distortion_model: "plumb_bob"
- D: [0.0, 0.0, 0.0, 0.0, 0.0]
- K: [911.4010620117188, 0.0, 645.8338623046875, 0.0, 910.145263671875, 347.9687194824219, 0.0, 0.0, 1.0]
- R: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
- P: [911.4010620117188, 0.0, 645.8338623046875, 0.0, 0.0, 910.145263671875, 347.9687194824219, 0.0, 0.0, 0.0, 1.0, 0.0]
- binning_x: 0
- binning_y: 0
- roi:
- x_offset: 0
- y_offset: 0
- height: 0
- width: 0
- do_rectify: False
- ---
其中包括相机的内部参数有关的参数:
当处理相机内参时,常见的三个参数是 D、K 和 P,此外相关的还有畸变模型。
D 是一个通常包含五个元素的数组 [k1, k2, p1, p2, k3],用于描述相机图像中的径向和切向畸变。
D: [0.0, 0.0, 0.0, 0.0, 0.0]
K 是一个3x3的矩阵,它包括了相机的内部参数,用于将相机坐标系中的三维点映射到图像平面上的二维坐标。
K 的主要元素包括:
K: [911.4010620117188, 0.0, 645.8338623046875, 0.0, 910.145263671875, 347.9687194824219, 0.0, 0.0, 1.0]
P 是一个3x4的矩阵,包含了相机的投影参数,用于将相机坐标系中的三维点映射到图像坐标系。
P 的元素包括了内参和外参信息。
P: [911.4010620117188, 0.0, 645.8338623046875, 0.0, 0.0, 910.145263671875, 347.9687194824219, 0.0, 0.0, 0.0, 1.0, 0.0]
distortion_model 是相机标定信息中的一个字段,用于描述相机的畸变模型。
畸变模型是用来描述相机镜头产生的畸变效应的数学模型。
在计算机视觉中,畸变通常分为径向畸变和切向畸变两种主要类型,而畸变模型用于对这些畸变进行建模和校正。
Plumb Bob (钉形畸变模型):
“plumb_bob” 畸变模型是最常见的畸变模型之一,也是默认的畸变模型。它通常用于描述径向畸变(Radial Distortion)和切向畸变(Tangential Distortion)。
径向畸变主要是由于镜头形状不完全圆形引起的,导致图像中心附近的像素与图像边缘的像素之间存在畸变。这种畸变通常用多项式函数建模。
切向畸变则是由于相机镜头不完全平行于图像平面引起的,导致图像中心附近的像素存在畸变。切向畸变通常也用多项式函数建模。
“plumb_bob” 畸变模型使用径向和切向畸变系数(D)来描述这两种畸变。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。