OpenCV 5.0.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 5.0.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
ArUcoとChArUcoによるキャリブレーション

前のチュートリアル: Diamondマーカーの検出
次のチュートリアル: Arucoモジュール FAQ
ArUcoモジュールはカメラのキャリブレーションにも使用できる。カメラキャリブレーションは、カメラの内部パラメータと歪み係数を取得することからなる。これらのパラメータはカメラの光学系が変更されない限り固定されたままであるため、カメラキャリブレーションは一度だけ行えばよい。

カメラキャリブレーションは通常、OpenCVの cv::calibrateCamera() 関数を使用して実行される。この関数は、異なる視点からの環境点とそのカメラ画像への投影との間の対応関係を必要とする。一般に、これらの対応関係はチェスボードパターンのコーナーから得られる。より詳細な情報は cv::calibrateCamera() 関数のドキュメントまたはOpenCVキャリブレーションチュートリアルを参照。

ArUcoモジュールを使用すると、ArUcoマーカーのコーナーまたはChArUcoコーナーに基づいてキャリブレーションを行える。ArUcoを使ったキャリブレーションは、オクルージョンや部分的な視界を許容するため、従来のチェスボードパターンを使うよりもはるかに柔軟である。

述べたとおり、キャリブレーションはマーカーのコーナーとChArUcoコーナーのどちらを使っても行える。ただし、提供されるコーナーがマーカーのコーナーに比べてはるかに正確であるため、ChArUcoコーナーを用いる手法を強く推奨する。標準のボードを使ったキャリブレーションは、何らかの制約によりChArUcoボードを使用できない状況においてのみ用いるべきである。

ChArUco ボードによるキャリブレーション

ChArUcoボードを使ってキャリブレーションするには、標準キャリブレーションが従来のチェスボードパターンで行うのと同じように、異なる視点からボードを検出する必要がある。ただし、ChArUcoを使う利点により、オクルージョンや部分的な視界が許容され、すべての視点ですべてのコーナーが見えている必要はない。

ChArUco calibration viewpoints

cv::aruco::CharucoBoard に対して cv::calibrateCamera() を使用する例:

// Create charuco board object and CharucoDetector
aruco::CharucoBoard board(Size(squaresX, squaresY), squareLength, markerLength, dictionary);
aruco::CharucoDetector detector(board, charucoParams, detectorParams);
// Collect data from each frame
vector<Mat> allCharucoCorners, allCharucoIds;
vector<vector<Point2f>> allImagePoints;
vector<vector<Point3f>> allObjectPoints;
vector<Mat> allImages;
Size imageSize;
while(inputVideo.grab()) {
Mat image, imageCopy;
inputVideo.retrieve(image);
vector<int> markerIds;
vector<vector<Point2f>> markerCorners;
Mat currentCharucoCorners, currentCharucoIds;
vector<Point3f> currentObjectPoints;
vector<Point2f> currentImagePoints;
// Detect ChArUco board
detector.detectBoard(image, currentCharucoCorners, currentCharucoIds);
if(key == 'c' && currentCharucoCorners.total() > 3) {
// Match image points
board.matchImagePoints(currentCharucoCorners, currentCharucoIds, currentObjectPoints, currentImagePoints);
if(currentImagePoints.empty() || currentObjectPoints.empty()) {
cout << "Point matching failed, try again." << endl;
continue;
}
cout << "Frame captured" << endl;
allCharucoCorners.push_back(currentCharucoCorners);
allCharucoIds.push_back(currentCharucoIds);
allImagePoints.push_back(currentImagePoints);
allObjectPoints.push_back(currentObjectPoints);
allImages.push_back(image);
imageSize = image.size();
}
}
Mat cameraMatrix, distCoeffs;
if(calibrationFlags & CALIB_FIX_ASPECT_RATIO) {
cameraMatrix = Mat::eye(3, 3, CV_64F);
cameraMatrix.at<double>(0, 0) = aspectRatio;
}
// Calibrate camera using ChArUco
double repError = calibrateCamera(allObjectPoints, allImagePoints, imageSize, cameraMatrix, distCoeffs,
noArray(), noArray(), noArray(), noArray(), noArray(), calibrationFlags);

各視点で取得したChArUcoコーナーとChArUco識別子は、ベクトル allCharucoCornersallCharucoIds に、視点ごとに1要素として格納される。

