在使用带棋盘的OpenCV official文档进行相机校准后检测矩形边框时遇到问题。这是我正在使用的以下代码:
cap = cv2.VideoCapture(0)
while True:
_, img = cap.read()
if img is not None:
# load data for undistortion
with np.load('R1.npz') as X:
mtx, dist, _, _ = [X[i] for i in ('mtx', 'dist', 'rvecs', 'tvecs')]
h, w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))
# undistort
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
# crop the image
x, y, w, h = roi
dst = dst[y:y + h, x:x + w]
# convert to gray scale
gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
# gaussian blur to remove noise
gray = cv2.GaussianBlur(gray, (5, 5), 0)
# threshold
thresh = cv2.adaptiveThreshold(gray, 255, 1, 1, 11, 2)
# find contours in the thresholded image
_, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# get image area
image_area = gray.size
for i in contours:
# if area of box > half of image area, it is possibly the biggest blob
if cv2.contourArea(i) > image_area / 2:
perimeter = cv2.arcLength(i, True)
# approximate the contours
approx = cv2.approxPolyDP(i, 0.02 * perimeter, True)
# draw the contours
cv2.drawContours(dst, [approx], 0, (0, 255, 0), 2, cv2.LINE_AA)
这是我如何存储相机矩阵和失真系数:
# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
# omitted code
for fname in images:
# omitted code
# Find the chess board corners
ret, corners = cv2.findChessboardCorners(gray, (7,6),None)
# If found, add object points, image points (after refining them)
if ret == True:
objpoints.append(objp)
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
imgpoints.append(corners2)
# global mtx, dist, rvecs, tvecs
# calibrate webcam and save output
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
np.savez("R1", ret=ret, mtx=mtx, dist=dist, rvecs=rvecs, tvecs=tvecs)
在相机校准之后,当在x方向上水平移动1000 px(从x = 1000 px到x = 1240 px)后移动网格时,系统不会检测到网格的边框。
这非常奇怪,因为校准相机的输出没有弯曲,程序在检测矩形边框时不会有问题。
在相机校准(带曲线输出)之前,它用于完美地检测矩形的边框。我真的很困惑,因为应该是另一种方式。
为了校准相机,我已经使用了大约90张图像,试图从所有可能的角度更精确。在这一点上,当我使用np.load
检索相机矩阵,失真系数,旋转和平移向量时,我不知道是否做错了,如上面的代码片段所示。
这些是undistort
函数的参数:
Mtx: [[ 1.44771567e+03 0.00000000e+00 5.47978617e+02]
[ 0.00000000e+00 1.45032420e+03 3.76928336e+02]
[ 0.00000000e+00 0.00000000e+00 1.00000000e+00]]
Dist: [[-0.10714946 0.00687251 0.00295331 -0.00231975 -0.18869188]]
New Camera Matrix: [[ 1.38938562e+03 0.00000000e+00 5.38801146e+02]
[ 0.00000000e+00 1.38108777e+03 3.79614791e+02]
[ 0.00000000e+00 0.00000000e+00 1.00000000e+00]]
任何人都可以帮我一把吗?我真的不知道自己做错了什么。
提前谢谢