import cv2 import numpy as np import glob# 設置尋找亞像素角點的參數,采用的停止準則是最大循環次數30和最大誤差容限0.001 criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)# 獲取標定板角點的位置 objp = np.zeros((6 * 7, 3), np.float32) objp[:, :2] = np.mgrid[0:7, 0:6].T.reshape(-1, 2) # 將世界坐標系建在標定板上,所有點的Z坐標全部為0,所以只需要賦值x和yobj_points = [] # 存儲3D點 img_points = [] # 存儲2D點images = glob.glob('C:\Users\Administrator\Desktop\cal_camera\cam\*.bmp') for fname in images:img = cv2.imread(fname)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)size = gray.shape[::-1]ret, corners = cv2.findChessboardCorners(gray, (7, 6), None)if ret:obj_points.append(objp)corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria) # 在原角點的基礎上尋找亞像素角點if True:img_points.append(corners2)else:img_points.append(corners)cv2.drawChessboardCorners(img, (7, 6), corners, ret) # 記住,OpenCV的繪制函數一般無返回值cv2.imshow('img', img)cv2.waitKey(50)print len(img_points) cv2.destroyAllWindows()# 標定 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, img.shape[:2], None, None) print "標定" print "ret:", ret print "mtx:\n", mtx # 內參數矩陣內參數的輸出向量。輸出順序為: # (fx,fy,cx,cy,) # {k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,τx,τy} ,如果不估計其中某一個參數,值等于0 print "dist:\n", dist # 畸變系數 distortion cofficients = (k_1,k_2,p_1,p_2,k_3) print "rvecs:\n", rvecs # 旋轉向量 # 外參數 print "tvecs:\n", tvecs # 平移向量 # 外參數print("-----------------------------------------------------") # 畸變校正 img = cv2.imread('C:\Users\Administrator\Desktop\cal_camera\cam\cam2.bmp') h, w = img.shape[:2] ''' #使用cv.getOptimalNewCameraMatrix()優化內參數和畸變系數, # 通過設定自由自由比例因子alpha。當alpha設為0的時候, # 將會返回一個剪裁過的將去畸變后不想要的像素去掉的內參數和畸變系數; # 當alpha設為1的時候,將會返回一個包含額外黑色像素點的內參數和畸變系數,并返回一個ROI用于將其剪裁掉。'''newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h)) print newcameramtx print("------------------使用undistort函數-------------------") #該功能可轉換圖像以補償徑向和切向鏡頭失真。 dst = cv2.undistort(img, mtx, dist, None, newcameramtx) x, y, w, h = roi dst1 = dst[y:y + h, x:x + w] cv2.imwrite('calibresult11.jpg', dst1) print "方法一:dst的大小為:", dst1.shape# undistort方法二 print("-------------------使用重映射的方式-----------------------") ''' 該函數計算聯合不變形和整流變換并代表。 以重映射的映射形式。未失真的圖像看起來像原始圖像,就像它一樣。 使用相機矩陣= newCameraMatrix和零失真用相機拍攝。如果是。 單目相機,newCameraMatrix通常等于cameraMatrix,或者它可以通過計算。cv :: getOptimalNewCameraMatrix用于更好地控制縮放。 ''' mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w, h), 5) # 獲取映射方程 # dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR) # 重映射 dst = cv2.remap(img, mapx, mapy, cv2.INTER_CUBIC) # 重映射后,圖像變小了 x, y, w, h = roi dst2 = dst[y:y + h, x:x + w] cv2.imwrite('calibresult11_2.jpg', dst2) print "方法二:dst的大小為:", dst2.shape # 圖像比方法一的小print("-------------------計算反向投影誤差-----------------------") tot_error = 0 for i in xrange(len(obj_points)):img_points2, _ = cv2.projectPoints(obj_points[i], rvecs[i], tvecs[i], mtx, dist)error = cv2.norm(img_points[i], img_points2, cv2.NORM_L2) / len(img_points2)tot_error += errormean_error = tot_error / len(obj_points) print "total error: ", tot_error print "mean error: ", mean_error