双目目标定:
畸变矫正:
立体矫正:
- #coding:utf-8
- import cv2
- import time
- import time
-
- left_camera = cv2.VideoCapture(0)
- left_camera.set(cv2.CAP_PROP_FRAME_WIDTH,640)
- left_camera.set(cv2.CAP_PROP_FRAME_HEIGHT,480)
-
- right_camera = cv2.VideoCapture(1)
- right_camera.set(cv2.CAP_PROP_FRAME_WIDTH,640)
- right_camera.set(cv2.CAP_PROP_FRAME_HEIGHT,480)
-
- path="/home/song/pic/" #图片存储路径
-
- AUTO =False # True自动拍照,False则手动按s键拍照
- INTERVAL = 0.0000005 # 调整自动拍照间隔
-
- cv2.namedWindow("left")
- cv2.namedWindow("right")
- cv2.moveWindow("left", 0, 0)
-
- counter = 0
- utc = time.time()
- folder = "/home/song/pic/" # 照片存储路径
-
- def shot(pos, frame):
- global counter
- timestr = datetime.datetime.now()
- path = folder + pos + "_" + str(counter) +".jpg"
- cv2.imwrite(path, frame)
- print("snapshot saved into: " + path)
-
- while True:
- ret, left_frame = left_camera.read()
- ret, right_frame = right_camera.read()
-
- cv2.imshow("left", left_frame)
- cv2.imshow("right", right_frame)
-
- now = time.time()
- if AUTO and now - utc >= INTERVAL:
- shot("left", left_frame)
- shot("right", right_frame)
- counter += 1
- utc = now
-
- key = cv2.waitKey(1)
- if key == ord("q"):
- break
- elif key == ord("s"):
- shot("left", left_frame)
- shot("right", right_frame)
- counter += 1
-
- left_camera.release()
- right_camera.release()
- cv2.destroyWindow("left")
- cv2.destroyWindow("right")

