使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

这篇具有很好参考价值的文章主要介绍了使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

准备

        1、一张棋盘图

        可以直接从opencv官方github下载,这是一个拥有10*7个格子的棋盘,共有9*6个角点,每个格子24mm,本文所使用的就是这一个棋盘。你需要将它打印在A4纸上用于后续使用。(也可以根据官方教程自行设置棋盘大小OpenCV: Create calibration pattern)

opencv/pattern.png at 4.x · opencv/opencv · GitHub

使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

         2、一个双目摄像头

使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

        随便在tb买的一个不知名摄像头,附赠了一个.exe的测试工具用于简单使用摄像头效果如下

 使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

 使用opencv简单测试一下,我用的笔记本,接上usb摄像头就是从1开始了,这个双目摄像头虽然有两个输入index=1和index=2但是其实只需要获取index=1的那个视频流就可以得到双目效果。

import cv2
cap = cv2.VideoCapture(1)
cap.set(cv2.CAP_PROP_FRAME_WIDTH,1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,480)
while(1):
    _, frame = cap.read()
    assert _, "摄像头获取失败"
    cv2.imshow('img', frame)
    c = cv2.waitKey(1)
    if c == 27:
        cap.release()
        break

开启前必须将分辨率设置为正确的宽度,我的相机是1280,如果设置宽度不正确会导致无法正确得到双目图像

可以通过下面代码获取相机分辨率,主要是获得width,双目图的width应该为两个相机的width之和

import cv2
cap0 = cv2.VideoCapture(1)
cap1 = cv2.VideoCapture(2)
res0 = [cap0.get(cv2.CAP_PROP_FRAME_WIDTH),cap0.get(cv2.CAP_PROP_FRAME_HEIGHT)]
res1 = [cap1.get(cv2.CAP_PROP_FRAME_WIDTH),cap1.get(cv2.CAP_PROP_FRAME_HEIGHT)] 
print(res0)
print(res1)
cap0.release()
cap1.release()

分辨率正确的双目图(1280*480)

使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

分辨率错误的双目图(2560*480)使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

开始操作

先给棋盘拍照

import cv2,os
cap = cv2.VideoCapture(1)
cap.set(cv2.CAP_PROP_FRAME_WIDTH,1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
# 生成目录
path = './calibration/'
path_l = './calibration/left/'
path_r = './calibration/right/'
os.mkdir(path) if not os.path.exists(path) else None
os.mkdir(path_l) if not os.path.exists(path_l) else None
os.mkdir(path_r) if not os.path.exists(path_r) else None
count = 0
while cap.isOpened():
    ret, frame = cap.read()
    cv2.imshow('img',frame)
    k = cv2.waitKey(1)
    # 按下ESC退出
    if k == 27:
        break
    # 按下空格键暂停
    if k == 32:
        cv2.imshow('img',frame)
        # 再次按下空格保存
        if cv2.waitKey() == 32:            
            cv2.imwrite(path + "{}.jpg".format(count), frame)# 保存全图
            cv2.imwrite(path_l + "{}.jpg".format(count), frame[:,0:640])# 保存左图
            cv2.imwrite(path_r + "{}.jpg".format(count), frame[:,640:])# 保存右图
            count += 1
cv2.destroyAllWindows()
cap.release()

按照下图至少拍摄12对左右图像,以获得最佳效果

使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

 来源:Stereo Calibration for the Dual Camera Mezzanine - Blog - FPGA - element14 Community

 测试一下棋盘角点绘制

import cv2
img = cv2.imread('./calib/left/0.jpg')
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, corner = cv2.findChessboardCorners(img1, (9,6))
ret, corner = cv2.find4QuadCornerSubpix(img1, corner, (7,7))
cv2.drawChessboardCorners(img, (9,6), corner, ret)
cv2.imshow('corner', img)
cv2.waitKey(0)

使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

 接下来就获取矫正所需要的参数

import cv2, glob
import numpy as np
'''
获得标定所需参数
'''
# 定义棋盘格的大小
chessboard_size = (9, 6)
# 定义图像分辨率,根据自己相机的分辨率修改
imgsz = (640, 480)
# 定义棋盘格中每个格子的物理大小,自己用尺子量,单位为毫米(mm)
square_size = 24

# 定义棋盘格模板的点的坐标
objp = np.zeros((chessboard_size[0]*chessboard_size[1], 3), np.float32) #生成每个角点三维坐标,共有chessboard_size[0]*chessboard_size[1]个坐标,z轴置0不影响
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2) * square_size #计算得到每个角点的x,y

