鱼眼摄像头的畸变矫正方法-python+opencv
魚眼攝像頭畸變校正的方法:
1. 棋盤矯正法
2. 經(jīng)緯度矯正法。
?
相機(jī)為什么會(huì)出現(xiàn)畸變?
當(dāng)前相機(jī)的畸變主要分為徑向畸變和切向畸變兩種。
? ? 徑向畸變產(chǎn)生的原因:相機(jī)的光學(xué)鏡頭厚度不均勻,離鏡頭越遠(yuǎn)場景的光線就越彎曲從而產(chǎn)生徑向畸變。
? ? 切向畸變產(chǎn)生的原因:鏡頭與圖像傳感器不完全平行造成的。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? 圖一? ?徑向畸變? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖二? 切向畸變
?
相機(jī)參數(shù)有哪些?
相機(jī)內(nèi)參:主要包括相機(jī)矩陣(包括焦距,光學(xué)中心,這些都是相機(jī)本身屬性)和畸變系數(shù)(畸變數(shù)學(xué)模型的5個(gè)參數(shù) D = {K1,K2,K3,P1,P2})。
相機(jī)外參:通過旋轉(zhuǎn)和平移將實(shí)際場景3D映射到相機(jī)的2D坐標(biāo)過程中的旋轉(zhuǎn)和平移就是外參。(他描述的是世界坐標(biāo)轉(zhuǎn)化成相機(jī)坐標(biāo)的過程)
相機(jī)的標(biāo)定流程
? ? ? 相機(jī)標(biāo)定流程就是4個(gè)坐標(biāo)系在轉(zhuǎn)換過程中求出計(jì)算機(jī)的外參和內(nèi)參的過程。四個(gè)坐標(biāo)系分別是:世界坐標(biāo)系(真實(shí)的實(shí)際場景),相機(jī)坐標(biāo)系(攝像頭鏡頭中心),圖像坐標(biāo)系(圖像傳感器成像中心,圖片中心,影布中心),像素坐標(biāo)系(圖像左上角為原點(diǎn))。如圖三所示,O1是圖像坐標(biāo)系,O0 是像素坐標(biāo)系,兩者之間的區(qū)別只是原點(diǎn)發(fā)生了變化。? ?
世界坐標(biāo)系 -》相機(jī)坐標(biāo)系? ? ?求解外參(旋轉(zhuǎn)和平移)
相機(jī)坐標(biāo)系 -》圖像坐標(biāo)系? ? ?求解內(nèi)參(攝像頭矩陣,畸變系數(shù))
圖像坐標(biāo)系 -》像素坐標(biāo)系? ? ?求解像素轉(zhuǎn)化矩陣(可簡單理解為原點(diǎn)從圖片中心到左上角,單位厘米變行列)
? ? ? 圖三? 圖像坐標(biāo)系和像素坐標(biāo)系
一、基于棋盤的相機(jī)畸變校正方法
打印棋盤并采集魚眼攝像頭下的棋盤圖片:
1. 棋盤獲取:鏈接: https://pan.baidu.com/s/14qB3kQ_MbWORay1i0GFm1A 提取碼: ksqw 復(fù)制這段內(nèi)容后打開百度網(wǎng)盤手機(jī)App,操作更方便哦
2. 采集圖片,采集圖片如下圖所示,可以多采集一些,標(biāo)注的會(huì)更加準(zhǔn)確。
? ? ? ?? ? ?
3. 使用采集的圖片求出相機(jī)的內(nèi)參和矯正系數(shù)(DIM, K, D),然后使用得到的(DIM, K, D)再進(jìn)行測試,代碼如下。
import cv2 import numpy as np import globdef get_K_and_D(checkerboard, imgsPath):CHECKERBOARD = checkerboardsubpix_criteria = (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)calibration_flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC+cv2.fisheye.CALIB_CHECK_COND+cv2.fisheye.CALIB_FIX_SKEWobjp = 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)_img_shape = Noneobjpoints = []imgpoints = []images = glob.glob(imgsPath + '/*.png')for fname in images:img = cv2.imread(fname)if _img_shape == None:_img_shape = img.shape[:2]else:assert _img_shape == img.shape[:2], "All images must share the same size."gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD,cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)if ret == True:objpoints.append(objp)cv2.cornerSubPix(gray,corners,(3,3),(-1,-1),subpix_criteria)imgpoints.append(corners)N_OK = len(objpoints)K = np.zeros((3, 3))D = np.zeros((4, 1))rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]rms, _, _, _, _ = cv2.fisheye.calibrate(objpoints,imgpoints,gray.shape[::-1],K,D,rvecs,tvecs,calibration_flags,(cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6))DIM = _img_shape[::-1]print("Found " + str(N_OK) + " valid images for calibration")print("DIM=" + str(_img_shape[::-1]))print("K=np.array(" + str(K.tolist()) + ")")print("D=np.array(" + str(D.tolist()) + ")")return DIM, K, Ddef undistort(img_path,K,D,DIM,scale=0.6,imshow=False):img = cv2.imread(img_path)dim1 = img.shape[:2][::-1] #dim1 is the dimension of input image to un-distortassert dim1[0]/dim1[1] == DIM[0]/DIM[1], "Image to undistort needs to have same aspect ratio as the ones used in calibration"if dim1[0]!=DIM[0]:img = cv2.resize(img,DIM,interpolation=cv2.INTER_AREA)Knew = K.copy()if scale:#change fovKnew[(0,1), (0,1)] = scale * Knew[(0,1), (0,1)]map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), Knew, DIM, cv2.CV_16SC2)undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)if imshow:cv2.imshow("undistorted", undistorted_img)return undistorted_imgif __name__ == '__main__':# 開始使用圖片來獲取內(nèi)參和畸變系數(shù)DIM, K, D = get_K_and_D((6,9), '')# 得到內(nèi)參和畸變系數(shù)畸變矯正進(jìn)行測試'''DIM=(2560, 1920)K=np.array([[652.8609862494474, 0.0, 1262.1021584894233], [0.0, 653.1909758659955, 928.0871455436396], [0.0, 0.0, 1.0]])D=np.array([[-0.024092199861108887], [0.002745976275100771], [0.002545415522352827], [-0.0014366825722748522]])img = undistort('../imgs/pig.jpg',K,D,DIM)cv2.imwrite('../imgs/pig_checkerboard.jpg', img)'''二、基于經(jīng)緯度的矯正方法
1. 算法原理:經(jīng)緯度矯正法, 可以把魚眼圖想象成半個(gè)地球, 然后將地球展開成地圖,經(jīng)緯度矯正法主要是利用幾何原理, 對圖像進(jìn)行展開矯正。(此算法操作簡單不需要使用棋盤來進(jìn)行數(shù)據(jù)采集)
2. 代碼實(shí)現(xiàn):
import cv2 import numpy as np import time# 魚眼有效區(qū)域截取 def cut(img):img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)(_, thresh) = cv2.threshold(img_gray, 20, 255, cv2.THRESH_BINARY)contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnts = sorted(contours, key=cv2.contourArea, reverse=True)[0]x,y,w,h = cv2.boundingRect(cnts)r = max(w/ 2, h/ 2)# 提取有效區(qū)域img_valid = img[y:y+h, x:x+w]return img_valid, int(r)# 魚眼矯正 def undistort(src,r):# r: 半徑, R: 直徑R = 2*r# Pi: 圓周率Pi = np.pi# 存儲(chǔ)映射結(jié)果dst = np.zeros((R, R, 3))src_h, src_w, _ = src.shape# 圓心x0, y0 = src_w//2, src_h//2# 數(shù)組, 循環(huán)每個(gè)點(diǎn)range_arr = np.array([range(R)])theta = Pi - (Pi/R)*(range_arr.T)temp_theta = np.tan(theta)**2phi = Pi - (Pi/R)*range_arrtemp_phi = np.tan(phi)**2tempu = r/(temp_phi + 1 + temp_phi/temp_theta)**0.5tempv = r/(temp_theta + 1 + temp_theta/temp_phi)**0.5# 用于修正正負(fù)號(hào)flag = np.array([-1] * r + [1] * r)# 加0.5是為了四舍五入求最近點(diǎn)u = x0 + tempu * flag + 0.5v = y0 + tempv * np.array([flag]).T + 0.5# 防止數(shù)組溢出u[u<0]=0u[u>(src_w-1)] = src_w-1v[v<0]=0v[v>(src_h-1)] = src_h-1# 插值dst[:, :, :] = src[v.astype(int),u.astype(int)]return dstif __name__ == "__main__":t = time.perf_counter()frame = cv2.imread('../imgs/pig.jpg')cut_img,R = cut(frame)t = time.perf_counter()result_img = undistort(cut_img,R)cv2.imwrite('../imgs/pig_vector_nearest.jpg',result_img)print(time.perf_counter()-t)?
感謝一下幾位大佬資源支持:
https://blog.csdn.net/hpuhjl/article/details/80899931
https://blog.csdn.net/waeceo/article/details/50580808
https://zhuanlan.zhihu.com/p/55648494
http://www.expoon.com/wenda/20180427218.html
總結(jié)
以上是生活随笔為你收集整理的鱼眼摄像头的畸变矫正方法-python+opencv的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js网易云歌词解析处理,
- 下一篇: Python实战HSV颜色模型——提取像