opencv学习记录3-相机标定与姿态解算

这篇具有很好参考价值的文章主要介绍了opencv学习记录3-相机标定与姿态解算。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

相机标定与姿态解算

1.相关概念学习

1.1相机模型

确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立相机成像的几何模型

1.2四个重要坐标系:

相机的几何模型,用来反映环境信息到图像信息之间的映射关系

  • 世界坐标系

  • 相机坐标系

  • 图像成像坐标系

  • 图像像素坐标系

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

整个成像过程分为两次映射过程

1.世界坐标系->相机坐标系

2.相机坐标系->像素坐标系

描述第一次映射模型的参数叫做 相机外参 ,描述第二次映射模型的参数叫做相机内参,它分为 内参矩阵畸变参数矩阵

1.3内参矩阵

描述了相机坐标系到像素坐标系之间的坐标转换

  • 水平缩放因子fx,垂直缩放因子fy: 物体投影到成像平面时水平、竖直的 放缩倍数 不同,坐标系转换时需要乘以 缩放因子

  • 水平平移因子Cx,垂直平移因子Cy: 从成像坐标系转换到像素坐标系需要带上 平移项

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

等号左边是像素坐标系,右边是内参矩阵和相机坐标系

1.4镜头畸变

产生原因:

  • 透镜形状:由于透镜形状造成的畸变称为 径向畸变 ,径向畸变分为 桶形畸变枕形畸变 ,径向畸变有 越远离光心,畸变越大的特征

  • 桶形畸变:过分偏折

  • 枕形畸变:偏折不够

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档
  • 安装误差:相机的组装过程中由于不能使透镜和成像面严格平行造成的畸变称为 切向畸变

1.5畸变的修正

径向畸变

创建一个映射函数F(r)来描述畸变发生前后像素点的对应关系,其中 r为像素点离图像中点的距离

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

切向畸变:

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

将两个修正综合一下得到:

完整的【原像素点->去畸变后像素点】的函数对应:

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

畸变参数矩阵:

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档
1.6如何求相机内参?

张正有棋盘标定法

一个标定板:

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档
1.7姿态解算

由于实物的坐标从相机坐标系投影到成像坐标系时,z轴方向信息全部丢失(纵深信息)

重获纵深信息——PNP解算

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

其中

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

为所求的坐标变换,其中 R为旋转3×3矩阵,t为平移1×3矩阵

即:

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

以上 12 个参数,说明最少用 6 对 3D-2D 匹配点 就可以实现对于矩阵的求解 ——> 直接线性变换( DLT )

如何更简便地求解?—— 用三个参数即可描述这种旋转变换: (欧拉角)

yaw角(绕z-轴转角)、pitch角(绕y-轴转角)、roll角(绕x-轴转角)

所以最少需要 3 对 3D-2D 匹配点 就可以实现求解。通常使用 4 对点,另一对点用于验证、减小误差

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

综上:给出 4 对 3D-2D 匹配点对 ,经过PNP解算后就可以获得一个 旋转矩阵R 和一个 平移矩阵T,这两个矩阵描述了世界坐标系与相机坐标系之间的转换方式——即描述了物体的 相对位姿

1.8旋转矩阵到欧拉角

把旋转矩阵转换成三个欧拉角:

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

得到

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

分别为 roll角(绕x-轴转角),pitch角(绕y-轴转角),yaw角(绕z-轴转角)

ps:(之后补充学习)
1.solvePnP解算出的是旋转向量,需要经过罗德里斯公式映射后才能变成旋转矩阵
2.要用卡尔曼滤波预测的方法来跟踪对面车辆的移动状态并进行预测
1.9总结
  1. 已知多对 3D-2D匹配点对 的世界坐标系坐标以及像素坐标系坐标

  1. 已知相机内参,即映射过程

  1. 利用PNP解算还原丢失的纵深信息

  1. 所有信息重新代回抽象模型,反解映射函式,求得相对姿态

2.实现一次相机标定

运用opencv自带函数

2.1代码

注:

常用cv2.findChessCorners来确定是否找到了角点,再输入物点,用cv2.cornerSubPix,寻找亚像素坐标,这样更精准

import numpy as np
import cv
#glob :返回所有匹配的文件路径列表
import glob

#EPS表示迭代次数达到最大次数时停止
#MAX_ITER表示角点位置变化的最小值已经达到最小时停止迭代
#两个条件都要满足
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30 , 0.001)

#以z轴为 0 取平面上的点
#6*8矩阵来储存角点

objp = np.zeros((6*8, 3), np.float32)
objp[:, :2] = np.mgrid[0:8, 0:6].T.reshape(-1, 2)

#objpoints 来储存世界坐标系下的三维点坐标
#imgpoints 来储存像素坐标系下的二维点坐标
objpoints = []
imgpoints = []

#选出所有拍摄的图片
images = glob.glob('C:/Users/DELL/Desktop/camera/*.JPG')

#转为黑白图片,提高效率
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
#找到棋盘格上的角点(返回到像素坐标系)
#ret来判断是否找到了角点
ret, corners = cv2.findChessboardCorners(gray, (8, 6), None)
if ret == True :
    #输入物点,(11,11)表示窗口大小,(-1,-1)表示忽略掉的细微结构
    #这样会更精确
    objpoints.append(objp)
    corners2 = cv2.cornerSubPix(gray, corners, (11,11), (-1, -1), criteria)
    imgpoints.append(corners2)
    
#画出找到的点(corners2->img,即亚像素坐标系到图像坐标系)
img = cv2.drawChessboardCorners(img, (8, 6), corners2, ret)
cv2.namedWindow('img', 0)
cv2.imshow('img', img)
while cv2.waitKey(100) != 27:
    if cv2.getWindowProperty('img', cv2.WND_PROP_VISIBLE) <= 0:
        break
cv2.destroyAllWindows()

#直接调用calibrateCamera即可完成求解矩阵等操作
#mrx:相机内参数
#dist:畸变参数
#rvecs:旋转向量
#tveces:平移向量
ret,mrx,dist,rvecs,tveces = cv2.calibrateCamera(objpoints,imgpoints, (8, 6),
None, None)

print(mrx)

结果:

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

测得相机内参矩阵:

[[ 4.70909596e+03 0.00000000e+00 7.80898770e+01]
[ 0.00000000e+00 2.71572676e+03 -5.91631123e+01]
[ 0.00000000e+00 0.00000000e+00 1.00000000e+00]]

畸变参数:

[ 0.11052443 -0.04990666 -0.03609475 -0.00387042 0.0139093 ]
2.2相机内参矩阵各参数含义说明
二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档
  • f:焦距

  • dx:像素x方向宽度,单位毫米

  • f/dx:使用像素来描述x轴方向焦距的长度

  • f/dy:使用像素来描述y轴方向焦距的长度

  • u0,v0:主点的实际位置,单位是像素

3.实现一次去畸变

3.1所给定数据如下

内参:

[[ 458.654 0.000 367.215]
[ 0.000 457.296 248.375]
[ 0.000 0.000 1.000 ]]

畸变参数:

[ -0.28340811, 0.07395907, 0.00019359, 1.76187114e-05, 0.0]

原图:

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档
3.2具体操作
import numpy as np
import cv2

#运用mat函数创建矩阵,用来存放畸变参数和内参
#mrx:相机内参数
#dist:畸变参数
mrx = np.mat([[458.654, 0.0, 367.215],[0.0, 457.296, 248.375], [0.0, 0.0, 1.0]])
dist = np.mat([ -0.28340811, 0.07395907, 0.00019359, 1.76187114e-05, 0.0])

#读取图像
img = cv2.imread('C:/Users/DELL/Desktop/distorted.png')
#返回该图片的大小和维度
h, w = img.shape[:2]
#用cv2.getOptimalNewCameraMatrix得到新的不畸变的相机参数
#roi:尺寸
newcameramtx,roi = cv2.getOptimalNewCameraMatrix(mrx, dist, (w, h), 1, (w, h))

