雙CCD 測距 opencv python

雙CCD 測距 opencv python

雙CCD 測距 opencv python


資料來源: Copilot


在使用OpenCV和Python進行雙CCD測距的過程中,主要涉及以下步驟:

01.雙目標定:獲取左右兩個相機的內參、外參和畸變係數。
02.畸變校正:消除透鏡引起的畸變,以獲得更準確的圖像。
03.立體校正:對左右視圖進行數學上的投影變換,使得成像平面平行於基線。
04.立體匹配與視差圖計算:爲左圖中的每一個像素在右圖中找到對應點,計算視差。
05.深度圖計算:利用視差和相機參數計算深度信息。

這些步驟需要編寫相應的Python代碼來實現。下面是一個簡化的代碼示例,展示了如何使用OpenCV進行雙目測距的基本流程:

code

import cv2
import numpy as np

# 預處理函數
def preprocess(img1, img2):
    # 轉換爲灰度圖並進行直方圖均衡
    im1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    im2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    im1 = cv2.equalizeHist(im1)
    im2 = cv2.equalizeHist(im2)
    return im1, im2

# 畸變校正函數
def undistortion(image, camera_matrix, dist_coeff):
    undistortion_image = cv2.undistort(image, camera_matrix, dist_coeff)
    return undistortion_image

# 立體匹配函數
def stereo_matching(img1, img2):
    # 使用SGBM算法進行立體匹配
    stereo = cv2.StereoSGBM_create(numDisparities=16, blockSize=15)
    disparity = stereo.compute(img1, img2)
    return disparity

# 主函數
def main():
    # 讀取圖像
    img_left = cv2.imread('left.jpg')
    img_right = cv2.imread('right.jpg')

    # 預處理
    img1, img2 = preprocess(img_left, img_right)

    # 畸變校正(此處省略了相機參數)
    # img1 = undistortion(img1, camera_matrix, dist_coeff)
    # img2 = undistortion(img2, camera_matrix, dist_coeff)

    # 立體匹配
    disparity = stereo_matching(img1, img2)

    # 顯示視差圖
    cv2.imshow('Disparity', np.uint8(disparity))
    cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

code[請不要省略步驟 給我詳細完整範例程式]

import numpy as np
import cv2
from matplotlib import pyplot as plt

# 參數設定
square_size = 1.0      # 棋盤格方塊的大小
pattern_size = (9, 6)  # 棋盤格的大小
path_left = 'left/*.jpg'  # 左相機圖像的路徑
path_right = 'right/*.jpg'  # 右相機圖像的路徑

# 準備物體點: (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((np.prod(pattern_size), 3), np.float32)
objp[:, :2] = np.indices(pattern_size).T.reshape(-1, 2)
objp *= square_size

# 陣列來存放物體點和圖像點
objpoints = []  # 真實世界中的3D點
imgpoints_l = []  # 左圖像中的2D點
imgpoints_r = []  # 右圖像中的2D點

# 讀取圖像並找到棋盤格角點
images_left = glob.glob(path_left)
images_right = glob.glob(path_right)

for i, fname in enumerate(images_left):
    img_l = cv2.imread(fname)
    img_r = cv2.imread(images_right[i])

    gray_l = cv2.cvtColor(img_l, cv2.COLOR_BGR2GRAY)
    gray_r = cv2.cvtColor(img_r, cv2.COLOR_BGR2GRAY)

    # 找到棋盤格角點
    ret_l, corners_l = cv2.findChessboardCorners(gray_l, pattern_size)
    ret_r, corners_r = cv2.findChessboardCorners(gray_r, pattern_size)

    # 如果找到足夠點對,將其存儲起來
    if ret_l and ret_r:
        objpoints.append(objp)

        corners2_l = cv2.cornerSubPix(gray_l, corners_l, (11, 11), (-1, -1), criteria)
        imgpoints_l.append(corners2_l)

        corners2_r = cv2.cornerSubPix(gray_r, corners_r, (11, 11), (-1, -1), criteria)
        imgpoints_r.append(corners2_r)

        # 繪製並顯示角點
        cv2.drawChessboardCorners(img_l, pattern_size, corners2_l, ret_l)
        cv2.drawChessboardCorners(img_r, pattern_size, corners2_r, ret_r)
        cv2.imshow('img left', img_l)
        cv2.imshow('img right', img_r)
        cv2.waitKey(500)