# 读取所有棋盘格图像并提取角点
imgpoints_left, imgpoints_right = [], []  # 存储图像中的角点
objpoints = []  # 存储模板中的角点
images = glob.glob('./calibration/right/*.jpg')  # 所有棋盘格图像所在的目录
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None) #计算corner
    ret, corners = cv2.find4QuadCornerSubpix(gray, corners, (7,7)) #提高角点检测的准确性和稳定性
    if ret == True:
        imgpoints_right.append(corners)
        objpoints.append(objp)

images = glob.glob('./calibration/left/*.jpg')  # 所有棋盘格图像所在的目录
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None) #计算corner
    ret, corners = cv2.find4QuadCornerSubpix(gray, corners, (7,7)) #提高角点检测的准确性和稳定性
    if ret == True:
        imgpoints_left.append(corners)
'''
开始标定,获得参数
'''
# 标定相机,获得内参和畸变参数
ret, mtx_r, dist_r, rvecs_r, tvecs_r = cv2.calibrateCamera(objpoints, imgpoints_right, gray.shape[::-1], None, None)
ret, mtx_l, dist_l, rvecs_l, tvecs_l = cv2.calibrateCamera(objpoints, imgpoints_left, gray.shape[::-1], None, None)

# 指定迭代次数最大30或者误差小于0.001
term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 进行双目相机标定,主要是获得R,T两个矩阵
rotation_matrix, translation_matrix = cv2.stereoCalibrate(
            objpoints, imgpoints_left, imgpoints_right,
            mtx_l, dist_l,
            mtx_r, dist_r,
            imgsz, flags=cv2.CALIB_FIX_INTRINSIC, criteria=term)[5:7]

# 获得矫正矩阵和投影矩阵,用于后续进行图像校正
rect_left, rect_right, \
proj_left, proj_right, \
dispartity, \
ROI_left, ROI_right = cv2.stereoRectify(
            mtx_l, dist_l,
            mtx_r, dist_r,
            imgsz, rotation_matrix, translation_matrix,
            flags=cv2.CALIB_ZERO_DISPARITY, alpha=-1)


'''
打印结果
'''
print('mtx_l = np.array({})'.format(np.array2string(mtx_l, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('mtx_r = np.array({})'.format(np.array2string(mtx_r, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('dist_l = np.array({})'.format(np.array2string(dist_l, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('dist_r = np.array({})'.format(np.array2string(dist_r, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('R = np.array({})'.format(np.array2string(rotation_matrix, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('T = np.array({})'.format(np.array2string(translation_matrix, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('rect_left = np.array({})'.format(np.array2string(rect_left, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('rect_right = np.array({})'.format(np.array2string(rect_right, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('proj_left = np.array({})'.format(np.array2string(proj_left, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('proj_right = np.array({})'.format(np.array2string(proj_right, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
print('dispartity = np.array({})'.format(np.array2string(dispartity, separator=', ', formatter={'int': lambda x: f'{x: 3d}'},prefix='[', suffix=']')))
# print('mtx_l = np.array({})'.format(mtx_l))
# print('mtx_r = np.array({})'.format(mtx_r))
# print('dist_l = np.array({})'.format(dist_l))
# print('dist_r = np.array({})'.format(dist_r))
# print('R = np.array({})'.format(rotation_matrix))
# print('T = np.array({})'.format(translation_matrix))
# print('rect_left = np.array({})'.format(rect_left))
# print('rect_right = np.array({})'.format(rect_right))
# print('proj_left = np.array({})'.format(proj_left))
# print('proj_right = np.array({})'.format(proj_right))
# print('dispartity = np.array({})'.format(dispartity))
print('ROI_left = np.array({})'.format(ROI_left))
print('ROI_right = np.array({})'.format(ROI_right))

得到下面参数

使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

可以直接复制用于图像矫正 

测试

import cv2, glob, os
import numpy as np
def get_corners(imgs, corners):
    for img in imgs:
        # 9x12棋盘有8x11个角点
        ret, c = cv2.findChessboardCorners(img, (9,6))
        assert(ret)
        ret, c = cv2.find4QuadCornerSubpix(img, c, (7,7))
        assert(ret)
        corners.append(c)
mtx_l = np.array([[479.61836296,   0.,         339.91341613],
 [  0.,         478.44413757, 240.61069496],
 [  0.,           0.,           1.,        ]])
mtx_r = np.array([[483.4989366,    0.,         306.98497259],
 [  0.,         482.17064224, 228.91672333],
 [  0.,           0.,           1.        ]])
dist_l = np.array([[ 0.07539615, -0.51291496,  0.00405133, -0.00084347,  0.7514282 ]])
dist_r = np.array([[-1.30834008e-01,  8.25592192e-01,  9.83305297e-04, -7.40611932e-06,  -1.67568022e+00]])
R = np.array([[ 9.99947786e-01, -1.06501500e-03,  1.01632001e-02],
 [ 8.52847758e-04,  9.99782093e-01,  2.08575744e-02],
 [-1.01831991e-02, -2.08478176e-02,  9.99730799e-01]])
T = np.array([[-62.0710667 ],
 [  0.27233791],
 [  0.49530174]])
rect_left = np.array([[ 0.99998384, -0.005285,    0.00209416],
 [ 0.00526285,  0.99993159,  0.01044553],
 [-0.00214922, -0.01043434,  0.99994325]])
rect_right = np.array([[ 0.99995854, -0.00438734, -0.00797926],
 [ 0.00430379,  0.99993606, -0.01045726],
 [ 0.00802463,  0.01042249,  0.99991348]])
proj_left = np.array([[480.3073899,    0.,         322.84606934,   0.,        ],
 [  0.,         480.3073899,  235.60386848,   0.,        ],
 [  0.,           0.,           1.,           0.,        ]])
proj_right = np.array([[ 4.80307390e+02,  0.00000000e+00,  3.22846069e+02, -2.98144281e+04],
 [ 0.00000000e+00,  4.80307390e+02,  2.35603868e+02,  0.00000000e+00],
 [ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00,  0.00000000e+00]])
dispartity = np.array([[ 1.00000000e+00,  0.00000000e+00,  0.00000000e+00, -3.22846069e+02],
 [ 0.00000000e+00,  1.00000000e+00,  0.00000000e+00, -2.35603868e+02],
 [ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00,  4.80307390e+02],
 [ 0.00000000e+00,  0.00000000e+00,  1.61098978e-02, -0.00000000e+00]])
ROI_left = np.array((5, 10, 612, 456))
ROI_right = np.array((14, 5, 626, 475))
img_left = []
img_right = []
corners_left = []
corners_right = []
img_file = glob.glob('./calibration/*.jpg')
imgsize = (640, 480)

for img in img_file:
    frame = cv2.imread(img)
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    l = frame[:,0:640]
    r = frame[:,640:]
    img_left.append(l)
    img_right.append(r)
print("获取角点", "left")
get_corners(img_left, corners_left)
print("获取角点", "right")
get_corners(img_right, corners_right)
for i in range(len(img_left)):
    l = img_left[i]
    r = img_right[i]
    # 计算双目校正的矩阵
    R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(mtx_l, dist_l, mtx_r, dist_r, imgsize, R, T)
    # 计算校正后的映射关系
    maplx , maply = cv2.initUndistortRectifyMap(mtx_l, dist_l, R1, P1, imgsize, cv2.CV_16SC2)
    maprx , mapry = cv2.initUndistortRectifyMap(mtx_r, dist_r, R2, P2, imgsize, cv2.CV_16SC2)
    # 映射新图像
    lr = cv2.remap(l, maplx, maply, cv2.INTER_LINEAR)
    rr = cv2.remap(r, maprx, mapry, cv2.INTER_LINEAR)
    all = np.hstack((lr,rr))
    # 变换之后和变换之前的角点坐标不一致,所以线不是正好经过角点,只是粗略估计,但偶尔能碰到离角点比较近的线,观察会比较明显
    cv2.line(all, (-1, int(corners_left[i][0][0][1])), (all.shape[1], int(corners_left[i][0][0][1])), (255), 1)
    # 可以看出左右图像y坐标对齐还是比较完美的,可以尝试着打印双目校正前的图片,很明显,左右y坐标是不对齐的
    cv2.imshow('a', all)
    c = cv2.waitKey()
    cv2.destroyAllWindows()
    if c == 27:
        break


print("end")

此段代码借鉴http://t.csdn.cn/uxwLA

使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

 参考链接:

Depther project - part 2: calibrate dual camera, parameters rectification - edgenoon.ai

http://t.csdn.cn/uxwLA

OpenCV: Create calibration pattern

opencv/pattern.png at 4.x · opencv/opencv · GitHub

Stereo Calibration for the Dual Camera Mezzanine - Blog - FPGA - element14 Community文章来源地址https://www.toymoban.com/news/detail-498307.html

到了这里,关于使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python进阶,使用 opencv 调用摄像头进行拍照

             opencv 支持 Python 版本的模块叫作 opencv-p hon ,可直接使用 pip install opencv-python 令进行安装,但常常会因为网络等问题导致失败。推荐使用离线模式来安装 opencv 模块。 下载完安装包后,使用如下命令进行安装: D: pip install opencv

    2024年02月11日
    浏览(66)
  • 【深度学习】python使用opencv调用摄像头拍摄并保存图片

    打开pycharm,新建一个camerm.py文件,把下面代码复制粘贴进去就可以了。 需要安装两个库:pip install opencv-python;pip install numpy

    2024年02月11日
    浏览(37)
  • 使用Python和OpenCV构建具有人体检测功能的摄像头录制器

    介绍 在本教程中,我们将探讨如何使用Python和OpenCV构建一个具有人体检测功能的摄像头录制应用程序。该应用程序允许我们从计算机的摄像头录制视频,并自动检测和提取人体存在的部分。借助YOLO目标检测算法的强大功能,我们可以轻松识别和隔离人体动作。让我们逐步深

    2024年01月16日
    浏览(42)
  • 双目摄像头Matlab参数定标

    1、安装好python3,可以在anaconda中安装python3。 2、一个合适的双目摄像头。 3、一台可以运行Matlab的电脑。 4、一张棋盘图(可A4打印,若效果不佳,则可A3打印)。 棋盘图如下图所示:需要测量小方框的边长(一般单位为毫米:mm)。 注意: 1、左、右摄像头图像中必须包含单

    2023年04月08日
    浏览(32)
  • 树莓派连接双目摄像头教程(详)

    前言:此教程为菜鸟准备好了代码,仅仅是初试水。 软件准备:Arduino IDE软件 硬件准备:树莓派 Arduin单片机 双目摄像头 树莓派桌面:1准备环境 2 Arduino IDE 3打开摄像头  1.软件准备 下载Arduino IDE软件 Windows用户可在浏览器输入网址:https://www.arduino.cc/en/Main/Software 下载安装都是

    2023年04月09日
    浏览(87)
  • 如何降低海康、大华等网络摄像头调用的高延迟问题(一):海康威视网络摄像头的python sdk使用(opencv读取sdk流)

    目录 1.python sdk使用 1.海康SDK下载  2.opencv读取sdk流  先说效果,我是用的AI推理的实时流,延迟从高达7秒降到小于1秒 如果觉得这个延迟还不能接受,下一章,给大家介绍点上不得台面的小方法 SDK(Software Development Kit)是软件开发工具包的缩写,它是一组用于开发特定软件或

    2024年02月07日
    浏览(90)
  • 树莓派CSI摄像头使用python调用opencv库函数进行运动检测识别

    目录 一、完成摄像头的调用 二、利用python调用opencv库函数对图像进行处理 2.1 图像处理大体流程 2.2 opencv调用函数的参数以及含义 2.2.1 ret, img = cap.read() 读取帧图像 2.2.2 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 灰度图像 2.2.3 gray_diff_img = cv2.absdiff(gray_img, previous_img) 帧差法 2.2.4 cv2.thre

    2024年02月15日
    浏览(49)
  • 全网最简单实用Android摄像头开发,同时预览多个摄像头,双目摄像头,同时打开手机前后摄像头(红外摄像头、人脸识别、活体检测、Android Camera、缩放、焦距、旋转、镜像、截图保存)

    如果你受够了网上那些乱七八糟的代码,你可以了解下我这个,能同时打开多个摄像头,在界面上预览,并且可以取得摄像头数据,byte[] 转为 Bitmap,保存为 jpg图片。 最近我们的某个项目要加上Android人脸识别,虽然有别人写好的“考勤”、“门口闸机”这些,但不能直接用

    2024年02月08日
    浏览(69)
  • python实现opencv调用摄像头

    Python的opencv库提供了一种简单而高效的方法来处理图像,包括从摄像头中读取视频流。在本篇技术博客中,我们将介绍如何使用Python的opencv库调用IP摄像头和本地摄像头的代码。 首先,我们需要安装Python的opencv库,可以使用pip install opencv-python命令进行安装。 在使用IP摄像头之

    2024年02月11日
    浏览(45)
  • 使用OpenCV调用摄像头

    1.创建一个摄像头调用的空项目 2.添加上篇博客里已经改好的属性表——现有属性表 3.返回解决方案资源管理器,在源文件里添加新建项命名为摄像头调用 4.输入以下代码,开始调试,然后就会弹出摄像头 #include opencv2/highgui/highgui.hpp  #include opencv2/imgproc/imgproc.hpp  #include ope

    2024年02月05日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包