智慧交通day03-车道线检测实现03:相机校正和图像校正的实现

简介: 标定的图片需要使用棋盘格数据在不同位置、不同角度、不同姿态下拍摄的图片,最少需要3张,当然多多益善,通常是10-20张。该项目中我们使用了20张图片

1.相机标定


根据张正友校正算法,利用棋盘格数据校正对车载相机进行校正,计算其内参矩阵,外参矩阵和畸变系数。


标定的流程是:


  • 准备棋盘格数据,即用于标定的图片
  • 对每一张图片提取角点信息
  • 在棋盘上绘制提取到的角点(非必须,只是为了显示结果)
  • 利用提取的角点对相机进行标定
  • 获取相机的参数信息


1.1. 标定的图片


标定的图片需要使用棋盘格数据在不同位置、不同角度、不同姿态下拍摄的图片,最少需要3张,当然多多益善,通常是10-20张。该项目中我们使用了20张图片,如下图所示:


71e789866b9e4151a164bdb6c0d02aa8.png


把这些图片存放在项目路径中的camera_cal文件夹中。


1.2. 相机校正


下面我们对相机进行校正,OPenCV中提供了对相机进行校正的代码,在本项目中直接使用opencv中的API进行相机的校正,如下所示:


# 1. 参数设定:定义棋盘横向和纵向的角点个数并指定校正图像的位置
nx = 9
ny = 6
file_paths = glob.glob("./camera_cal/calibration*.jpg")
# 2. 计算相机的内外参数及畸变系数
def cal_calibrate_params(file_paths):
    object_points = []  # 三维空间中的点:3D
    image_points = []   # 图像空间中的点:2d
    # 2.1 生成真实的交点坐标:类似(0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)的三维点
    objp = np.zeros((nx * ny, 3), np.float32)
    objp[:, :2] = np.mgrid[0:nx, 0:ny].T.reshape(-1, 2)  
    # 2.2 检测每幅图像角点坐标
    for file_path in file_paths:
        img = cv2.imread(file_path)
        # 将图像转换为灰度图
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # 自动检测棋盘格内4个棋盘格的角点(2白2黑的交点)
        rect, corners = cv2.findChessboardCorners(gray, (nx, ny), None)
        # 若检测到角点,则将其存储到object_points和image_points
        if rect == True:
            object_points.append(objp)
            image_points.append(corners)
    # 2.3 获取相机参数
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None)
    return ret, mtx, dist, rvecs, tvecs


在这里有几个API给大家介绍下:


1.寻找棋盘图中的棋盘角点


rect, corners = cv2.findChessboardCorners(image, pattern_size, flags)


参数:


  • Image: 输入的棋盘图,必须是8位的灰度或者彩色图像


  • Pattern_size:棋盘图中每行每列的角点个数(内角点)。


  • flags: 用来定义额外的滤波步骤以有助于寻找棋盘角点。所有的变量都可以单独或者以逻辑或的方式组合使用。取值主要有:


CV_CALIB_CB_ADAPTIVE_THRESH :使用自适应阈值(通过平均图像亮度计算得到)将图像转换为黑白图,而不是一个固定的阈值。


CV_CALIB_CB_NORMALIZE_IMAGE :在利用固定阈值或者自适应的阈值进行二值化之前,先使用cvNormalizeHist来均衡化图像亮度。


CV_CALIB_CB_FILTER_QUADS :使用其他的准则(如轮廓面积,周长,方形形状)来去除在轮廓检测阶段检测到的错误方块。


返回:


  • Corners:检测到的角点


  • rect: 输出是否找到角点,找到角点返回1,否则返回0


  • 检测完角点之后我们可以将将测到的角点绘制在图像上,使用的API是:


cv2.drawChessboardCorners(img, pattern_size, corners, rect)


参数:


  • Img: 预绘制检测角点的图像
  • pattern_size : 预绘制的角点的形状
  • corners: 角点矩阵
  • rect: 表示是否所有的棋盘角点被找到,可以设置为findChessboardCorners的返回值


注意:如果发现了所有的角点,那么角点将用不同颜色绘制(每行使用单独的颜色绘制),并且把角点以一定顺序用线连接起来,如下图所示:


33a8f24862144a7eb9df3e88d731616b.png


  • 利用定标的结果计算内外参数


ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, image_size, None, None)


参数:


  • Object_points:世界坐标系中的点,在使用棋盘的场合,我们令z的坐标值为0,而x,y坐标用里面来度量,选用英寸单位,那么所有参数计算的结果也是用英寸表示。最简单的方式是我们定义棋盘的每一个方块为一个单位。
  • image_points:在图像中寻找到的角点的坐标,包含object_points所提供的所有点
  • image_size: 图像的大小,以像素为衡量单位


返回:


  • ret: 返回值


  • mtx: 相机的内参矩阵,大小为3*3的矩阵


  • dist: 畸变系数,为5*1大小的矢量


  • rvecs: 旋转变量


  • tvecs: 平移变量


1.3 图像去畸变


效果预览:


                       处理前: fc189a1e031d4a078d4fffa9aef70810.png 处理后:738de205ce614da8a81be4e0b6d4c3a4.png


上一步中我们已经得到相机的内参及畸变系数,我们利用其进行图像的去畸变,最直接的方法就是调用opencv中的函数得到去畸变的图像:


def img_undistort(img, mtx, dist):
    dst = cv2.undistort(img, mtx, dist, None, mtx)
    return dst