#用cv2.undistort去畸变
dst = cv2.undistort(img, mrx, dist, None, newcameramtx)
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('C:/Users/DELL/Desktop/1.png',dst)

去畸变后结果:

二维码求解姿态,python,opencv,计算机视觉,算法,Powered by 金山文档

3.实现姿态解算

solvepnp通过2D点和3D点求解相机的位姿 (R,t),在opencv3中常用的方法是 epnp, DLS,迭代法

3.1二维码角点检测
import cv2
import numpy as np

# 读取图像
src = cv2.imread( 'C:/Users/DELL/Desktop/test.png')

# 灰度转换,提高效率
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# 检测
qrcoder = cv2.QRCodeDetector()
# 解码
#points:得到的二维码四个点的坐标信息
codeinfo, points, straight_qrcode = qrcoder.detectAndDecode(gray)
result = np.copy(src)
# 描绘轮廓
cv2.drawContours(result, [np.int32(points)], 0, (0, 0, 255), 2)

cv2.namedWindow('result', 0)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

3.2姿态解算
# 使用opencv中的函数solvepnp
import cv2
import numpy as np

mrx = np.mat([[ 4.70909596e+03 , 0.00000000e+00, 7.80898770e+01],[
0.00000000e+00 , 2.71572676e+03 ,-5.91631123e+01], [ 0.00000000e+00 ,
0.00000000e+00 , 1.00000000e+00]])
dist = np.mat([ 0.11052443, -0.04990666 ,-0.03609475, -0.00387042 , 0.0139093 ])

#objpoints:世界坐标系的坐标(假设一个
tag_size_half = 0.025
objPoints = np.mat([[-tag_size_half, -tag_size_half, 0],
                    [tag_size_half, -tag_size_half, 0],
                    [tag_size_half, tag_size_half, 0],
                    [-tag_size_half, tag_size_half, 0]], dtype=np.float64)
#3.1中获得的二维码四个点的2d坐标信息
imgPoints = np.mat([[ 687, 484 ],[1520, 437 ],[1476.684 , 1558.8041],[ 647 ,
1411 ]])

# cv2.Rodrigues():进行旋转矩阵和旋转向量之间的相互转化
#rvecs:相机坐标系中物体的旋转
#tvec:相机坐标系中物体的平移
retval,rvec,tvec = cv2.solvePnP(objPoints, imgPoints, mrx, dist)

print(during1)
print( rvec, tvec)

结果:

[[-0.37706436]
[ 1.25688629]
[-0.13645112]]

[[0.02891978]
[0.05420701]
[0.14332578]]

(参考资料csdn,知乎)

四种方法对比:

  1. 迭代法:只能用四个共面的点来求解

  1. P3P:可以使用任意 4 个特征点求解,不要求共面

  1. EPNP:只要特征点数量大于 3 就可求出正解

  1. BA(光束法平差):这种方法将相机位姿和三维点位置放在一起进行重投影误差最小化的优化

( BA 非线性?)

精确度: BA最精确

用时比较: P3P方法用时最短

经查询,p3p在使用时仍有一些问题:

1. P3P值利用3个点的信息,当给定的匹配点多于3组时,难以利用更多的信息。
2. 如果3D点或2D点受到噪声影响,或者存在误匹配,则算法失效。

EPnP的思路和P3P差不多,相对P3P来说,EPnP利用更多的信息,用迭代的方式对相机位姿进行优化,以尽可能消除噪声的影响。文章来源地址https://www.toymoban.com/news/detail-775543.html

ps:

P3P使用时最后还需要一对点用于验证。

