使用圆形图案进行相机校准

问题描述 投票:0回答:2

我正在按照 本教程 在 Raspberry Pi 上校准我的相机(带有一些镜头),但使用 圆形图案 而不是棋盘图案。问题是,生成的未失真图像被缩小并且不完整,当我从代码中得到每次缩小时,它看起来像的右侧部分(通常情况更糟)。问题是是否可以对代码做一些事情,以便它会给出像教程中的示例这样的图片。我必须使用棋盘图案吗?

我的代码:

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:我尝试过使用棋盘图案进行校准,但程序甚至不想识别该图案!以下是示例 检测到圆形图案:

因此,据称该程序可以检测到圆圈,但并不如预期的那么理想。

python-3.x opencv raspberry-pi camera-calibration
2个回答
3
投票

您可以尝试调整斑点检测器的参数。默认情况下,

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 及其参数的更多信息,请参阅 本教程


0
投票
I want to ask about the method that u use for cv2.findCirclesGrid() Implement circles calibration. N.B. after using ``cv2.findCirclesGrid()`` a point refinement algorithm is needed (like  ``cv2.cornerSubPix()`` does for the chessboard).

Thnaks

© www.soinside.com 2019 - 2024. All rights reserved.