Help us understand the problem. What is going on with this article?

キャリブレーションパターンの管理と生成

More than 1 year has passed since last update.

はじめに

キャリブレーションパターンの作り方

  • キャリブレーションパターンを作るサイトスクリプト手順など、多数公開されており、その意味ではN番煎じも甚だしい記事です。
  • ただし、通常と違うのは、今回は「バージョン管理も念頭に入れ」て、「ベクタ形式で生成する」ことです

後日談というか、今回のオチ

  • ビルドするとチェッカーパターンのパワーポイント(pptx)を生成するプログラムを公開しました
  • ここでパターンの数とサイズを指定して
    cmake.png

  • こうなって
    vs.png

  • こう
    ppt.png

  • という具合にビルドするだけでパワーポイント用のバイナリファイルが作られます

  • あとはこれを、「倍率指定100%」で印刷する(用紙サイズ指定ではありません)と、誤差1mm以下の精度で印刷してくれます1

  • プリンタで印刷するとサイズが変わってしまう報告がありますが、私が試した限りでは、「用紙指定」ではなく「倍率指定」なのがキモ、という認識です。

    中身の詳細

  • 大まかに説明すれば

    • xmlファイルを複数含むディレクトリをプログラムで生成
    • ディレクトリを単一zipファイルに圧縮
    • zipファイルをpptxにリネーム
  • をしているだけです。

  • Office は拡張子の末尾にxがつくようになってから、ファイルの実態は複数のxmlファイルを単一のファイルにZIP形式で圧縮したもの、となりました

  • 今回はCMakeを使ってpptxファイルを生成しています

円形キャリブレーションパターンの方が精度良いんじゃないの?

  • はい、随所で円形パターンの方が精度が良いことが報告されています
  • なので、cmakeを使ってる理由はそこで、cmakeのコンフィグ時に、パターンの個数や長さの他に種類も変更できるようにしてあります
    explanationGenerator.png

  • 図中にも示しましたが、MARKER_TYPESmarker_Chessboardmarker_CircleSymmetricalmarkerCircleAsymmetricalの3種類があり、それぞれ

    • チェッカーボード
    • 円形パターン(格子)
    • 円形パターン(互い違いに配置)
  • となっております

  • この通り
    circleSymmetricalCapture.png

  • 色んなパターンも生成できます
    circleAsymmetricalCapture.png

印刷がきれいになるだけなの?

  • 最大の特徴が、キャリブレーションパターンの情報がヘッダファイルに生成される点です
  • このプロジェクトをcmakeでコンフィグすると、buildディレクトリ直下にconfig.hというファイルが生成されます
config.h
#ifndef CONFIGURE_H_INCLUDED
#define CONFIGURE_H_INCLUDED

/* number of markers in column */
const int cNumMarkerCols = 4;

/* number of markers in row */
const int cNumMarkerRows = 9;

/* gap between markers in cm (= size of each box of chessboard) */
const float cMarkerGap = 1.0f; // in cm

/* diameter of the circle in cm (not used for chessboard) */
const float cSizeCircle = 0.5f; // in cm

/* offset from the edge in cm */
const float cOffset = 1.0f; // in cm

/* name of powerpoint slide file name */
#define DEFAULT_XML_FILENAME "slide1.xml"

/* name of thumbnail file */
#define THUMBNAIL_FILENAME "thumbnail.jpeg"

enum markerType
{
    marker_Chessboard,
    marker_CircleSymmetrical,
    marker_CircleAsymmetrical,
};

const enum markerType cMarkerType = marker_Chessboard;

