日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

相机标定理解

發布時間:2024/1/8 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 相机标定理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一。原理
參考:
camera calibration using opencv
相機標定原理、步驟
opencv-python 攝像頭標定

生成黑白棋盤標定圖和單目相機標定
相機外參估計

坐標系

坐標系名稱介紹圖形
世界坐標系world coordinate,測量坐標系,三維直角坐標系,以其為基準可以描述相機和待測物體的空間位置。世界坐標系的位置可以根據實際情況自由確定
相機坐標系camera coordinate,三維直角坐標系,原點位于鏡頭光心處,x,y軸分別與相面的兩邊平行,z軸為鏡頭光軸,與像平面垂直
像素坐標系pixel coordinate,二維直角坐標系,反映相機CCD/CMOS芯片中像素的排列情況。原點位于左上角,u,v分別于像面的兩邊平行,單位是像素(整數)。但是它不利于坐標轉換
圖像坐標系XOY,單位通常是毫米,原點是相機光軸與相面的交點(也叫主點)

4大坐標系理解圖:

坐標系之間轉換:

轉換
世界坐標系-》相機坐標系
圖像坐標系-》像素坐標系
相機坐標系-》圖像坐標系
世界坐標系-》像素坐標系

過程理解:
要找到3D點在圖像平面上的投影,我們首先需要使用外參(旋轉和平移)將該點從世界坐標系統轉換成相機坐標系,接下來,使用相機的內參將點投影到圖像平面上。

相機標定3+要素(內參,外參,畸變參數等):
0.先看下總公式:

P:3x4投影矩陣
K:內參 3x3矩陣
R:旋轉矩陣 3x3
t:平移矩陣 3x1

1.內參K

fx,fy:x,y焦距,通常值一樣
cx,cy:圖像平面光學中心的x,y坐標,一般近似圖像中心點
gamma:是軸之間的傾斜度,一般是0

2.外參
Rt
R:旋轉矩陣 3x3 但opencv標定時3x1矩陣??!!
t: 平移矩陣 3x1

3.畸變參數

分徑向畸變(k1,k2,k3)和切向畸變(p1,p2)

畸變類型內容示例
徑向畸變來自于透鏡形狀,包括枕型畸變、桶型畸變,光學中心畸變為0,越往邊緣移動,畸變也嚴重
切向畸變透鏡制造上的缺陷使得透鏡本身與圖像平面不平行而產生的,包括薄透鏡畸變、離心畸變
二。相機標定步驟
1、打印一張棋盤格,把它貼在一個平面上,作為標定物。
2、通過調整標定物或攝像機的方向,為標定物拍攝一些不同方向的照片。
3、從照片中提取棋盤格角點。
4、估算理想無畸變的情況下,五個內參和六個外參。
5、應用最小二乘法估算實際存在徑向畸變下的畸變系數。
6、極大似然法,優化估計,提升估計精度。

三。代碼注釋
內參,畸變參數的求解:

#!/usr/bin/env pythonimport cv2 import numpy as np import os import glob# Defining the dimensions of checkerboard CHECKERBOARD = (6,9) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)# Creating vector to store vectors of 3D points for each checkerboard image objpoints = [] # Creating vector to store vectors of 2D points for each checkerboard image imgpoints = [] # Defining the world coordinates for 3D points objp = np.zeros((1, CHECKERBOARD[0]*CHECKERBOARD[1], 3), np.float32) objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2) prev_img_shape = None# Extracting path of individual image stored in a given directory images = glob.glob('./images/*.jpg') for fname in images:img = cv2.imread(fname)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)# Find the chess board corners# If desired number of corners are found in the image then ret = trueret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)"""If desired number of corner are detected,we refine the pixel coordinates and display them on the images of checker board"""if ret == True:objpoints.append(objp)# refining pixel coordinates for given 2d points.corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)imgpoints.append(corners2)# Draw and display the cornersimg = cv2.drawChessboardCorners(img, CHECKERBOARD, corners2,ret)cv2.imshow('img',img)cv2.waitKey(10)cv2.destroyAllWindows()h,w = img.shape[:2]""" Performing camera calibration by passing the value of known 3D points (objpoints) and corresponding pixel coordinates of the detected corners (imgpoints) """ ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)print("Camera matrix {}: \n".format(mtx.shape)) print(mtx) print("dist {}: \n".format(dist.shape)) print(dist) print("rvecs {}: \n".format(np.array(rvecs).shape)) print(rvecs) print("tvecs {}: \n".format(np.array(tvecs).shape)) print(tvecs)# Using the derived camera parameters to undistort the imageimg = cv2.imread(images[0]) # Refining the camera matrix using parameters obtained by calibration newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))# Method 1 to undistort the image dst = cv2.undistort(img, mtx, dist, None, newcameramtx)# Method 2 to undistort the image mapx,mapy=cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w, h), 5)dst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR) print("dst shape is ", dst.shape)x, y, w, h = roi cropped_frame = dst[y:y+h, x:x+w] print("cropped_frame shape is ", cropped_frame.shape)# Displaying the undistorted image cv2.imshow("distorted image", img) cv2.imshow("undistorted image", dst) cv2.imshow("cropped image", cropped_frame) cv2.waitKey(0)#計算誤差 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 += errorprint("mean error: ", mean_error/len(objpoints))