calibrateCamera() 関数は、cameraMatrixdistCoeffs の配列にカメラキャリブレーションパラメータを格納する。この関数は、キャリブレーションから得られた再投影誤差を返す。rvecstvecs の要素には、各視点における(ChArUcoボードに対する)推定されたカメラ姿勢が格納される。

最後に、calibrationFlags パラメータはキャリブレーションのオプションの一部を決定する。

完全に動作する例は、samples/cpp/tutorial_code/objectDetection フォルダ内の calibrate_camera_charuco.cpp に含まれている。

このサンプルは現在、cv::CommandLineParser を介してコマンドラインから入力を受け取る。このファイルの場合、例のパラメータは次のようになる:

"camera_calib.txt" -w=5 -h=7 -sl=0.04 -ml=0.02 -d=10
-v=path/img_%02d.jpg

opencv/samples/cpp/tutorial_code/objectDetection/tutorial_camera_charuco.yml のカメラキャリブレーションパラメータは、このフォルダに配置された img_00.jpg-img_03.jpg によって取得された。

ArUco ボードによるキャリブレーション

述べたとおり、ChArUcoコーナーはマーカーのコーナーよりも正確であるため、カメラキャリブレーションにはArUcoボードではなくChArUcoボードの使用が推奨される。ただし、いくつかの特殊なケースではArUcoボードに基づくキャリブレーションを使用することが求められる場合がある。前述の場合と同様に、異なる視点からArUcoボードを検出する必要がある。

ArUco calibration viewpoints

cv::aruco::GridBoard に対して cv::calibrateCamera() を使用する例:

// Create board object and ArucoDetector
aruco::GridBoard gridboard(Size(markersX, markersY), markerLength, markerSeparation, dictionary);
aruco::ArucoDetector detector(dictionary, detectorParams);
// Collected frames for calibration
vector<vector<vector<Point2f>>> allMarkerCorners;
vector<vector<int>> allMarkerIds;
Size imageSize;
while(inputVideo.grab()) {
Mat image, imageCopy;
inputVideo.retrieve(image);
vector<int> markerIds;
vector<vector<Point2f>> markerCorners, rejectedMarkers;
// Detect markers
detector.detectMarkers(image, markerCorners, markerIds, rejectedMarkers);
// Refind strategy to detect more markers
if(refindStrategy) {
detector.refineDetectedMarkers(image, gridboard, markerCorners, markerIds, rejectedMarkers);
}
if(key == 'c' && !markerIds.empty()) {
cout << "Frame captured" << endl;
allMarkerCorners.push_back(markerCorners);
allMarkerIds.push_back(markerIds);
imageSize = image.size();
}
}
Mat cameraMatrix, distCoeffs;
if(calibrationFlags & CALIB_FIX_ASPECT_RATIO) {
cameraMatrix = Mat::eye(3, 3, CV_64F);
cameraMatrix.at<double>(0, 0) = aspectRatio;
}
// Prepare data for calibration
vector<Point3f> objectPoints;
vector<Point2f> imagePoints;
vector<Mat> processedObjectPoints, processedImagePoints;
size_t nFrames = allMarkerCorners.size();
for(size_t frame = 0; frame < nFrames; frame++) {
Mat currentImgPoints, currentObjPoints;
gridboard.matchImagePoints(allMarkerCorners[frame], allMarkerIds[frame], currentObjPoints, currentImgPoints);
if(currentImgPoints.total() > 0 && currentObjPoints.total() > 0) {
processedImagePoints.push_back(currentImgPoints);
processedObjectPoints.push_back(currentObjPoints);
}
}
// Calibrate camera
double repError = calibrateCamera(processedObjectPoints, processedImagePoints, imageSize, cameraMatrix, distCoeffs,
noArray(), noArray(), noArray(), noArray(), noArray(), calibrationFlags);

完全に動作する例は、samples/cpp/tutorial_code/objectDetection フォルダ内の calibrate_camera.cpp に含まれている。

このサンプルは現在、cv::CommandLineParser を介してコマンドラインから入力を受け取る。このファイルの場合、例のパラメータは次のようになる:

"camera_calib.txt" -w=5 -h=7 -l=100 -s=10 -d=10 -v=path/aruco_videos_or_images