11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

charucoキャリブレーションボード

Posted at

はじめに

OpenCVでカメラキャリブレーションをする場合、ターゲットとしてチェスボード画像サークルグリッド画像を使う場合が多いと思います。
キャリブレーションについて調査中、チェスボード画像の白いマスの部分に何かQRコード風の模様が付いているものを見かけることがありました。
調べてみると、Opencv contribのARマーカー検出等のモジュールであるarucoモジュールの中の機能の一つ、charucoモジュールとのことだったので、試しに使ってみることにしました。

参考

ソースコードなどはOpenCVのリファレンスを参考にしています。
https://docs.opencv.org/4.1.2/df/d4a/tutorial_charuco_detection.html

ボード画像の作成

まずはじめに、キャリブレーションに使うボードの画像を作る必要がありますが、その画像を作成する機能もcharucoモジュールに含まれています。
次のコードで、キャリブレーション画像を作成できます。

main.cpp
#include <opencv2/opencv.hpp>
#include <opencv2/aruco/charuco.hpp>

int main(int argc, const char * argv[]) {
    //マーカ辞書作成 6x6マスのマーカを250種類生成
    cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
    
    //charucoボード生成 10x7マスのチェスボード、グリッドのサイズ0.04f、グリッド内マーカのサイズ0.02f
    cv::Ptr<cv::aruco::CharucoBoard> board = cv::aruco::CharucoBoard::create(10, 7, 0.04f, 0.02f, dictionary);
    cv::Mat boardImage;
    board->draw(cv::Size(1920, 1080), boardImage, 10, 1);
    cv::imwrite("BoardImage.jpg", boardImage);
}

↓のような画像が出力できます。
BoardImage.jpg

この画像を紙などに印刷してキャリブレーション用の撮影を行います。
今回は面倒だったのでノートPCにモニターに写した状態で撮影してみます。

検出

カメラはiPhone XSのカメラを使いました。

検出のソースコードは次のとおりです。

main.cpp
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/aruco/charuco.hpp>

int detectCharucoBoard(std::string srcPath, std::string dstPath)
{
    cv::Mat image = cv::imread(srcPath);
    cv::Mat imageCopy = image.clone();
    
    //マーカ辞書作成 6x6マスのマーカを250種類生成
    cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
    
    //charucoボード生成 10x7マスのチェスボード、グリッドのサイズ0.04f、グリッド内マーカのサイズ0.02f
    cv::Ptr<cv::aruco::CharucoBoard> board = cv::aruco::CharucoBoard::create(10, 7, 0.04f, 0.02f, dictionary);
    
    //マーカー検出時メソッドを指定
    cv::Ptr<cv::aruco::DetectorParameters> params = cv::aruco::DetectorParameters::create();
    params->cornerRefinementMethod = cv::aruco::CORNER_REFINE_NONE;
    
    //マーカー検出
    std::vector<int> markerIds;
    std::vector<std::vector<cv::Point2f> > markerCorners;
    cv::aruco::detectMarkers(image, board->dictionary, markerCorners, markerIds, params);
    
    if (markerIds.size() > 0) {
        
        //マーカー位置を描画
        cv::aruco::drawDetectedMarkers(imageCopy, markerCorners, markerIds);
        
        //マーカーの座標をもとに、チェスボード画像の交点を検出
        std::vector<cv::Point2f> charucoCorners;
        std::vector<int> charucoIds;
        cv::aruco::interpolateCornersCharuco(markerCorners, markerIds, image, board, charucoCorners, charucoIds);
        if (charucoIds.size() > 0)
        {
            //チェスボード交点位置を描画
            cv::aruco::drawDetectedCornersCharuco(imageCopy, charucoCorners, charucoIds, cv::Scalar(0, 0, 255));
        }
    }
    
    cv::imwrite(dstPath, imageCopy);
    
    return 0;
}


int main(int argc, const char * argv[]) {
    
    detectCharucoBoard("./IMG_5410.jpeg", "./IMG_5410_detect.jpg");
    detectCharucoBoard("./IMG_5411.jpeg", "./IMG_5411_detect.jpg");
    detectCharucoBoard("./IMG_5412.jpeg", "./IMG_5412_detect.jpg");
    
    return 0;
}

画像を見てみましょう。
この画像が…
IMG_5410.jpeg

こうなります。マーカー(青いid)もチェスボード交点(赤いid)も両方検出できているようです。
IMG_5410_detect.jpg

これだけなら、別に普通のチェスボードでも良くない?という感じがします。

ただし、画像を見てもらうとわかるように、charucoモジュールで検出されるチェスボードの交点には、それぞれ別々のid番号が振ってあります。おそらく、この交点idは、交点に対して最も近いマーカのidをもとに割り振っているものと思われます。これによって通常のチェスボードとは若干異なる撮影ができるようになります。それは…
IMG_5411.jpeg
IMG_5411_detect.jpg
このように、ボード全体が写っていなくても、チェスボード交点が検出できるようになります。
通常のチェスボード交点検出関数cv::findChessboardCornersだと、指定したマスのチェスボード画像全体が写っていないと検出ができません。なのでカメラをボードに近づけたり、ボードを画角の端側で撮影しようとすると、ボードが画角外にはみ出してボードが検出できなくなることがありました。そのせいで通常のチェスボードだとキャリブレーション用の撮影自体が結構面倒だったり難しかったりすることが多いのですが、これを使えば効率よく撮影できそうですし、チェスボードの一部でも良いこと、全体を写さなくていいことを利用して色々と応用できそうです。

ちなみにもっとアップで撮影してもOKでした。
IMG_5412.jpeg
IMG_5412_detect.jpg

まとめ

charucoのボード検出をやってみました。
従来のチェスボードとは仕様が異なる検出ができたので、どう応用するかを考えてみたいと思います。

11
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?