使用OpenCV进行相机标定 - cv2.getOptimalNewCameraMatrix的结果为零ROI。

4

这是我在stackoverflow上的第一篇文章。如果我的英语和编程知识有所影响,请原谅。

好的,我正在尝试在Windows 8.1操作系统中使用OpenCV 2.4.9进行相机标定(Ubuntu操作系统无法解决问题)。

问题:我正在使用下面的代码对相机进行标定,但似乎如果我的样本图像(带有棋盘格图案)数量超过2个,则newcameramtx、roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))的ROI结果为[0,0,0,0]。样本数与该结果有何关系?(在更改此代码之前,先前的最大样本数为12)。

说到最大样本数,我的意思是从我的相机获取的带有棋盘格图案的图像,如果数量超过最大数量,那么ROI将不能给出良好的结果。

角点检测非常好。您可以在这里找到我的示例图像。

# -*- coding: utf-8 -*-
"""
Created on Fri May 16 15:23:00 2014

@author: kakarot
"""

import numpy as np
import cv2
#import os
#import time
from matplotlib import pyplot as plt
LeftorRight = 'L'

numer = 12
chx = 6
chy = 9
chd = 25
# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, numer, 0.001)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((chy*chx,3), np.float32)
objp[:,:2] = np.mgrid[0:chy,0:chx].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space, (x25mm)
imgpoints = [] # 2d points in image plane.

enum = 1

while(enum<=numer):
    img=cv2.imread('1280x720p/BestAsPerMatlab/calib_'+str(LeftorRight)+str(enum)+'.jpg')

    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, (chy,chx),None)
    #cv2.imshow('Calibration',img)

    # If found, add object points, image points (after refining them)
    if  ret == True and enum <= numer:

        objpoints.append(objp*chd)


        cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        imgpoints.append(corners)


        # Draw and display the corners
        cv2.drawChessboardCorners(img, (chy,chx),corners,ret)
        cv2.imshow('Calibration',img)
        cv2.imwrite('1280x720p/Chessboard/calibrated_L{0}.jpg'.format(enum),img)
        print enum

        #time.sleep(2)
        if enum == numer:
            ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)

            img = cv2.imread('1280x720p/BestAsPerMatlab/calib_'+str(LeftorRight)+'7.jpg')
            gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
            h,  w = img.shape[:2]           #a (1 to see the whole picture)
            newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
            if (np.size(roi) == 4 and np.mean(roi) != 0):
                # undistort
                mapx,mapy = cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
                dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)

                # crop the image
                x,y,w,h = roi
                dst = dst[y:y+h, x:x+w]
                dst = cv2.cvtColor(dst,cv2.COLOR_RGB2BGR)
                plt.imshow(dst)
                #cv2.imwrite('result.jpg',dst)
                #np.savetxt('mtxL.txt',mtx)
                #np.savetxt('distL.txt',dist)
            else:
                np.disp('Something Went Wrong')
        enum += 1
'''
    k = cv2.waitKey(1) & 0xFF
    if k == 27:
        break
'''
cv2.destroyAllWindows()

编辑: 我正在使用两个廉价的USB相机。我发现一个相机的样本集很好,而且我可以使用超过19个样本而没有问题。但是当使用另一个相机的校准样本时,最多只能使用2个样本图像。(如果我制作另一个样本集,数量将会有所变化)。总的来说,似乎存在某些与所产生校准矩阵相关的问题。但这是很奇怪的。

最后,我正在使用鱼眼相机,认为在每次拍摄的末端裁剪足够的像素就可以模拟普通相机......也许这就是导致我麻烦的原因!


你应该为你的问题找一个更好的标题。 - phil652
你是完全正确的。我忘了,谢谢。 - 2nisi
2
你能让它适用于鱼眼相机吗?在我的情况下,似乎在getOptimalNewCameraMatrix中调用的c++代码中的icvGetRectangles函数无法处理大视场角相机。它找不到内部和外部矩形。 - Romanzo Criminale
1个回答

1

你应该将 dist 改为

dist = np.array([-0.13615181, 0.53005398, 0, 0, 0]) # no translation

然后进行调用

newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))

它对我起作用了。


你使用的是哪个相机(视野)? - Romanzo Criminale
我正在使用一款惠普的简单网络摄像头。 - Sam
dist数组中的最后一个参数不需要为0,只有数组索引2和3控制着翻译,其他的是径向畸变参数。 - aaron
@Sam,你是怎么计算它们的? - hamid kavianathar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接