带圆形图案的相机校准
Camera calibration with circular pattern
我正在关注 this tutorial to calibrate my camera (with some lens) on Raspberry Pi, but using a circular pattern instead of the chessboard one. The problem is that the resulting undistorted image is shrinked and not full, and when I get every shrinking away from the code, it looks like the right part of (usually it's even worse). The question is if it is possible to do something with the code so that it would give away a picture like the example from the tutorial。我必须为此使用棋盘模式吗?
我的代码:
import numpy as np
import cv2
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
# 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((4*11,3), np.float32)
#objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
objp=np.array([[0,0,0],[1,0,0],[2,0,0],[3,0,0],[0.5,0.5,0],[1.5,0.5,0],[2.5,0.5,0],[3.5,0.5,0]])
for y in range(2,11):
for x in range(4):
objp=np.append(objp,[np.array([objp[4*(y-2)+x][0],objp[4*(y-2)+x][1]+1,0])],axis=0)
# 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.
#images = glob.glob('pict*.jpg')
# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 32
rawCapture = PiRGBArray(camera, size=(640, 480))
# allow the camera to warmup
time.sleep(0.1)
ret0=[]
j=0
for i,frame in enumerate(camera.capture_continuous(rawCapture, format="bgr", use_video_port=True)):
image = frame.array
img=image[::-1]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Find the chess board corners
ret, corners = cv2.findCirclesGrid(gray, (4,11),None,flags=cv2.CALIB_CB_ASYMMETRIC_GRID)
# If found, add object points, image points (after refining them)
if ret == True and np.sum(np.int32(ret0))<15 and not i%10:
ret0.append(ret)
print("{} more for proper calibration".format(15-np.sum(np.int32(ret0))))
objpoints.append(objp.astype('float32'))
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
imgpoints.append(corners2.reshape(-1, 2).astype('float32'))
# Draw and display the corners
img = cv2.drawChessboardCorners(img.copy(), (4,11), corners2,ret)
cv2.imshow('img',img)
cv2.waitKey(1000)
cv2.imwrite('cal{}.jpg'.format(j),img)
j+=1
rawCapture.truncate(0)
elif np.sum(np.int32(ret0))<15:
cv2.imshow('img',img)
cv2.waitKey(1)
rawCapture.truncate(0)
else:
rawCapture.truncate(0)
break
dist = np.array([-0.13615181, 0.53005398, 0, 0, 0]) # no translation
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
h, w = img.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
np.savetxt('newcameramtx.out',newcameramtx)
np.savetxt('mtx.out',mtx)
np.savetxt('dist.out',dist)
#img=cv2.imread('pict1.jpg')
# 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]
cv2.imwrite('calibresult.png',dst)
cv2.imshow('undistorted',dst)
cv2.waitKey(0)&0xFF
cv2.destroyAllWindows()
UPD:我试过用棋盘图案进行校准,但程序甚至不想识别该图案!这里有例子
检测到圆形图案:
因此程序据称可以检测到圆圈,但并不像预期的那样理想。
您可以尝试调整斑点检测器的参数。默认情况下 findCirclesGrid
使用 SimpleBlobDetector。所以尝试调整参数,例如:
params = cv2.SimpleBlobDetector_Params()
params.minArea = 10;
params.minDistBetweenBlobs = 5;
detector = cv2.SimpleBlobDetector_create(params)
然后将其传递给 findCirclesGrid:
cv2.findCirclesGrid(gray, (4,11),None,flags=cv2.CALIB_CB_ASYMMETRIC_GRID,detector)
另外你可以尝试使用cv2.CALIB_CB_ASYMMETRIC_GRID + cv2.CALIB_CB_CLUSTERING
有关 SimpleBlobDetector 及其参数的详细信息,请参阅 this tutrial。
我正在关注 this tutorial to calibrate my camera (with some lens) on Raspberry Pi, but using a circular pattern instead of the chessboard one. The problem is that the resulting undistorted image is shrinked and not full, and when I get every shrinking away from the code, it looks like the right part of
我的代码:
import numpy as np
import cv2
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
# 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((4*11,3), np.float32)
#objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
objp=np.array([[0,0,0],[1,0,0],[2,0,0],[3,0,0],[0.5,0.5,0],[1.5,0.5,0],[2.5,0.5,0],[3.5,0.5,0]])
for y in range(2,11):
for x in range(4):
objp=np.append(objp,[np.array([objp[4*(y-2)+x][0],objp[4*(y-2)+x][1]+1,0])],axis=0)
# 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.
#images = glob.glob('pict*.jpg')
# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 32
rawCapture = PiRGBArray(camera, size=(640, 480))
# allow the camera to warmup
time.sleep(0.1)
ret0=[]
j=0
for i,frame in enumerate(camera.capture_continuous(rawCapture, format="bgr", use_video_port=True)):
image = frame.array
img=image[::-1]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Find the chess board corners
ret, corners = cv2.findCirclesGrid(gray, (4,11),None,flags=cv2.CALIB_CB_ASYMMETRIC_GRID)
# If found, add object points, image points (after refining them)
if ret == True and np.sum(np.int32(ret0))<15 and not i%10:
ret0.append(ret)
print("{} more for proper calibration".format(15-np.sum(np.int32(ret0))))
objpoints.append(objp.astype('float32'))
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
imgpoints.append(corners2.reshape(-1, 2).astype('float32'))
# Draw and display the corners
img = cv2.drawChessboardCorners(img.copy(), (4,11), corners2,ret)
cv2.imshow('img',img)
cv2.waitKey(1000)
cv2.imwrite('cal{}.jpg'.format(j),img)
j+=1
rawCapture.truncate(0)
elif np.sum(np.int32(ret0))<15:
cv2.imshow('img',img)
cv2.waitKey(1)
rawCapture.truncate(0)
else:
rawCapture.truncate(0)
break
dist = np.array([-0.13615181, 0.53005398, 0, 0, 0]) # no translation
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
h, w = img.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
np.savetxt('newcameramtx.out',newcameramtx)
np.savetxt('mtx.out',mtx)
np.savetxt('dist.out',dist)
#img=cv2.imread('pict1.jpg')
# 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]
cv2.imwrite('calibresult.png',dst)
cv2.imshow('undistorted',dst)
cv2.waitKey(0)&0xFF
cv2.destroyAllWindows()
UPD:我试过用棋盘图案进行校准,但程序甚至不想识别该图案!这里有例子
检测到圆形图案:
因此程序据称可以检测到圆圈,但并不像预期的那样理想。
您可以尝试调整斑点检测器的参数。默认情况下 findCirclesGrid
使用 SimpleBlobDetector。所以尝试调整参数,例如:
params = cv2.SimpleBlobDetector_Params()
params.minArea = 10;
params.minDistBetweenBlobs = 5;
detector = cv2.SimpleBlobDetector_create(params)
然后将其传递给 findCirclesGrid:
cv2.findCirclesGrid(gray, (4,11),None,flags=cv2.CALIB_CB_ASYMMETRIC_GRID,detector)
另外你可以尝试使用cv2.CALIB_CB_ASYMMETRIC_GRID + cv2.CALIB_CB_CLUSTERING
有关 SimpleBlobDetector 及其参数的详细信息,请参阅 this tutrial。