位置: IT常识 - 正文

Python计算机视觉———照相机标定

编辑:rootadmin
Python计算机视觉———照相机标定

推荐整理分享Python计算机视觉———照相机标定,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

一、实验原理

1.1相机标定简介

1.2算法流程

1.3相机标定原理

1.4矩阵计算

1.5相机标定参数求解

二、代码及实现运行

2.1代码实现

2.2运行结果

一、实验原理1.1相机标定简介

在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立相机成像的几何模型,这些几何模型参数就是相机参数。在大多数条件下这些参数必须通过实验与计算才能得到,这个求解参数的过程就称之为相机标定(或摄像机标定)。无论是在图像测量或者机器视觉应用中,相机参数的标定都是非常关键的环节,其标定结果的精度及算法的稳定性直接影响相机工作产生结果的准确性。因此,做好相机标定是做好后续工作的前提,提高标定精度是科研工作的重点所在。在零失真相机标定法中,每一个像素矢量在空间都是独立标定的,无需知道相机内部的结构,无需建立几何模型。

1.2算法流程

(1)打印一张棋盘方格图并贴在一个平面上 (2)从不同角度拍摄若干张模板图像 (3)检测出图像中的特征点 (4)由检测到的特征点计算出每幅图像中的平面投影矩阵H (5)确定出摄像机的参数

相机标定方法有:传统相机标定法、主动视觉相机标定方法、相机自标定法、零失真相机标定法。

传统相机标定法需要使用尺寸已知的标定物,通过建立标定物上坐标已知的点与其图像点之间的对应,利用一定的算法获得相机模型的内外参数。根据标定物的不同可分为三维标定物和平面型标定物。三维标定物可由单幅图像进行标定,标定精度较高,但高精密三维标定物的加工和维护较困难。平面型标定物比三维标定物制作简单,精度易保证,但标定时必须采用两幅或两幅以上的图像。传统相机标定法在标定过程中始终需要标定物,且标定物的制作精度会影响标定结果。同时有些场合不适合放置标定物也限制了传统相机标定法的应用。

目前出现的自标定算法中主要是利用相机运动的约束。相机的运动约束条件太强,因此使得其在实际中并不实用。利用场景约束主要是利用场景中的一些平行或者正交的信息。其中空间平行线在相机图像平面上的交点被称为消失点,它是射影几何中一个非常重要的特征,所以很多学者研究了基于消失点的相机自标定方法。自标定方法灵活性强,可对相机进行在线定标。但由于它是基于绝对二次曲线或曲面的方法,其算法鲁棒性差。

基于主动视觉的相机标定法是指已知相机的某些运动信息对相机进行标定。该方法不需要标定物,但需要控制相机做某些特殊运动,利用这种运动的特殊性可以计算出相机内部参数。基于主动视觉的相机标定法的优点是算法简单,往往能够获得线性解,故鲁棒性较高,缺点是系统的成本高、实验设备昂贵、实验条件要求高,而且不适合于运动参数未知或无法控制的场合。

零失真相机标定法是以LCD显示屏为参考基准,以相移光栅为媒介,建立LCD像素与相机传感器像素之间的映射关系,确定每个相机像素点在LCD上的视点位置。镜头使相机在LCD上的视场为非矩形。在这个有畸变的视场内,可以构造一个内接的虚拟传感器,并保持相同的像素数。这样每个虚拟像素点就一定落在某四个相邻视点构成的任意四边形之内。虚拟像素点的亮度将由这四点的亮度经加权插值确定,而与其它像素点无关。用这四个加权系数的集合对原始图像作重采样(四次乘法、四次加法),就可以得到零畸变的输出图。对彩色相机的RGB三通道分别处理,但选用一个公共的虚拟传感器,则合成的彩色图像将是零畸变、零色差的。每个像素点(物理视点和虚拟点)的位置误差都是零均值,均方差都可小于1/1,000像素点距。

1.3相机标定原理

世界坐标系(world coordinate system) 用户定义的三维世界的坐标系,为了描述目标物在真实世界里的位置而被引入,坐标 (xw, yw, zw),单位为m。 相机坐标系(camera coordinate system) 在相机上建立的坐标系,为了从相机的角度描述物体位置而定义,作为沟通世界坐标系和图像/像素坐标系的中间一环,坐标 (xc, yc, zc),单位为m。 图像坐标系(image coordinate system) 也有看到称作“像平面坐标系”的,为了描述成像过程中物体从相机坐标系到图像坐标系的投影透射关系而引入,方便进一步得到像素坐标系下的坐标,坐标 (x,y),单位为m。 像素坐标系(pixel coordinate system) 为了描述物体成像后的像点在数字图像上的坐标而引入,是我们真正从相机内读取到的信息所在的坐标系,坐标 (u,v),单位为pixels(像素数目)  

针孔相机模型

 

图像径向畸变是图像像素点以畸变中心为中心点,沿着径向产生的位置偏差,从而导致图像中所成的像发生形变。图像径向畸变是成像过程中最主要的畸变,同时也是对成像效果影响最大的畸变。图像的径向畸变的存在不仅影响了图像视觉效果,而且增加了后续识别、跟踪等图像处理算法的度。

 

 

1.4矩阵计算外参矩阵:Python计算机视觉———照相机标定

 

 

 计算单应性矩阵H

设三维世界坐标的点为 ,二维相机平面像素坐标为,所以标定用的棋盘格平面到图像平面的单应性关系为:  (其中,K为相机的内参矩阵,R为外部参数矩阵(旋转矩阵),T为平移向量。令:

设棋盘格位于Z=0的平面,定义旋转矩阵R的第i列为 ri, 则有:

于是空间到图像的映射可改为:H=λK[r1 r2 t] 其中H 是描述Homographic矩阵,可通过最小二乘,从角点世界坐标到图像坐标的关系求解。  

计算内参数矩阵

根据步骤1中的式子,令 H 为 H = [h1 h2 h3],则 [h1 h2 h3]=λK[r1 r2 t],再根据正交和归一化的约束可以得到等式:

即每个单应性矩阵能提供两个方程,而内参数矩阵包含5个参数,要求解,至少需要3个单应性矩阵。为了得到三个不同的单应性矩阵,我们使用至少三幅棋盘格平面的图片进行标定。通过改变相机与标定板之间的相对位置来得到三个不同的图片。为了方便计算,我们定义:

B 中的未知量可表示为6D 向量 b, 

设H中的第i列为 hi,,根据b的定义,可以推导出公式, 

 

最后推导出:

 

通过上式,我们可知当观测平面 n ≥ 3 时,即至少3幅棋盘格图像,可以得到b的唯一解,求得相机内参数矩阵K。 

1.5相机标定参数求解

 

 

 

 

 

二、代码及实现运行2.1代码实现生成棋盘:import cv2import sysimport numpy as npimage = np.ones([1080, 1920, 3], np.uint8) * 255x_nums = 14 y_nums = 7 square_pixel = 120 # 1080/9 = 120 pixelsx0 = square_pixely0 = square_pixeldef DrawSquare(): flag = -1 for i in range(y_nums): flag = 0 - flag for j in range(x_nums): if flag > 0: color = [0,0,0] else: color = [255,255,255] cv2.rectangle(image,(x0 + j*square_pixel,y0 + i*square_pixel), (x0 + j*square_pixel+square_pixel,y0 + i*square_pixel+square_pixel),color,-1) flag = 0 - flag cv2.imwrite('D:/chess_map_14x7.bmp',image)if __name__ == '__main__': DrawSquare()相机标定:import cv2import numpy as npimport glob#criteria:角点精准化迭代过程的终止条件criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)#棋盘格模板规格len = 18#黑白格长度w = 6h = 13# 世界坐标系中的棋盘格点,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐标,记为二维矩阵world_point = np.zeros((w*h, 3), np.float32)#初始化一个6*13行3列的矩阵,类型为float#把每一个世界坐标的xy赋值[:,:2]中,:表示列表的所有字列表全部,:2表示从1截止到第二个数字world_point[:, :2] = np.mgrid[0:w*len:len, 0:h*len:len].T.reshape(-1, 2)# 储存棋盘格角点的世界坐标和图像坐标对world_points = [] # 在世界坐标系中的三维点imgpoints = [] # 在图像平面的二维点j=1images = glob.glob('*.jpg')#读取所有jpg文件for fname in images: img = cv2.imread(fname) #将图片缩小 img = cv2.resize(img,None,fx=0.4, fy=0.4, interpolation = cv2.INTER_CUBIC) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 找到棋盘格角点 #寻找角点,存入corners,ret是找到角点的flag(如果找到角点则为true) ret, corners = cv2.findChessboardCorners(gray, (w, h), None) # 如果找到足够点对,将其存储起来 if ret is True: cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) #加入到世界坐标系 world_points.append(world_point) #角点加入到图像坐标系 imgpoints.append(corners) # 将角点在图像上显示 cv2.drawChessboardCorners(img, (w, h), corners, ret) cv2.imshow('findCorners', img) cv2.waitKey(1) print(str(j)+"完成\n") j+=1 else: print('错误') j+=1cv2.destroyAllWindows()#求解摄像机的内在参数和外在参数。mtx 内参数矩阵,dist 畸变系数,rvecs 旋转向量,tvecs 平移向量 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(world_points, imgpoints, gray.shape[::-1], None, None)# 找棋盘格角点# 去畸变img2 = cv2.imread('1.jpg')img2= cv2.resize(img2,None,fx=0.4, fy=0.4, interpolation = cv2.INTER_CUBIC)cv2.imshow("畸变图像", img2)cv2.waitKey(100)cv2.destroyAllWindows()h, w = img2.shape[:2]#内参数矩阵newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 0, (w, h)) # 自由比例参数#校正后图像dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)cv2.imwrite('calibresult.png', dst)f = open('内参数矩阵.txt', 'w+')f.write('内参数矩阵:\n'+str(newcameramtx)+'\n')f.close()print('内参数输出完毕')f = open('外参数矩阵.txt', 'w+')#得到旋转矩阵与平移for t in range(0,j-1):#向量变为矩阵 newrvecs=cv2.Rodrigues(rvecs[t].ravel()) newtvecs=cv2.Rodrigues(tvecs[t].ravel()) f.write('第'+str(t+1)+'张图像的外参数矩阵:\n'+'(1)旋转矩阵:\n'+str(newrvecs[0])+'\n'+'(2)平移矩阵:\n'+str(newtvecs[0])+'\n') t+=1f.close()print('外参数输出完毕')f = open('畸变系数.txt', 'w+')f.write('畸变系数:\n'+str(dist)+'\n')f.close()print('结果输出完毕')np.savez('data.npz', mtx= mtx, dist= dist,rvecs=rvecs,tvecs=tvecs)print('*.npz文件输出完毕')三维立方体:import cv2import numpy as npimport glob#加载数据with np.load('data.npz') as X:#加载上一部生成的参数mtx, dist, _, _= [X[i] for i in ('mtx','dist','rvecs','tvecs')]#criteria:角点精准化迭代过程的终止条件criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)#棋盘格模板规格len = 18#黑白格长度w = 6h = 13#画坐标轴和立方体def draw(img, corners, imgpts,imgpts2): corner=tuple(corners[0].ravel())#ravel()方法将数组维度拉成一维数组 # img要画的图像,corner起点,tuple终点,颜色,粗细 img= cv2.line(img, corner, tuple(imgpts2[0].ravel()), (255,0,0), 8) img= cv2.line(img, corner, tuple(imgpts2[1].ravel()), (0,255,0), 8) img= cv2.line(img, corner, tuple(imgpts2[2].ravel()), (0,0,255), 8) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img,'X',tuple(imgpts2[0].ravel()+2), font, 1,( 255,0,0),2,cv2.LINE_AA) cv2.putText(img,'Y',tuple(imgpts2[1].ravel()+2), font, 1,( 0,255,0),2,cv2.LINE_AA) cv2.putText(img,'Z',tuple(imgpts2[2].ravel()+2), font, 1,( 0,0,255),2,cv2.LINE_AA) imgpts= np.int32(imgpts).reshape(-1,2)#draw ground floor in green for i,j in zip(range(4),range(4,8)):#正方体顶点逐个连接 img= cv2.line(img, tuple(imgpts[i]), tuple(imgpts[j]),(255,215,0),3)#draw top layer in red color #imgpts[4:]是八个顶点中上面四个顶点 #imgpts[:4]是八个顶点中下面四个顶点 #用函数drawContours画出上下两个盖子,它的第一个参数是原始图像,第二个参数是轮廓,一个python列表,第三个参数是轮廓的索引(当设置为-1时绘制所有轮廓) img = cv2.drawContours(img, [imgpts[4:]],-1,(255,215,0),3) img = cv2.drawContours(img, [imgpts[:4]],-1,(255,215,0),3) return imgobjp= np.zeros((w*h,3), np.float32)objp[:,:2] = np.mgrid[0:w*len:len,0:h*len:len].T.reshape(-1,2)axis = np.float32([[0,0,0], [0,2*len,0], [2*len,2*len,0], [2*len,0,0],[0,0,-2*len],[0,2*len,-2*len],[2*len,2*len,-2*len],[2*len,0,-2*len] ])axis2= np.float32([[3*len,0,0], [0,3*len,0], [0,0,-3*len]]).reshape(-1,3)images = glob.glob('*.jpg')i=1;for fname in images: img = cv2.imread(fname) img = cv2.resize(img,None,fx=0.4, fy=0.4, interpolation = cv2.INTER_CUBIC) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 找到棋盘格角点 #寻找角点,存入corners,ret是找到角点的flag ret, corners = cv2.findChessboardCorners(gray, (w, h), None) if ret is True: corners2= cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria) #求解物体位姿的需要 _,rvecs, tvecs, inliers =cv2.solvePnPRansac(objp, corners2, mtx, dist) #projectPoints()根据所给的3D坐标和已知的几何变换来求解投影后的2D坐标。 #imgpts是整体的8个顶点 imgpts,_=cv2.projectPoints(axis, rvecs, tvecs, mtx, dist) #imgpts2是三个坐标轴的x,y,z划线终点 imgpts2, _ =cv2.projectPoints(axis2, rvecs, tvecs, mtx, dist) img=draw(img,corners2,imgpts,imgpts2) cv2.imshow('世界坐标系与小盒子',img) cv2.imwrite(str(i)+'.png', img) cv2.waitKey(1000) i+=1;cv2.destroyAllWindows()print("完毕")2.2运行结果

 

 

 

 

本文链接地址:https://www.jiuchutong.com/zhishi/299286.html 转载请保留说明!

上一篇:全面带你了解AIGC的风口

下一篇:Vue3 从入门到放弃 (第一篇.环境准备)(vue3的)

  • 微信来电音乐在哪里设置(微信来电音乐在哪里取消)

    微信来电音乐在哪里设置(微信来电音乐在哪里取消)

  • 微信朋友圈怎么发布(微信朋友圈怎么@一个人)

    微信朋友圈怎么发布(微信朋友圈怎么@一个人)

  • 雄迈摄像头恢复出厂设置(雄迈摄像头恢复出厂设置后还是原来)

    雄迈摄像头恢复出厂设置(雄迈摄像头恢复出厂设置后还是原来)

  • 苹果x多久充满才算正常(苹果x多久充满电正常)

    苹果x多久充满才算正常(苹果x多久充满电正常)

  • iphone虚拟home键不见了(iphone虚拟home键怎么设置功能)

    iphone虚拟home键不见了(iphone虚拟home键怎么设置功能)

  • 魅族手机流量自动打开怎么处理(魅族手机流量自动开启)

    魅族手机流量自动打开怎么处理(魅族手机流量自动开启)

  • 惠普m126a硒鼓型号(惠普m126a硒鼓型号怎么添加苹果笔记本)

    惠普m126a硒鼓型号(惠普m126a硒鼓型号怎么添加苹果笔记本)

  • 蚂蚁森林时间可以改吗(蚂蚁森林可以隐身吗)

    蚂蚁森林时间可以改吗(蚂蚁森林可以隐身吗)

  • 诊断策略服务未运行不能上网(诊断策略服务未运行win7)

    诊断策略服务未运行不能上网(诊断策略服务未运行win7)

  • 为什么微信打字键盘在上面移不下来(为什么微信打字没有表情包)

    为什么微信打字键盘在上面移不下来(为什么微信打字没有表情包)

  • 苹果新换的电池掉电快(苹果新换的电池充不进去电)

    苹果新换的电池掉电快(苹果新换的电池充不进去电)

  • 苹果通话记录背景变成黑色了(苹果通话记录背景页面怎么设置)

    苹果通话记录背景变成黑色了(苹果通话记录背景页面怎么设置)

  • 微软型号1724是几代(微软型号1873)

    微软型号1724是几代(微软型号1873)

  • icp备案如何办理(icp备案步骤)

    icp备案如何办理(icp备案步骤)

  • 手机怎么拦截外地号码(手机怎么拦截外国号码华为手机)

    手机怎么拦截外地号码(手机怎么拦截外国号码华为手机)

  • 淘宝积分什么时候清零(淘宝积分什么时候更新一次)

    淘宝积分什么时候清零(淘宝积分什么时候更新一次)

  • 手机显示未接通是什么意思(手机显示未接来电)

    手机显示未接通是什么意思(手机显示未接来电)

  • xsmax分辨率是多少(xsmax分辨率多少p)

    xsmax分辨率是多少(xsmax分辨率多少p)

  • ipadmini和ipadair和ipad pro的区别(ipad和ipadair哪个更好)

    ipadmini和ipadair和ipad pro的区别(ipad和ipadair哪个更好)

  • 如何查询airpods真伪(如何查询airpods激活时间)

    如何查询airpods真伪(如何查询airpods激活时间)

  • 小米5耗电快怎么办(小米耗电快怎么回事)

    小米5耗电快怎么办(小米耗电快怎么回事)

  • 140940(140940kg是多少吨)

    140940(140940kg是多少吨)

  • word自动生成目录步骤(word自动生成目录只有一半怎么回事)

    word自动生成目录步骤(word自动生成目录只有一半怎么回事)

  • 苹果蓝牙耳机二代区别(苹果蓝牙耳机二代怎么辨别真假)

    苹果蓝牙耳机二代区别(苹果蓝牙耳机二代怎么辨别真假)

  • 网络拒绝接入是怎么回事(网络拒绝接入是不是别人设置了)

    网络拒绝接入是怎么回事(网络拒绝接入是不是别人设置了)

  • 怎么快速判断哪些进程是系统进程最简单的方法(如何快速判断)

    怎么快速判断哪些进程是系统进程最简单的方法(如何快速判断)

  • 得了遗尿症应该怎么办?(得了遗尿症应该怎么办)

    得了遗尿症应该怎么办?(得了遗尿症应该怎么办)

  • c语言中有哪些循环语句(c语言中有哪些循环结构)

    c语言中有哪些循环语句(c语言中有哪些循环结构)

  • 留抵税额是什么意思啊
  • 印花税的计税依据为各种应税凭证上所记载的计税金额
  • 非居民个人如何认定
  • 如何解除委托合同范文
  • 合并报表是把资产负债表相加吗
  • 汇算退回的所得税分录
  • 应收账款计入借方贷方
  • 应交税费是没有增值税吗
  • 劳务公司劳务协议范本
  • 青年企业家协会入会要求
  • 成本组成计税价格公式
  • 营改增前未完工的老项目可以开专票吗
  • 增值税普通发票查询真伪
  • 服务合同需要征税吗
  • 会计中应收账款的英文
  • 应付账款是负数怎么回事
  • 其他非流动负债包括哪些科目
  • 当月不抵扣的增值税发票怎么做账
  • 航天信息服务费的会计分录
  • 专项维修基金和契税有什么区别
  • 应纳税所得额是开票金额吗
  • 应收账款年末余额过大
  • 跨期费用会计处理
  • 增值税税控系统技术维护费每年都可以抵扣吗
  • 财务会计制度备案操作流程
  • 新版edge浏览器文字不显示
  • 在linux2.4.0版本中
  • type3插件
  • 金税盘的服务费
  • php .htaccess
  • 其他应收款年末怎么处理
  • 薏米红豆粥的做法视频
  • 预收房屋租金
  • 财务运作规律
  • 发票开错重新开票怎么做账务处理?
  • php使用crypt()函数进行加密
  • 终身职业技能培训
  • 井下生产安全知识
  • 免费镜像翻转软件
  • 结转已销售产品的实际生产成本会计分录
  • ajax向php传值
  • 序列标注技术应用
  • 学长学姐面试要注意哪些细节
  • 财政拨入的科技费是什么
  • 个体工商户超过100万怎么缴税
  • 实缴的钱注销后可以拿回来吗
  • 无偿提供房屋使用证明有什么后果
  • 企业付美金外汇要交税吗
  • 外汇保值业务的特点包括
  • 受托加工的物资是存货吗
  • 安装SQL2005的实训体会
  • mysql正则表达式匹配数字
  • 对公账户有法律效力吗
  • 一次性伤残补助金怎么计算
  • 利润减负债
  • 企业所得税计算题及答案解析
  • 农民专业合作社法
  • 先收款后给发票合法吗
  • 员工缴纳工伤保险怎么赔偿
  • 发票开错是不是可以作废?
  • 工程项目采购
  • 收到联营单位投入的款项98600元存入银行
  • 小规模免增值税吗
  • 跨年做进项税额转出
  • 不能抵扣的进项税怎么做账务处理
  • centos邮件服务器
  • xp系统开机一直在启动界面
  • windows2003密码破解
  • 电脑xp系统桌面
  • win10右键菜单管理在哪打开
  • winxp能玩啥大型游戏
  • cocos2dx开发的游戏
  • Jqgrid之强大的表格插件应用
  • python抢红包
  • android事件响应和处理机制
  • animate如何拖动图片
  • js格式化时间戳
  • Android ORM之GreenDao学习
  • 十万元版增值税税率13发票最高开多少
  • 图书销售税点
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设