在进行双目相机的标定之前,需要先对左右目的单目摄像头进行单目标定。这是因为双目摄像头的标定需要知道每个摄像头的内部参数(如相机矩阵、畸变系数)以及相机之间的外部参数(相对位置和朝向)。这些参数是通过单目标定来获得的。
单目标定通常包括以下步骤:
相机内参标定:通过拍摄一个包含已知尺寸的标定板的图像,然后使用相机标定算法来估计相机内参,如焦距、主点坐标和畸变系数。
相机外参标定:通过将相机放置在不同位置或拍摄不同方向的图像,使用外参标定算法来估计相机的位置和朝向。这一步通常需要多幅图像,以确定相机在三维空间中的位置和姿态。
畸变矫正:使用内参标定得到的畸变系数来矫正图像,以去除镜头畸变。
生成标定文件:将内外参和畸变系数保存在标定文件中,以便后续的双目标定使用。
一旦单目摄像头的内部参数、外部参数和畸变系数都已知,就可以进行双目标定,以确定双目摄像头之间的相对位置和朝向,以及立体视觉中的标定参数。
- #-*- coding:utf-8 -*-
- import numpy as np
- import cv2
- import glob
-
- # 设置迭代终止条件
- criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
-
- # 设置 object points, 形式为 (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
- objp = np.zeros((6*7,3), np.float32) #我用的是6×7的棋盘格,可根据自己棋盘格自行修改相关参数
- objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
-
- # 用arrays存储所有图片的object points 和 image points
- objpoints = [] # 3d point in real world space
- imgpoints = [] # 2d points in image plane.
-
- #用glob匹配文件夹/home/song/pic_1/right/下所有文件名含有“.jpg"的图片
- images = glob.glob(r"/home/song/pic/right/*.jpg")
- for fname in images:
- img = cv2.imread(fname)
- gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
- # 查找棋盘格角点
- ret, corners = cv2.findChessboardCorners(gray, (7,6), None)
- # 如果找到了就添加 object points, image points
- if ret == True:
- objpoints.append(objp)
- corners2=cv2.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria)
- imgpoints.append(corners)
- # 对角点连接画线加以展示
- cv2.drawChessboardCorners(img, (7,6), corners2, ret)
- cv2.imshow('img', img)
- cv2.waitKey(500)
- cv2.destroyAllWindows()
- # 标定
- ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
- print(mtx, dist)
- #对所有图片进行去畸变,有两种方法实现分别为: undistort()和remap()
- images = glob.glob(r"/home/song/pic/right/*.jpg")
- for fname in images:
- prefix=fname.split('/')[5]
- img = cv2.imread(fname)
- h, w = img.shape[:2]
- newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
- # # 使用 cv.undistort()进行畸变校正
- # dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
- # # 对图片有效区域进行剪裁
- # # x, y, w, h = roi
- # # dst = dst[y:y+h, x:x+w]
- # cv2.imwrite('/home/song/pic_1/undistort/'+prefix, dst)
- # 使用 remap() 函数进行校正
- mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w, h), 5)
- dst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
- # 对图片有效区域进行剪裁
- x, y, w, h = roi
- dst = dst[y:y + h, x:x + w]
- cv2.imwrite('/home/song/pic/undistort/'+prefix, dst)
- #重投影误差计算
- mean_error = 0
- for i in range(len(objpoints)):
- imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
- error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
- mean_error += error
- print("total error: ", mean_error/len(objpoints))
- #coding:utf-8
- import numpy as np
- import cv2
- import matplotlib.pyplot as plt
- from PIL import Image
-
- # 设置迭代终止条件
- criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
- criteria_stereo = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
-
- # 设置 object points, 形式为 (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
- objp = np.zeros((6 * 7, 3), np.float32) #我用的是6×7的棋盘格,可根据自己棋盘格自行修改相关参数
- objp[:, :2] = np.mgrid[0:7, 0:6].T.reshape(-1, 2)
-
- # 用arrays存储所有图片的object points 和 image points
- objpoints = [] # 3d points in real world space
- imgpointsR = [] # 2d points in image plane
- imgpointsL = []
-
- # 本次实验采集里共计30组待标定图片依次读入进行以下操作
- for i in range(0,30):
- t = str(i)
- ChessImaR = cv2.imread('/home/song/pic/right_' + t + '.jpg', 0) # 右视图
- ChessImaL = cv2.imread('/home/song/pic/left_' + t + '.jpg', 0) # 左视图
- retR, cornersR = cv2.findChessboardCorners(ChessImaR,(7, 6), None) # 提取右图每一张图片的角点
- retL, cornersL = cv2.findChessboardCorners(ChessImaL,(7, 6), None) # # 提取左图每一张图片的角点
- if (True == retR) & (True == retL):
- objpoints.append(objp)
- cv2.cornerSubPix(ChessImaR, cornersR, (11, 11), (-1, -1), criteria) # 亚像素精确化,对粗提取的角点进行精确化
- cv2.cornerSubPix(ChessImaL, cornersL, (11, 11), (-1, -1), criteria) # 亚像素精确化,对粗提取的角点进行精确化
- imgpointsR.append(cornersR)
- imgpointsL.append(cornersL)
-
- # 相机的单双目标定、及校正
- # 右侧相机单独标定
- retR, mtxR, distR, rvecsR, tvecsR = cv2.calibrateCamera(objpoints,imgpointsR,ChessImaR.shape[::-1], None, None)
-
- # 获取新的相机矩阵后续传递给initUndistortRectifyMap,以用remap生成映射关系
- hR, wR = ChessImaR.shape[:2]
- OmtxR, roiR = cv2.getOptimalNewCameraMatrix(mtxR, distR,(wR, hR), 1, (wR, hR))
-
- # 左侧相机单独标定
- retL, mtxL, distL, rvecsL, tvecsL = cv2.calibrateCamera(objpoints,imgpointsL,ChessImaL.shape[::-1], None, None)
-
- # 获取新的相机矩阵后续传递给initUndistortRectifyMap,以用remap生成映射关系
- hL, wL = ChessImaL.shape[:2]
- OmtxL, roiL = cv2.getOptimalNewCameraMatrix(mtxL, distL, (wL, hL), 1, (wL, hL))
-
- # 双目相机的标定
- # 设置标志位为cv2.CALIB_FIX_INTRINSIC,这样就会固定输入的cameraMatrix和distCoeffs不变,只求解𝑅,𝑇,𝐸,𝐹
- flags = 0
- flags |= cv2.CALIB_FIX_INTRINSIC
-
- retS, MLS, dLS, MRS, dRS, R, T, E, F = cv2.stereoCalibrate(objpoints,imgpointsL,imgpointsR,OmtxL,distL,OmtxR,distR,
- ChessImaR.shape[::-1], criteria_stereo,flags)
-
-
- # 利用stereoRectify()计算立体校正的映射矩阵
- rectify_scale= 1 # 设置为0的话,对图片进行剪裁,设置为1则保留所有原图像像素
- RL, RR, PL, PR, Q, roiL, roiR= cv2.stereoRectify(MLS, dLS, MRS, dRS,
- ChessImaR.shape[::-1], R, T,
- rectify_scale,(0,0))
- # 利用initUndistortRectifyMap函数计算畸变矫正和立体校正的映射变换,实现极线对齐。
- Left_Stereo_Map= cv2.initUndistortRectifyMap(MLS, dLS, RL, PL,
- ChessImaR.shape[::-1], cv2.CV_16SC2)
-
- Right_Stereo_Map= cv2.initUndistortRectifyMap(MRS, dRS, RR, PR,
- ChessImaR.shape[::-1], cv2.CV_16SC2)
-
- #立体校正效果显示
- for i in range(0,1): # 以第一对图片为例
- t = str(i)
- frameR = cv2.imread('/home/song/pic/right_' + t + '.jpg', 0)
- frameL = cv2.imread('/home/song/pic/left_' + t + '.jpg', 0)
-
- Left_rectified= cv2.remap(frameL,Left_Stereo_Map[0],Left_Stereo_Map[1], cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0) # 使用remap函数完成映射
- im_L=Image.fromarray(Left_rectified) # numpy 转 image类
-
- Right_rectified= cv2.remap(frameR,Right_Stereo_Map[0],Right_Stereo_Map[1], cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0)
- im_R=Image.fromarray(Right_rectified) # numpy 转 image 类
-
- #创建一个能同时并排放下两张图片的区域,后把两张图片依次粘贴进去
- width = im_L.size[0]*2
- height = im_L.size[1]
-
- img_compare = Image.new('RGBA',(width, height))
- img_compare.paste(im_L,box=(0,0))
- img_compare.paste(im_R,box=(640,0))
-
- #在已经极线对齐的图片上均匀画线
- for i in range(1,20):
- len=480/20
- plt.axhline(y=i*len, color='r', linestyle='-')
- plt.imshow(img_compare)
- plt.show()
双目视觉是指通过两个摄像头(或相机)捕获的图像来模拟人类双眼视觉系统。它可以提供更多的深度信息和立体感,因此在许多领域都有具体的应用。
以下是一些双目视觉的具体应用:
三维重建:通过双目摄像头捕获的图像,可以使用立体视觉算法来重建场景的三维结构。这对于计算机辅助设计、虚拟现实、增强现实等领域非常有用。
物体检测与跟踪:双目视觉可以提供更多的深度信息,从而使得物体检测和跟踪更加准确和稳定。例如,在自动驾驶中,双目视觉可以用于检测和跟踪其他车辆、行人等。
深度感知:通过双目视觉可以获取场景中物体的深度信息,从而可以进行深度感知和距离测量。这在机器人导航、室内定位、无人机避障等领域非常有用。
姿态估计:双目视觉可以用于估计物体或人体的姿态和运动。例如,在人机交互中,双目视觉可以用于手势识别和追踪。
立体匹配:通过双目视觉可以进行立体匹配,即将两个图像中对应的像素点进行匹配。这在计算机视觉中是一个重要的问题,可以用于图像配准、目标识别等。
视觉SLAM:双目视觉可以与同步定位与地图构建(SLAM)算法结合使用,实现同时定位和地图构建。这在无人车、无人机等领域中非常重要。