到了这里,关于opencv学习记录3-相机标定与姿态解算的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Web相机和浏览器的二维码扫描方案

    Web相机和适用于浏览器的二维码扫描方案 在线体验 | English 支持浏览器扫描二维码 支持拍照 支持录像功能 支持二维码解析和生成 CDN 1. QRCamera options: 2. getCameras 获取摄像头列表 3. switchCamera 切换摄像头 4. scanQrcode 开启识别二维码 stopScanQrcode 停止识别二维码 4. photo 拍照 5. rec

    2024年02月04日
    浏览(42)
  • 【ESP32Arduino+MPU6050姿态解算】自制无人机学习笔记2 PLatformIO 下载即可使用

    本人之前发表过一篇关于esp32读取mpu6050数据的文章,链接:http://t.csdn.cn/AwzSZ,但其存在一些漏洞,具体表现在输出数据存在不连贯和错误,在mpu6050高速运动时存在较大误差等。仅作为参考。故在此重发作为修正。当前该篇文章中所述的模块,已经过无人机稳定性控制的测试

    2024年02月16日
    浏览(44)
  • 微信小程序 图片 相机 二维码 动画相关API(实现选择相册、拍照、录像、动画)

    本文探讨微信小程序 图片 相机 二维码 动画相关API(实现选择相册、拍照、录像、动画)功能,带有示例代码

    2024年02月04日
    浏览(56)
  • OpenCV实战(24)——相机姿态估计

    校准相机后,就可以将捕获的图像与物理世界联系起来。如果物体的 3D 结构是已知的,那么就可以预测物体如何投影到相机的传感器上,图像形成的过程由投影方程描述。当方程的大部分项已知时,就可以通过观察一些图像来推断其他元素 ( 2D 或 3D ) 的值。相机姿态估计就是

    2024年02月05日
    浏览(45)
  • 数字图像处理二维码识别python+opencv实现二维码实时识别

    数字图像处理二维码识别 python+opencv实现二维码实时识别 特点: (1)可以实现普通二维码,条形码; (2)解决了opencv输出中文乱码的问题 (3)增加网页自动跳转功能 (4)实现二维码实时检测和识别 代码保证原创、无错误、能正常运行(如果电脑环境配置没问题) 送二维

    2024年01月16日
    浏览(69)
  • OpenCV(三十八):二维码检测

    1.二维码识别原理 功能图形: 位置探测图形:通常,二维码中有三个位置探测图形,呈现L型或大角度十字架形状,分布在二维码的三个角上,用于帮助扫描设备定位二维码的位置和方向。 位置探测图形分隔符:帮助扫描设备区分位置探测图形和二维码的数据区域。 计算模式

    2024年02月07日
    浏览(47)
  • 【Python】【OpenCV】定位二维码

    相较于BarCode,QRCode有明显的特征区域,也就是左上角、右上角、左下角三个”回“字区域,得益于hierarchy中,父子关系的轮廓是连续的(下标),所以这个时候我们就可以通过cv2.findContours()返回的hierarchy来进行定位。 我们直接上代码   通常我们所见的二维码都是有留白边缘

    2024年02月04日
    浏览(46)
  • 10. Opencv检测并截取图中二维码

    1. 说明 在二维码扫描功能开发中,使用相机扫描图片时,往往图片中的信息比较多样,可能会造成二维码检测失败的问题。一种提高检测精度的方式就是把二维码在图片中单独抠出来,去除其它冗余信息,然后再去识别这张提取出来的二维码。本篇博客记录采用的一种实现二

    2024年02月03日
    浏览(37)
  • opencv检测二维码和条形码

    使用excel可以实现制作二维码,但只能实现做英文和数字类型的,步骤如下: 在任意单元格输入内容 选项卡里找到开发工具—插入—点击ActiveX控件的最右下角。 弹出的窗口内,往下滑动选择Microsoft BarCode Control 16.0后,点击确定。 在任意区域,摁住鼠标左键不放,拖动鼠标,

    2024年02月10日
    浏览(56)
  • opencv快速实现任意角度二维码矫正

    那天听到领导他们在讨论,说要将图片进行个矫正处理,还叫来了算法部的大佬来讨论将要如何处理这个,讨论场面很是激烈 不得不说好奇心是个很神奇的东西,就把我给吸引过去了 我定眼一看,感觉作为JAVA开发的我自己也能进行处理 因为看到了图片后,发现了图片中一个

    2024年02月05日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包