我们看下求畸变的API:


dst = cv2.undistort(img, mtx, dist, None, mtx)


参数:


  • Img: 要进行校正的图像
  • mtx: 相机的内参
  • dist: 相机的畸变系数


返回:


  • dst: 图像校正后的结果


31e3214de04b4d069e65e15147c66913.png


总结:


1.标定的图片


不同角度和方向拍摄的棋盘格图片数据


2.相机校正


检测棋盘格数据的角点:


cv2.findChessboardCorners()


计算相机的内参数和外参数:cv2.calibrateCamera()


3.图像去畸变


cv2.undistort()


代码总览:


# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#遍历文件夹
import glob
from moviepy.editor import VideoFileClip
"""参数设置"""
nx = 9
ny = 6
#获取棋盘格数据
file_paths = glob.glob("./camera_cal/calibration*.jpg")
# 绘制对比图
def plot_contrast_image(origin_img, converted_img, origin_img_title="origin_img", converted_img_title="converted_img",
                        converted_img_gray=False):
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 20))
    ax1.set_title = origin_img_title
    ax1.imshow(origin_img)
    ax2.set_title = converted_img_title
    if converted_img_gray == True:
        ax2.imshow(converted_img, cmap="gray")
    else:
        ax2.imshow(converted_img)
    plt.show()
#相机矫正使用opencv封装好的api
#目的:得到内参、外参、畸变系数
def cal_calibrate_params(file_paths):
    #存储角点数据的坐标
    object_points = [] #角点在真实三维空间的位置
    image_points = [] #角点在图像空间中的位置
    #生成角点在真实世界中的位置
    objp = np.zeros((nx*ny,3),np.float32)
    #以棋盘格作为坐标,每相邻的黑白棋的相差1
    objp[:,:2] = np.mgrid[0:nx,0:ny].T.reshape(-1,2)
    #角点检测
    for file_path in file_paths:
        img = cv2.imread(file_path)
        #将图像灰度化
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        #角点检测
        rect,coners = cv2.findChessboardCorners(gray,(nx,ny),None)
        #角点检测结果的绘制
        # imgcopy = img.copy()
        # cv2.drawChessboardCorners(imgcopy,(nx,ny),coners,rect)
        # plot_contrast_image(img,imgcopy)
        #若检测到角点,则进行保存 即得到了真实坐标和图像坐标
        if rect == True :
            object_points.append(objp)
            image_points.append(coners)
    # 相机较真
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None)
    return ret, mtx, dist, rvecs, tvecs
# 图像去畸变:利用相机校正的内参,畸变系数
def img_undistort(img, mtx, dist):
    dis = cv2.undistort(img, mtx, dist, None, mtx)
    return dis
if __name__ == "__main__":
    ret, mtx, dist, rvecs, tvecs =cal_calibrate_params(file_paths)
    if np.all(mtx!=None):
        img = cv2.imread("test/test1.jpg")
        undistort_img = img_undistort(img,mtx,dist)
        plot_contrast_image(img,undistort_img)
        print("done")
    else:
        print("failed")
目录
相关文章
|
1月前
|
编解码 机器人
标定系列一、手眼标定基础介绍
标定系列一、手眼标定基础介绍
|
7月前
|
机器学习/深度学习 传感器 算法
使用显著性检测的可见光和红外图像的两尺度图像融合(Matlab代码实现)
使用显著性检测的可见光和红外图像的两尺度图像融合(Matlab代码实现)
|
3月前
|
机器学习/深度学习 算法 前端开发
高速公路表面图像裂缝检测程序
高速公路表面图像裂缝检测程序
|
4月前
|
传感器 机器学习/深度学习 存储
使用激光雷达(LiDAR)和相机进行3D物体跟踪
使用激光雷达(LiDAR)和相机进行3D物体跟踪
|
9月前
|
传感器
使用校准相机测量平面物体
使用校准相机测量平面物体。
83 0
|
9月前
检测使用校准的立体摄像头拍摄的视频中的人物并确定其与摄像头的距离
检测使用校准的立体摄像头拍摄的视频中的人物,并确定他们与摄像头的距离。
99 0
|
9月前
|
机器学习/深度学习 传感器 安全
【目标检测】基于背景差分实现运动车辆检测附Matlab代码
【目标检测】基于背景差分实现运动车辆检测附Matlab代码
|
10月前
|
机器学习/深度学习 传感器 编解码
【车道线检测】基于计算机视觉实现车道线视频检测附matlab代码
【车道线检测】基于计算机视觉实现车道线视频检测附matlab代码
|
11月前
|
传感器 算法 智慧交通
智慧交通day03-车道线检测实现02-1:相机校正
我们所处的世界是三维的,而照片是二维的,我们可以把相机认为是一个函数,输入量是一个场景,输出量是一幅灰度图。这个从三维到二维的过程的函数是不可逆的。
113 0
|
11月前
|
机器学习/深度学习 传感器 算法
智慧交通day03-车道线检测实现02-2:张氏标定法+双目标定
该方法介于传统标定法和自标定法之间,既克服了传统标定法需要的高精度三维标定物的缺点,又解决了自标定法鲁棒性差的难题。标定过程不需要特殊的标定物,只需使用一张打印出来的棋盘格,并从不同方向拍摄几组图片即可,不仅实用灵活方便,而且精度很高,鲁棒性好。因此很快被全世界广泛采用,极大的促进了三维计算机视觉从实验室走向真实世界的进程。
222 0