#endif // CONFIGURE_H_INCLUDED
  • で、この中に先程のパターン数、パターンの種類、長さ、全ての情報が埋め込まれているわけです。
    • cmakeのコマンド、configure_fileがあり、これよってファイルの中に埋め込んだ変数がcmakeで得られた実際の数値/文字列に置き換えられます
    • OpenCVのHAVE_FFMPEGとかWITH_OPENCLを持つ、cvconfig.hと同じ方法です
  • 何が良いかというと、これのおかげでソースコードとキャリブレーションパターンが一意にバージョン管理することができるのが最大のウリです。
  • キャリブレーションパターンとソースコード、別々に管理してたりしませんか?
    • そもそもgit、ひいてはGithubはあまりバイナリの管理には向いていません
    • 圧縮して全履歴を保存することが理由ですが、バイナリには圧縮がほとんどきかないため、Gitのリポジトリに入れると、容易にサイズが肥大化します
    • そのような理由からGithubでも1コミットのサイズに制約がついています

You will not be allowed to push files larger than 100 MB.

  • もちろんそれでもパワーポイントのpptxファイル、特にキャリブレーションパターン程度ならばkbオーダなので、無視してもいいぐらいのサイズです。
  • しかしながら、あとから実験の記録を見返したときに、「あれ?このキャリブレーションパターンいつ使ったんだっけ?」とか、「この写真中のボード、間隔何cmだったかな?」とか、悩んだりしないでいいわけです!
  • その時点の実験を再現するならば、ビルドするだけで、全く同じキャリブレーションパターンを生成できるからです!すごい!

このプログラムキャリブレーションパターン生成するだけ?

  • キャリブレーションパターンを生成してそれでおしまいということはまず無いので、このソースコードを使いたい人は、何らかキャリブレーション用ソースコードとともに、このCMakeLists.txtを管理したいと考えていると思います
  • ここでは、その応用した使い方を紹介したいと思います
    • 直接埋め込む方法
    • execute_process でcmake時点でビルドする方法

直接埋め込む方法

  • 詳細は割愛します。公開したプロジェクトをforkなりダウンロードなりして改造してくれれば良いと思います

execute_process を使う方法

  • CMakeにはexecute_processという強力な機能があります。
  • cmakeするときに、裏側でソースのダウンロード、cmakeによるconfiguration、ビルド、実行までcmakeの裏側で行えます
  • パターンを再生成するためには、cmakeからやり直す必要があります
    • が現実問題パターンの生成をやり直すことはそうそうないのではないでしょうか。
    • 以下のコードをご自身のCMakeLists.txtに追加するだけで、裏側で勝手にpptxが生成さる、手軽さがウリです。
    • pptxbuild\third-party\build\generated.pptxに生成されます。
    • 下記の例では${TARGET_NAME}ターゲットをmain.cppから生成して、その際にcalibrationPatternGeneratorが生成するconfig.hをインクルードしています
CMakeLists.txt
set(PATTERN_GENERATOR_WORK  "${CMAKE_BINARY_DIR}/third-party")
set(PATTERN_GENERATOR_BUILD "${PATTERN_GENERATOR_WORK}/build")
set(DOWNLOADED_ZIP          "${CMAKE_BINARY_DIR}/patternGenerator.zip")
file(MAKE_DIRECTORY ${PATTERN_GENERATOR_WORK} ${PATTERN_GENERATOR_BUILD})
file(DOWNLOAD "https://github.com/tomoaki0705/calibrationPatternGenerator/archive/v1.0.zip" ${DOWNLOADED_ZIP})
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xz ${DOWNLOADED_ZIP} WORKING_DIRECTORY ${PATTERN_GENERATOR_WORK})
execute_process(COMMAND ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} "../calibrationPatternGenerator-1.0/" WORKING_DIRECTORY ${PATTERN_GENERATOR_BUILD})
execute_process(COMMAND ${CMAKE_COMMAND} --build . --target ALL_BUILD --config Release WORKING_DIRECTORY ${PATTERN_GENERATOR_BUILD})

# executable
add_executable(${TARGET_NAME} main.cpp ${PATTERN_GENERATOR_BUILD}/config.h)

実際にやってみた

  • チェスボード
    • captureChessboard.png
    • resultChessboard.png
  • 円形パターン(格子)
    • captureSymmetricalCircle.png
    • resultSymmetricalCircle.png
  • 円形パターン(互い違いに配置)
    • captureAsymmetricalCircle.png
    • resultAsymmetricalCircle.png