外參的求解:

import cv2 import numpy import numpy as nptwod_point = "1189 254 1216 254 1242 255 1268 255 1294 256 1322 254 1347 255 1375 253 1187 279 1214 " \"278 1243 281 1269 279 1296 280 1321 279 1346 281 1374 280" twod_point = np.array(twod_point.split( ),dtype=np.float) print(len(twod_point)//2) twod_point = twod_point.reshape((16,2)) print(twod_point.shape)threed_point = np.zeros(shape=(16,3)) for i in range(len(twod_point)):x = twod_point[i][0]y = twod_point[i][1]threed_point[i][0] = (x -1189)/27 *4threed_point[i][1] = (y - 254)/25 *4 newcameramtx=[[1.67276660e+03,0.00000000e+00,6.22925147e+02],[0.00000000e+00,1.67104004e+03,3.44706162e+02],[0.00000000e+00,0.00000000e+00,1.00000000e+00]] dist=[[-6.11401280e-01 ,4.08011840e-01 ,-5.83043580e-05 ,-1.16998902e-03,-7.99593012e-01]] newcameramtx = np.array(newcameramtx,dtype=np.uint8) dist = np.array(dist,dtype=np.uint8) _,r,t = cv2.solvePnP(threed_point,twod_point,newcameramtx,dist) np.set_printoptions(suppress=True)def Pix2World(point2D, rVec, tVec, cameraMat, height):"""Function used to convert given 2D points back to real-world 3D pointspoint2D : An array of 2D pointsrVec : Rotation vectortVec : Translation vectorcameraMat: Camera Matrix used in solvePnPheight : Height in real-world 3D spaceReturn : output_array: Output array of 3D points"""point3D = []point2D = (np.array(point2D, dtype='float32')).reshape(-1, 2)numPts = point2D.shape[0]point2D_op = np.hstack((point2D, np.ones((numPts, 1))))rMat = cv2.Rodrigues(rVec)[0]# print(rMat)rMat_inv = np.linalg.inv(rMat)kMat_inv = np.linalg.inv(cameraMat)for point in range(numPts):uvPoint = point2D_op[point, :].reshape(3, 1)tempMat = np.matmul(rMat_inv, kMat_inv)tempMat1 = np.matmul(tempMat, uvPoint)tempMat2 = np.matmul(rMat_inv, tVec)s = (height + tempMat2[2]) / tempMat1[2]p = tempMat1 * s - tempMat2point3D.append(p)point3D = (np.array(point3D, dtype='float32')).reshape([-1, 1, 3])return point3Dframe = cv2.imread("source.jpg") # cap = cv2.VideoCapture("rtsp://admin:MLLaaa100848@192.168.1.64:554/h264/ch1/main/av_stream") # ret, frame = cap.read() drawing = False #鼠標按下為真 mode = True #如果為真,畫矩形,按m切換為曲線 px,py,ix,iy=-1,-1,-1,-1 def draw_circle(event,x,y,flags,param):global ix, iy, drawing, mode,px,py,sourceif event == cv2.EVENT_LBUTTONDOWN:drawing = Trueix, iy = x, yp3d = Pix2World([ix, iy], r, t, newcameramtx, 0)source = p3delif event == cv2.EVENT_LBUTTONUP:if drawing == True:if mode == True:px,py = x,ycv2.line(frame, (ix, iy), (x, y), (0, 255, 0), 10)p3d2 = Pix2World([px, py], r, t, newcameramtx, 0)coord = p3d2-sourcelength = round(np.sqrt(np.sum((p3d2-source) ** 2))*10,3)cv2.putText(frame,"L:"+str(length)+'mm',(int((px+ix)/2)-10,int((py+iy)/2)-10),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)print("-"*20,'\n',"實際長度",length,'\n','-'*20,)cv2.imshow("frame",frame)cv2.waitKey(0)cv2.namedWindow('frame') cv2.setMouseCallback("frame",draw_circle) cv2.imshow("frame", frame) k = cv2.waitKey(0)# while ret: # ret, frame = cap.read() # cv2.imshow("frame",frame) # k = cv2.waitKey(0) # # if cv2.waitKey(1) & 0xFF == ord('q'): # # break # if k == ord('s'): # break cv2.destroyAllWindows() # cap.release()

總結

以上是生活随笔為你收集整理的相机标定理解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。