首页 > 编程语言 >张正友棋盘代码-python

张正友棋盘代码-python

时间:2024-01-10 17:11:37浏览次数:40  
标签:张正友 mtx dist img python cv2 标定 path 棋盘

具体实现方案:

棋盘是一块由黑白方块间隔组成的标定板,我们用它来作为相机标定的标定物(从真实世界映射到数字图像内的对象)。之所以我们用棋盘作为标定物是因为平面棋盘模式更容易处理(相对于复杂的三维物体),但与此同时,二维物体相对于三维物体会缺少一部分信息,于是我们会多次改变棋盘的方位来捕捉图像,以求获得更丰富的坐标信息。

下面将依次对刚体进行一系列变换,使之从世界坐标系进行仿射变换、投影透射,最终得到像素坐标系下的离散图像点,过程中会逐步引入各参数矩阵。

标定图片需要使用标定板在不同位置、不同角度、不同姿态下拍摄,最少需要3张,以10~20张为宜。标定板需要是黑白相间的矩形构成的棋盘图,制作精度要求较高,如下图所示:

标定步骤:

1、打印一张棋盘格,把它贴在一个平面上,作为标定物。
2、通过调整标定物或摄像机的方向,为标定物拍摄一些不同方向的照片。
3、从照片中提取棋盘格角点。
4、估算理想无畸变的情况下,五个内参和六个外参。
5、应用最小二乘法估算实际存在径向畸变下的畸变系数。
6、极大似然法,优化估计,提升估计精度。

import cv2
import numpy as np
import glob

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

w = 8
h = 6


objp = np.zeros((w*h,3), np.float32)
objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2)
objp = 2 * objp
objpoints = []
imgpoints = []

def get_internal_reference(path):
    images = glob.glob(path + '/*.jpg')
    for frame in images:
        img = cv2.imread(frame)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        ret, corners = cv2.findChessboardCorners(gray, (w,h),None)   #在灰度图像 gray 中找到棋盘格角点
        if ret:
            cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)  #亚像素级别的角点精确化
            objpoints.append(objp)#将世界坐标系中的棋盘格角点的理论坐标(objp)加入 objpoints 和 imgpoints 中。
            # 这些点用于后续相机标定的计算。
            imgpoints.append(corners)#图像坐标系中检测到的角点坐标(corners)加入  imgpoints 中
            cv2.drawChessboardCorners(img, (w,h), corners, ret)
        # cv2.imshow('draw',img)
        # cv2.waitKey(0)
    #利用棋盘格角点的理论坐标和图像坐标进行相机标定。

    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
    # ret表示的是重投影误差;mtx是相机的内参矩阵;dist表述的相机畸变参数;
    # rvecs表示标定棋盘格世界坐标系到相机坐标系的旋转参数:rotation vectors,需要进行罗德里格斯转换;
    # tvecs表示translation vectors,主要是平移参数。
    #返回相机矩阵 mtx 和畸变参数 dist
    return ret, mtx, dist, rvecs, tvecs

以上为获得参数矩阵的代码。若要对一组图像进行标定,使用以下函数调用以上代码。

from calibration import get_internal_reference
def camera_calibration(path):  # path为棋盘标定内参的图片路径
    if os.path.exists(path):
        ret, mtx, dist, rvecs, tvecs = get_internal_reference(path)
    else:
        os.makedirs(path)
        cap = cv2.VideoCapture(0)
        count = 0
        i = 1
        EXTRACT_FREQUENCY = 10
        while len(os.listdir(path)) < 25:
            _, frame = cap.read()
            if frame is None:
                break
            if count % EXTRACT_FREQUENCY == 0:
                save_path = '{}/{}.jpg'.format(path, i)
                cv2.imwrite(save_path, frame)
                cv2.imshow('calibration_img', frame)
                cv2.waitKey(1000)
                i += 1
            count += 1
        cv2.destroyAllWindows()
        ret, mtx, dist, rvecs, tvecs = get_internal_reference(path)
    return ret, mtx, dist, rvecs, tvecs #(mtx是相机的内参矩阵;dist表述的相机畸变参数;)
ret, mtx, dist, rvecs, tvecs = camera_calibration('img')

img=cv2.imread('img/1.jpg',cv2.IMREAD_GRAYSCALE)
u, v = img.shape[:2]
# img=cv2.imread('E:/project/calibration images/1.jpg',cv2.IMREAD_GRAYSCALE)
# 校正图像
h,w = img.shape
print(h,w)

