web-dev-qa-db-ja.com

PythonおよびOpenCVエラーを使用したWebカメラのキャリブレーション

これらすべてにかなり新しいので、 this ガイドに従い、以下のコードを使用してWebカメラのキャリブレーションを実行しようとしています。次のエラーが発生します。

OpenCVエラー:collectCalibrationData、ファイル/build/buildd/opencv-2.4.8+dfsg1/modules/calib3d/src/calibration.cpp、行3193でアサーションが失敗しました(ni> 0 && ni == ni1)

cv2.error:/build/buildd/opencv-2.4.8+dfsg1/modules/calib3d/src/calibration.cpp:3193:エラー:(-215)ni> 0 && ni == ni1 in function collectCalibrationData

誰かがこのエラーとは何か、そしてそれを修正する方法を説明できますか?

(下部に完全なエラー)

import numpy as np
import cv2
import glob


criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world 
imgpoints = [] # 2d points in image plane.
images = glob.glob('*.png')


objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
objp = objp * 22


for fname in images:

    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    ret = False
    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, (6,9))
    # If found, add object points, image points (after refining them)
    if ret == True:
        objpoints.append(objp)
        cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)

        imgpoints.append(corners)
        # Draw and display the corners 
        cv2.drawChessboardCorners(img, (6,9), corners, ret)
        cv2.imshow('img',img)
        cv2.waitKey(0)

cv2.waitKey(0)
for i in range (1,5):
    cv2.waitKey(1)
    cv2.destroyAllWindows()
    cv2.waitKey(1)


ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)

OpenCVエラー:collectCalibrationData、ファイル/build/buildd/opencv-2.4.8+dfsg1/modules/calib3d/src/calibration.cpp、行3193トレースバック(最後の最後の呼び出し)でアサーションが失敗しました(ni> 0 && ni == ni1) ):ファイル ""、1行目、ファイル "/usr/lib/python2.7/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py"、540行目、runfile execfile(filename、namespace)ファイル"/home/student/Test/test.py "、49行目、ret、mtx、dist、rvecs、tvecs = cv2.calibrateCamera(objpoints、imgpoints、gray.shape [::-1]、None、None)cv2.error :/build/buildd/opencv-2.4.8+dfsg1/modules/calib3d/src/calibration.cpp:3193:エラー:(-215)ni> 0 && ni == ni1 in function collectCalibrationData

14
Pyroz

私はこれと同じ問題を抱えていました、そしてあなたの主な間違い(私が自分で作ったので私は知っています)はあなたがチェッカーボードのサイズを変更したことです(デフォルトは例では7x6、あなたは6x9です)が、初期化でサイズを変更することを怠っていますルーチンの先頭にあるコード

objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)

複数のチェッカーボードサイズでこれを機能させるには、次のようにコードを調整できます。

# checkerboard Dimensions
cbrow = 5
cbcol = 7

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

.
.
.
ret, corners = cv2.findChessboardCorners(gray, (cbcol, cbrow), None)
46
Paulus

ソースコードを掘り下げる:

_for( i = 0; i < nimages; i++, j += ni )
{
    Mat objpt = objectPoints.getMat(i);
    Mat imgpt1 = imagePoints1.getMat(i);
    ni = objpt.checkVector(3, CV_32F);
    int ni1 = imgpt1.checkVector(2, CV_32F);
    CV_Assert( ni > 0 && ni == ni1 );
    ...
_

これ:Assertion failed (ni > 0 && ni == ni1)は、オブジェクトポイントarrayの長さがゼロであるか、オブジェクト配列と画像配列のサイズが異なることを意味します。

明確にするために:calibrateCamera()は、オブジェクトポイントの配列と別の画像ポイントの配列だけでなく、画像とオブジェクトポイントの配列の配列が提供されることを期待しています。 。画像が1つしかない場合(したがって、画像とオブジェクトポイントのセットが1つしかない場合)、これらの配列を角かっこで囲むことができます。

_obj = [[x, y, z], [x1, y1, z1]] # wrong
img = [[x, y], [x1, y1]]        # wrong

obj = [[[x, y, z], [x1, y1, z1]]] # right
img = [[[x, y], [x1, y1]]]        # right
_

私が最初にこのチュートリアルに従ったときを振り返ると、変更したのはファイル拡張子(jpgからpng)だけで、独自のリソースを使用していることを示唆しているようです。したがって、問題は使用している画像の数。使用している1つまたは複数の画像で、チェッカーボードが正常に選択されていない可能性があると思います。したがって、オブジェクトポイント配列に何も追加されません。 calibrateCameraを実行する前に配列を印刷してみてください。おそらく、_/samples/cpp_内にあるチェッカーボードイメージを使用してください。

3
s-low

私も同じ問題を抱えていましたが、少し調べてみると、ここの回答に問題が見つかりました。

objpの形を変えて解決しました:

objp = objp.reshape(-1,1,3)

また、別の問題がありました。findChessboardCornersによって検出されたコーナーの数が7 * 6(パターンサイズ)未満になる可能性があるため、3Dポイントで検出されたコーナーの数を維持しました。

corners2 = cv2.cornerSubPix(image=gray, corners=corners, 
               winSize=(11,11), zeroZone=(-1,-1),
               criteria=(cv2.TERM_CRITERIA_EPS + 
                         cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))
imgpoints.append(corners2)
objpoints.append(objp[0:corners2.shape[0]])

その後、コードは正常に機能しました:D

[〜#〜] edit [〜#〜]retval(TrueまたはFalse)を使用する代わりに、次のことを確認すると、コーナーの数がパターンサイズより少なくなる可能性があることに気付きました。 cornersNoneではありません。

2
Marta Gómez

同じ問題が発生し、アサーションが失敗しました(ni> 0 && ni == ni1);最初の答えで話されたniとni1の本当の意味を学ぶべきだと思います。 objectpointとimagepointsは正確に同じサイズである必要があります。マットの数やサイズに関係なく。私の場合、私の問題は、イメージポイントとオブジェクトポイントの両方に5つのマットがあり、マットのサイズでは、イメージポイントが36 * 2で、オブジェクトポイントが48 * 3であるということです。したがって、1つがpoint2fで、もう1つがpoint3fであることを除いて、まったく同じである必要があると言いました。

0
Nan

次の例に従った場合:

opencvdoc

次に、問題は簡単に解決できます。これは、次の関数が原因です。

Corners2 = cv2.cornerSubPix(灰色、コーナー、(11,11)、(-1,1)、基準)

Opencvの現在のバージョンでは、Nullを返します

これも:

Img = cv2.drawChessboardCorners(img、(7.6)、corners2、ret)

だからあなたがしなければならないのはそれらのコード行を変更することだけです、これは私のコードの適応です:

from webcam import Webcam
import cv2
from datetime import datetime
import numpy as np

webcam = Webcam()
webcam.start()

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
objp = np.zeros((6*9,3), np.float32)
objp[:,:2] = np.mgrid[0:9,0:6].T.reshape(-1,2)
objpoints = []
imgpoints = []
i = 0

while i < 10:
    image = webcam.get_current_frame()
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    ret, corners = cv2.findChessboardCorners(gray, (9,6), None)    
    print ret

    if ret == True:
        cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)       
        imgpoints.append(corners)
        objpoints.append(objp)
        cv2.drawChessboardCorners(image, (9,6), corners,ret)
        i += 1


    cv2.imshow('grid', image)
    cv2.waitKey(1000)

cv2.destroyAllWindows()
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
np.savez("webcam_calibration_ouput_2", ret=ret, mtx=mtx, dist=dist, rvecs=rvecs, tvecs=tvecs)

ウェブカメラクラス:

import cv2
from threading import Thread

class Webcam:

    def __init__(self):
        self.video_capture = cv2.VideoCapture(0)
        self.current_frame = self.video_capture.read()[1]

    # create thread for capturing images
    def start(self):
        Thread(target=self._update_frame, args=()).start()

    def _update_frame(self):
        while(True):
            self.current_frame = self.video_capture.read()[1]

    # get the current frame
    def get_current_frame(self):
        return self.current_frame

チェスの寸法によって6と9の数字が変わる可能性があることに注意してください。私のチェスの寸法は、10x7でした。

0
Oscar Javier

ありがとう@ s-low!あなたのソースコードはとても役に立ちます。

初心者にとってもう1つの考えられる間違いは、objpのデータ型についてです。

objp = np.zeros((6*7,3), np.float32)を割り当てたとき、データ型の割り当てを無視しました。 python 2.7では、デフォルトのdtypeは_float64_です。したがって、コードが関数 '_cv2.calibrateCamera_'を呼び出していたとき、同様のアサーションがありました。エラー:

_OpenCV Error: Assertion failed (ni >= 0) in collectCalibrationData, file /Users/jhelmus/anaconda/conda-bld/work/opencv-2.4.8/modules/calib3d/src/calibration.cpp, line 3169
_

したがって、ソースコードni = objpt.checkVector(3, CV_32F)だけで、objpの行列を_float32_に割り当てる必要があるという手がかりが得られました。

0
Jundong

モバイルカメラで自分で撮った自分のjpg画像を入力しているときにも同じ問題が発生しました。最初に、あなたが共有しているリンクで利用可能なコードを実行していたとき、rectが常にFALSEに設定されていることがわかりました。後で、チェッカーボードのパターンを認識しないようにコードを作成するチェッカーボードの正確なサイズを入力していることがわかりました。つまり、サイズ8X6のチェッカーボードを使用し、コードに8X6を入力しました。たとえば、次のようになります。

objp = np.zeros((6*8,3), np.float32)
objp[:,:2] = np.mgrid[0:8,0:6].T.reshape(-1,2)

パターンを認識できなかったため、行と列の次元をそれぞれ1つ(または複数、私の場合は7X5)減らしてブームを起こしたとき、印刷された画像のパラメーターを次のように取得しました。出力。

objp = np.zeros(((5*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:5].T.reshape(-1,2)

また、このドキュメントを OpenCV 3.0ベータドキュメント に使用している場合は、修正が必要な可能性のある小さな変更があります。その違いは、 ここ に移動することで見つけることができます。

0
Bhanu Chander

したがって、エラーは、オブジェクトと同じ長さである必要があるときにimgpointsが1つの長い配列であることが原因であることがわかりました。 1つの画像を使用すると、キャリブレーション関数内のimgpointをコーナーに直接置き換えることができることがわかりました。同じエラーのある人に役立つことを願っています。

(途中でいくつかの変更を加えましたが、複数の画像を使用するように修正しようとしています)

import numpy as np
import cv2
import glob

# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# Arrays to store object points and image points from all the images.

imgpoints = [] # 2d points in image plane.
images = glob.glob('*.png')

for fname in images:

    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    ret = False
    # Find the chess board c  orners
    ret, corners = cv2.findChessboardCorners(gray, (6,9))
    # If found, add object points, image points (after refining them)
    if ret == True:
        cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
        imgpoints.append(corners)
        # Draw and display the corners 
        cv2.drawChessboardCorners(img, (6,9), corners, ret)
        cv2.imshow('img',img)
        cv2.waitKey(0)

cv2.waitKey(0)
for i in range (1,5):
    cv2.waitKey(1)
    cv2.destroyAllWindows()
    cv2.waitKey(1)
imgpoints = np.array(imgpoints,'float32')
print len(corners), len(pattern_points)



pattern_size = (9, 6)
pattern_points = np.zeros( (np.prod(pattern_size), 3), np.float32)
pattern_points[:, :2] = np.indices(pattern_size).T.reshape(-1, 2).astype(np.float32)
pattern_points = np.array(pattern_points,dtype=np.float32)

ret, matrix, dist_coef, rvecs, tvecs = cv2.calibrateCamera([pattern_points], [corners], gray.shape[::-1], flags=cv2.CALIB_USE_INTRINSIC_GUESS)
0
Pyroz