ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

相机标定(python基础)

2021-10-03 09:32:40  阅读:181  来源: 互联网

标签:img python cv2 标定 相机 print 坐标系


引言:首先提出的问题是什么是相机标定?有什么作用呢?如何进行相机标定?

1.什么是相机标定?

        所谓的相机标定就是将外界世界的坐标信息转化为计算机(自带相机/摄像头)可以理解的“距离”,将世界坐标系转换到相机坐标系。我们可以理解为从一个坐标系转换到另一个坐标系所需要的转换关系就是相机标定。

        简单滴说:A=F(B),其中F()就是相机标定要做的工作。

2.有什么作用?(能干啥?)

        通俗地讲,例如:我和你在世界坐标系(平常我们所说的距离)下的距离为0.5m,但是相机并不知道我和你到底有多近!因此我们可以利用相机标定的方式,使相机知道我和你之间的距离。

3.如何进行相机标定:

1》世界坐标系、相机坐标系、图像坐标系。

        在相机标定之前,我们需要知道这三个坐标系概念:世界坐标系很常见,就是我们通常说的“我和你之间的距离”。相机坐标系:就是以相机聚焦中心为三维坐标原点而建立的坐标系。

         图像坐标系:就是在一幅图像上以左下角为二维坐标的原点所建立的二维平面。

(为了看的更清楚,本作将坐标系移动10个像素) 

2》相机标定流程:

1.准备标定数据集(一般为棋盘方格)。

2.提取角点信息(方格的各个交点,不包括边缘的点)

3.将世界坐标系------》相机坐标系。

4.将相机坐标系------》图像坐标系。

5.相机参数计算。

6.校验结果(审核标定结果准确度)

3.数据集建立。

        模板图片如图所示:

(多啰嗦几句!)

1》建立数据集时,你是用的拍摄设备就是你要标定的相机哦!

2》最好拍20—30张作为数据标定数据集。

4.参考代码

import cv2
import numpy as np
import glob
 
# 设置寻找亚像素角点的参数,采用的停止准则是最大循环次数30和最大误差容限0.001
criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)
 
# 获取标定板角点的位置
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)  # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y
 
obj_points = []    # 存储3D点
img_points = []    # 存储2D点
 
images = glob.glob("E:\python\Python Project\opencv_showimage\images\calibrateImages\*.jpg")
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    size = gray.shape[::-1]
    ret, corners = cv2.findChessboardCorners(gray, (7,6), None)
 
    if ret:
        obj_points.append(objp)
 
        corners2 = cv2.cornerSubPix(gray, corners, (5,5), (-1,-1), criteria)  # 在原角点的基础上寻找亚像素角点
        if corners2:
            img_points.append(corners2)
        else:
            img_points.append(corners)
 
        cv2.drawChessboardCorners(img, (7,6), corners, ret)   # 记住,OpenCV的绘制函数一般无返回值
        cv2.imshow('img', img)
        cv2.waitKey(50)
 
print len(img_points)
cv2.destroyAllWindows()
 
# 标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points,size, None, None)
 
print "ret:",ret
print "mtx:\n",mtx        # 内参数矩阵
print "dist:\n",dist      # 畸变系数   distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print "rvecs:\n",rvecs    # 旋转向量  # 外参数
print "tvecs:\n",tvecs    # 平移向量  # 外参数
 
print("-----------------------------------------------------")
# 畸变校正
img = cv2.imread(images[12])
h, w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
print newcameramtx
print("------------------使用undistort函数-------------------")
dst = cv2.undistort(img,mtx,dist,None,newcameramtx)
x,y,w,h = roi
dst1 = dst[y:y+h,x:x+w]
cv2.imwrite('calibresult11.jpg', dst1)
print "方法一:dst的大小为:", dst1.shape
 
# undistort方法二
print("-------------------使用重映射的方式-----------------------")
mapx,mapy = cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)  # 获取映射方程
#dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)      # 重映射
dst = cv2.remap(img,mapx,mapy,cv2.INTER_CUBIC)        # 重映射后,图像变小了
x,y,w,h = roi
dst2 = dst[y:y+h,x:x+w]
cv2.imwrite('calibresult11_2.jpg', dst2)
print "方法二:dst的大小为:", dst2.shape        # 图像比方法一的小
 
print("-------------------计算反向投影误差-----------------------")
tot_error = 0
for i in xrange(len(obj_points)):
    img_points2, _ = cv2.projectPoints(obj_points[i],rvecs[i],tvecs[i],mtx,dist)
    error = cv2.norm(img_points[i],img_points2, cv2.NORM_L2)/len(img_points2)
    tot_error += error
 
mean_error = tot_error/len(obj_points)
print "total error: ", tot_error
print "mean error: ", mean_error

特别注意:

我们最后求得的参数就是:(不要忘了我们的初心)

print "ret:",ret
print "mtx:\n",mtx        # 内参数矩阵
print "dist:\n",dist      # 畸变系数   distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print "rvecs:\n",rvecs    # 旋转向量  # 外参数
print "tvecs:\n",tvecs    # 平移向量  # 外参数

5.最后:

GAME OVER ! ! !

如果感觉不错,就点个赞吧!!!

欢迎小伙伴梦一起探讨学习,我们都是热爱学习的热血小年轻!!!

 

标签:img,python,cv2,标定,相机,print,坐标系
来源: https://blog.csdn.net/m0_56654441/article/details/120591434

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有