new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (u, v ), 0, (u, v ))
undistorted_image = cv2.undistort(img, mtx, dist, None, new_camera_matrix)
# undistorted_image = cv2.undistort(img, np.array(mtx), np.array(dist))
img_diff = cv2.absdiff(img, undistorted_image)
cv2.imshow('img',img)
cv2.imshow('yun',undistorted_image)
cv2.imshow('yun1',img_diff)
cv2.waitKey(0)
cv2.destroyAllWindows()

即可得到矫正结果。如下显示

以下为标定图像和原图的差异图

 

 

 

 

 

 

标签:张正友,mtx,dist,img,python,cv2,标定,path,棋盘
From: https://www.cnblogs.com/heyrroo/p/17956888

相关文章

  • python3可视化之matplotlib库
     importmatplotlib.pyplotaspltimportnumpyasnpN=8i=0#指定一个画板fig=plt.figure(figsize=(20,5*N))x=np.arange(0,3*np.pi,0.1)y_sin=np.sin(x)y_cos=np.cos(x)i+=1plt.subplot(N,1,i)plt.plot(x,y_sin)plt.plot(x,y_cos)plt......
  • python3控制结构
    选择n=10i=2ifn==i:print("equal")elifn<i:print("lower")else:print("higher")遍历whilei<n:i+=1print(i)else:print("done")foriinrange(0,5):print(i)else:......
  • python3图片处理之pillow库
    pillow库简单使用fromPILimportImage,ImageFilter#pillow库img=Image.open("../../files/1.jpg")#通道print(img.getbands())#('R','G','B')print(img.getbbox())#(0,0,690,517)#图片的尺寸print(img.size)#(690......
  • Python对于for循环,可以用range()来控制循环次数,写法:range(次数)
    '''for循环次数循环的是列表、集合、元组、字典、字符串,这些类型中保存了几个数据值就循环几次'''#Python对于for循环,可以用range()来控制循环次数#写法:range(次数)name='Rocco'#设置变量name为字符串类型,值为'Rocco'ps='123456'#设置变量ps为字符串类型,值为'123456'......
  • Python中的迭代器和生成器是什么
    在Python中,迭代器和生成器是两个非常重要的概念。它们可以帮助我们更加高效地处理数据,并且在处理大数据集时具有很好的性能表现。本文将介绍Python中的迭代器和生成器,并详细讲解它们的用法和实现原理。迭代器什么是迭代器在Python中,迭代器(Iterator)是一种对象,它可以实现迭代器......
  • 在Python中如何使用列表推导式来创建一个列表
    在Python中,列表推导式(Listcomprehensions)是一种简洁、灵活、高效的语法,用于快速创建一个新的列表。它可以使代码更加简洁易读,并且比使用循环和条件语句手动构建列表要更加高效。列表推导式的基本语法如下:new_list=[expressionforiteminiterableifcondition]其中,`expressio......
  • 如何使用Python装饰器来修改函数
    在Python中,装饰器是一种强大的工具,它可以用来修改函数的行为,而无须对函数本身进行修改。装饰器提供了一种简洁、灵活的方式来扩展函数的功能,使代码更加模块化、可复用,并且能够减少重复的代码。装饰器的基本概念是将一个函数作为参数传递给另一个函数,并返回一个新的函数。这个新的函......
  • Python中的元类和元编程是什么
    在Python中,元类和元编程是一些高级概念,能够帮助我们更深入地理解和扩展语言的特性。通过元类和元编程,我们可以在运行时动态地创建类、修改类和实例化对象,从而使我们能够更加灵活地编写代码。1.元类是什么?在Python中,类是对象的模板,用于创建对象。而元类则是用于创建类的类。也就是说......
  • Python中的异常处理机制是什么
    在Python编程中,异常处理机制是一种重要的机制,用于捕获和处理程序中出现的异常情况。通过合理地使用异常处理,我们可以使程序更加健壮、稳定,并提供更好的用户体验。1.异常是什么?在编程中,异常是指在程序运行过程中发生的错误或异常情况。例如,除以零、索引越界、文件不存在等都属于异常......
  • Python中的lambda函数是什么
    在Python中,lambda函数是一种匿名函数,它可以快速创建简单的函数,通常只需要一行代码。lambda函数可以作为参数传递给其他函数,也可以用于列表推导式和其他地方需要函数的场景。基本语法lambda函数的基本语法如下:```lambdaarguments:expression```其中,`arguments`表示函数的参数,可以......