最近在学习相机标定和图片的畸变矫正,看了张氏标定法和关于畸变矫正的博客和代码。
自己根据opencv官方文档的介绍,仿写了标定和矫正代码,但是效果一直不满意,或者说效果达不到预期,特来求助各位大佬。
因为标定过程中用的棋盘格是用手机拍摄的,为了控制变量因素,待矫正的图片也选择用手机拍摄的,图片如下_****
第一张是畸变图片,第二张是矫正后的图片
从矫正后的图片可以看出,效果好像只是在原畸变图片的基础上进行了裁剪,并没有达到矫正的作用。
于是,又选择了一张网图进行测试。效果如下:
从第二张矫正后的图片可以看出,左上角畸变反而更严重了
经过一番尝试之后,还是不懂代码里边的参数怎么调节,请大神看了之后,给点拨迷津。
附上标定用的棋盘格:
这种棋盘格,用手机拍的,共使用了18张,不同角度的图片。
**下边,附上源代码:
**
import numpy as np
import cv2 as cv
import glob
import matplotlib.pyplot as plt
#终止条件
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER,30,0.001)
#准备对象点
objp = np.zeros((9*6,3),np.float32)
objp[:,:2] = np.mgrid[0:6,0:9].T.reshape(-1,2)
#用于存储所有图像的对象点和图像点的数组、
objpoints = []
imgpoints = []
images = glob.glob('C:\\Users\\16238\\Desktop\\board\\*.jpg')
for fname in images:
img = cv.imread(fname)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
#找到棋盘格角点
ret,corners = cv.findChessboardCorners(gray,(6,9),None)
#如果找到,添加对象点,图像点(细化)
if ret == True:
objpoints.append(objp)
corners2 = cv.cornerSubPix(gray,corners,(15,15),(-1,-1),criteria)
imgpoints.append(corners)
#绘制并显示角点
cv.drawChessboardCorners(img,(6,9),corners2,ret)
#cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
import pickle
ret,mtx,dist,rvecs,tvecs = cv.calibrateCamera(objpoints,imgpoints,gray.shape[::-1],None,None)
print("ret:",ret)
print("mtx:\n",mtx)#内参矩阵
print("dist:\n",dist)#畸变系数
print("rvecs:\n",rvecs)#旋转向量
print("tvecs:\n",tvecs)#平移向量
img = cv.imread('1.jpg')
h,w = img.shape[:2]
newcameramtx,roi = cv.getOptimalNewCameraMatrix(mtx,dist,(w,h),0,(w,h))
dst = cv.undistort(img,mtx,dist,None,newcameramtx)
#对给定的目标和图像点进行摄像机标定
dst = cv.undistort(img,mtx,dist,None,newcameramtx)
#使用remapping
mapx,mapy = cv.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst = cv.remap(img,mapx,mapy,cv.INTER_LINEAR)
#裁剪图像
#x,y,w,h = roi
#dst = dst[y:y+w,x:x+h]
cv.imwrite('undistort.jpg',dst)
mean_error = 0
for i in range(len(objpoints)):
imgpoints2, _ = cv.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
error = cv.norm(imgpoints[i], imgpoints2, cv.NORM_L2)/len(imgpoints2)
mean_error += error
print("total error: ", mean_error/len(objpoints))