苦労した点

日本語に苦労(xml作成編)

  • もちろん最初は手動でpptxファイルを作り、それと同じコンテンツをプログラムから出力しようとしました
  • が、一向にエラーで開けない2
  • 最終的にはバイナリエディタで比較したところ、「楕円1」という文字列がもとのpptxにあり、それをダイレクトに出力すると文字コードの関係でファイルのエンコードが破壊されていました
  • なので、日本語を諦めて「ellipse 1」もしくは「box 1」と修正

圧縮プログラムに苦労

  • 実はcmakeには、標準で複数ファイルを圧縮する機能がついています
  • cmake -E tar cf hoge.zip file1.xml file2.xml とコマンドを叩くと、cmakeが圧縮ファイルを作ってくれます
  • が、これも何故かpptxとしては開けない。バイナリエディタで比較すると、どうにもファイルフォーマットがzipでない模様。
  • で、コマンドがtarとなってるので、ファイル名はzipでも、tar圧縮されたファイルが生成されていた、というオチ
  • 仕方ないので7zipの実行バイナリをcmake時にダウンロードして来て、裏で実行するスクリプトに改造したのですが、そのあとで、cmakeの3.3からzipフォーマットでの出力がサポートされたことを発見3
  • cmake -E tar cf hoge.zip --format=zip file1.xml file2.xml と、formatオプションを渡すと、ちゃんとZIPファイルとして作ってくれる。

まとめ

  • 筆者は以下の環境で検証しました
項目 環境1 環境2 環境3
OS Windows 7 Professional 64bit Windows 10 Pro 64bit Ubuntu 14.04 32bit
Office 2016 2016 20164
OpenCV 3.3.0 3.2.0 3.1.0
コンパイラ Visual Studio 2013 Update 5 Visual Studio 2013 Update 5 gcc 4.8.4
CMake 3.9.1 3.10.0 3.5.1
CUDA 8.0 8.0 -
  • 明日はTaroYamadaさんの記事で、執筆時点でのタイトルは「仮) OpenCV と Intel Movidius Neural Compute Stick のSDKを連携させた。」です。楽しみ!

補足

pptxだけしかダメなの?docxは?

  • 検証していませんが、docxも中身はzipファイルです。本プログラムを改造して、docxを出力するようにすれば申請書のフォーマットに則ってdocxファイルを出力したり、ネ申エクセルのフォーマットに則ったxlsxファイルを出力することも原理的には可能のはずです。うまくいけば、texファイルからdocxを生成できる夢もあるかも知れません(が、恐ろしく高い障壁が立っている気もします)

OpenCV関係なくね?CMakeだけじゃね?

XMLを直書きしてるけれど、OpenCVのFileStorageクラスは使わなかったの?

  • OpenCVにはxmlで行列やパラメータを書き出せるcv::FileStorageクラスが存在します
  • 実はこれで書き出すことも試したのですが、実は書き出す以前に読み込むことに失敗しました。
  • ですので、どうやらOffice用のxmlとOpenCVがパースできるxmlのフォーマットのどこかに差異があるようです
  • 今回はそこまで検証しておりません、あしからず

  1. 最近のプリンタはすごいですね。 

  2. 誤ったフォーマットのpptxファイルをパワーポイントで開こうとすると、「ファイルが壊れています」というダイアログが表示され、無情にも真っ白なファイルが。。。 

  3. リンク先には「3.2から」と書かれているが、Windows版のバイナリで検証した結果、多分3.2では非対応で、3.3から対応が盛り込まれた 

  4. Linuxで生成した後にWindowsにpptxファイルだけ転送。この表には記載しなかったが、OpenOfficeでも開けることだけは確認した。印刷は試してないので不明。 

  5. 検証していませんが、多分2.4系列でも動くのではないかと思います 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away