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

1.相机标定

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

标定的流程是:

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

1.1. 标定的图片

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

把这些图片存放在项目路径中的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 = []  # 三维空间中的点:3Dimage_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_pointsif 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的返回值

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

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

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 图像去畸变

效果预览:
                        处理前:  处理后:

上一步中我们已经得到相机的内参及畸变系数,我们利用其进行图像的去畸变,最直接的方法就是调用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: 图像校正后的结果


总结:

  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_titleax1.imshow(origin_img)ax2.set_title = converted_img_titleif 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)#以棋盘格作为坐标,每相邻的黑白棋的相差1objp[:,: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 disif __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")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/469644.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win10编辑js文件报错,错误','

在filezilla中编辑js文件报错,在本地可以使用文本编辑,但需重新上传覆盖,很不方便 在win10默认应用中修改为文本编辑即可,在FTP编辑: 直接可以打开编辑

智慧交通day03-车道线检测实现04:车道线提取原理+代码实现+效果图

我们基于图像的梯度和颜色特征,定位车道线的位置。 在这里选用Sobel边缘提取算法,Sobel相比于Canny的优秀之处在于,它可以选择横向或纵向的边缘进行提取。从车道的拍摄图像可以看出,我们关心的正是车道线在横向上的边缘突变。Ope…

linux下的shell编程

下面是一个最简单的shell: 例5:输入参数 $#是指参数个数、$是所有输入的参数 #! /bin/sh echo "$# parameters"; echo "$";wqfwqf-System-Product-Name:/worksen/linuxshell$ ./echo.sh ad 1 parameters ad新建一个shell. gedit echo.sh 输入以…

C#通过修改注册表改变IE默认选项

修改注册表,这个代码好实现,关键是怎么找到对应的注册表值,也就是说画一条线很容易,难的是找到要在哪里画,然后我百度了一圈,出来的都是画线的,没有指出或者指出的不全的注册表对应值&#xff0…

宝塔+wordpress搭建/迁移网站

使用宝塔linux和阿里云ECS搭建网站/从百度云服务器迁移网站到阿里云ECS 为服务器安装宝塔软件 示例: ECS:Ubuntu 18.04 打开阿里云控制台,进入已绑定的实例页面,使用workbench或者VNC(推荐使用workbench,workbench可…

智慧交通day03-车道线检测实现05:透视变换+代码实现

为了方便后续的直方图滑窗对车道线进行准确的定位,我们在这里利用透视变换将图像转换成俯视图,也可将俯视图恢复成原有的图像,代码如下: 计算透视变换所需的参数矩阵: def cal_perspective_params(img, points):offs…

LOCAL_MODULE_TAGS 选项说明(android编译选项选择)

LOCAL_MODULE_TAGS :user eng tests optional user: 指该模块只在user版本下才编译 eng: 指该模块只在eng版本下才编译 tests: 指该模块只在tests版本下才编译 optional:指该模块在所有版本下都编译 eng This is the default flavor. A plain "make" is t…

李宏毅老师ML_HW1——PM2.5预测

处理数据之前的pre-process 观察下载的数据文件train.csv train.csv只有每个月前20天的数据,另外每个月剩下10天数据用于作业结果评估,对学生不可见 观察数据发现rainfall栏有很多NR表示没有降雨,但是我们只需要数字,因此可以使用…

“员工请假”流程及在线表单开发示例

1. “员工请假”流程及在线表单开发示例 1.1. 描述 通过本示例达到快速对F2流程管理平台的在线表单速讯上手及零编码式的开发。实现一个以请假为示例的流程及在线表单,及请假数据的查询。 1.2. 目标效果 (1) 如何配置一个“请假在线表单” &a…

【Pytorch神经网络基础理论篇】 03 数据操作 + 数据预处理

同学你好!本文章于2021年末编写,已与实际存在较大的偏差! 故在2022年末对本系列进行填充与更新,欢迎大家订阅最新的专栏,获取基于Pytorch1.10版本的理论代码(2023版)实现, Pytorch深度学习理论篇(2023版)…

git版本控制系统常用指令,Xmind笔记整理

git仓库使用、项目版本管理基本常用指令 纯手工整理Xmind笔记: 点我下载 预览图: Png: 如有错误,谢谢指出

Spark学习(一) -- Spark安装及简介

标签(空格分隔): Spark 学习中的知识点:函数式编程、泛型编程、面向对象、并行编程。 任何工具的产生都会涉及这几个问题: 现实问题是什么?理论模型的提出。工程实现。思考: 数据规模达到一台机…

ValueError:only one element tensors can be converted to Python scalars

缘由是:要转换的list里面的元素包含多维的tensor。c

java起步

例1: javac HelloWorld.java 这是编译 java HelloWorld 这是运行 gedit helloworld.javapublic class helloworld {public static void main(String args[]){int num;num3;System.out.println("this is num"num);} }

Django基本概念、安装、配置到实现框架,Xmind学习笔记

Django从安装、配置到实现简单web框架的基本操作流程 纯手工Xmind笔记整理: 点我下载 预览图: 如有错误,谢谢指出

解决若要安装 Microsoft Office 2010,需要MSXML 版本 6.10.1129的问题

单击 开始单击 运行键入 注册表编辑器然后单击 确定.找到HKEY_CLASSES_ROOT\TypeLib\{F5078F18-C551-11D3-89B9-0000F81FE221}\6.0\0\win32。用鼠标右键单击 win32然后单击 权限.为自己授予完全控制到的项。双击 (默认值) 在下的值 win32然后再更改它的值…

ValueError matplotlib display text must have all code points 128 or use Unicode strings

错误问题&#xff1a;ValueError: matplotlib display text must have all code points < 128 or use Unicode strings 错误原因&#xff1a;在使用matplotlib进行图表展示时&#xff0c;如果需要在图表上添加中文&#xff0c;可能会报字符类型的值错误。 解决办法&#x…

VC6.0常见英文错误对照表

fatal error C1003: error count exceeds number; stopping compilation 中文对照&#xff1a;&#xff08;编译错误&#xff09;错误太多&#xff0c;停止编译 分析&#xff1a;修改之前的错误&#xff0c;再次编译 fatal error C1004: unexpected end of file found 中文…

Django 页面报错 Maximum recursion depth exceeded

Django 页面报错 Maximum recursion depth exceeded 原因&#xff1a; 视图中某个方法或函数的名称与django模块里的方法重名&#xff0c;而且在内部又调用了同名的方法导致重复调用自己 解决方法&#xff1a; 1、logout()换一个命名 # 退出登录使用logout(request)&#xf…

PAT (Basic Level) Practise 1045 快速排序(离散化+主席树区间内的区间求和)

1045. 快速排序(25) 时间限制200 ms内存限制 65536 kB代码长度限制 8000 B判题程序 Standard 作者 CAO, Peng著名的快速排序算法里有一个经典的划分过程&#xff1a;我们通常采用某种方法取一个元素作为主元&#xff0c;通过交换&#xff0c;把比主元小的元素放到它的左边&…