cv2.destroyAllWindows()

# 相機標定
ret_l, mtx_l, dist_l, rvecs_l, tvecs_l = cv2.calibrateCamera(objpoints, imgpoints_l, gray_l.shape[::-1], None, None)
ret_r, mtx_r, dist_r, rvecs_r, tvecs_r = cv2.calibrateCamera(objpoints, imgpoints_r, gray_r.shape[::-1], None, None)

# 立體校正
flags = 0
flags |= cv2.CALIB_FIX_INTRINSIC
# flags |= cv2.CALIB_FIX_PRINCIPAL_POINT
flags |= cv2.CALIB_USE_INTRINSIC_GUESS
flags |= cv2.CALIB_FIX_FOCAL_LENGTH
flags |= cv2.CALIB_FIX_ASPECT_RATIO
flags |= cv2.CALIB_ZERO_TANGENT_DIST
flags |= cv2.CALIB_RATIONAL_MODEL
flags |= cv2.CALIB_SAME_FOCAL_LENGTH
flags |= cv2.CALIB_FIX_K3
flags |= cv2.CALIB_FIX_K4
flags |= cv2.CALIB_FIX_K5

stereocalib_criteria = (cv2.TERM_CRITERIA_MAX_ITER +
                        cv2.TERM_CRITERIA_EPS, 100, 1e-5)
ret, mtx_l, dist_l, mtx_r, dist_r, R, T, E, F = cv2.stereoCalibrate(
    objpoints, imgpoints_l, imgpoints_r, mtx_l, dist_l, mtx_r, dist_r, gray_l.shape[::-1], criteria=stereocalib_criteria, flags=flags)

# 立體校正映射
R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(
    mtx_l, dist_l, mtx_r, dist_r, gray_l.shape[::-1], R, T, flags=cv2.CALIB_ZERO_DISPARITY, alpha=-1, newImageSize=(0, 0))

map1_l, map2_l = cv2.initUndistortRectifyMap(
    mtx_l, dist_l, R1, P1, gray_l.shape[::-1], cv2.CV_16SC2)
map1_r, map2_r = cv2.initUndistortRectifyMap(
    mtx_r, dist_r, R2, P2, gray_r.shape[::-1], cv2.CV_16SC2)

# 載入測試圖像
img_l = cv2.imread(images_left[0])
img_r = cv2.imread(images_right[0])

# 畸變校正和立體校正
img_l_rect = cv2.remap(img_l, map1_l, map2_l, cv2.INTER_LINEAR)
img_r_rect = cv2.remap(img_r, map1_r, map2_r, cv2.INTER_LINEAR)

# 計算視差
stereo = cv2.StereoBM_create(numDisparities=16, blockSize=15)
disparity = stereo.compute(img_l_rect, img_r_rect)

# 計算深度
h, w = img_l_rect.shape[:2]
f = 0.8*w                          # 假設焦距
Q = np.float32([[1, 0, 0, -0.5*w],
                [0,-1, 0,  0.5*h], # 調整坐標系,使其與左相機坐標系一致
                [0, 0, 0,     -f], # 設置焦距
                [0, 0, 1,      0]])
points = cv2.reprojectImageTo3D(disparity, Q)
colors = cv2.cvtColor(img_l_rect, cv2.COLOR_BGR2RGB)
mask = disparity > disparity.min()
out_points = points[mask]
out_colors = colors[mask]

# 輸出到PLY
output_file = 'out.ply'
with open(output_file, 'w') as f:
    f.write('ply\n')
    f.write('format ascii 1.0\n')
    f.write('element vertex %d\n' % len(out_points))
    f.write('property float x\n')
    f.write('property float y\n')
    f.write('property float z\n')
    f.write('property uchar red\n')
    f.write('property uchar green\n')
    f.write('property uchar blue\n')
    f.write('end_header\n')
    for p, c in zip(out_points, out_colors):
        f.write('%f %f %f %d %d %d\n' % (p[0], p[1], p[2], c[2], c[1], c[0]))

# 顯示結果
plt.imshow(disparity,'gray')
plt.show()

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *