データの書き込み
■ データの書き込み
OpenCVでは, "opencv-matrix", "opencv-nd-matrix", "opencv-sparse-matrix", "opencv-image", "opencv-sequence", "opencv-sequence-tree", "opencv-graph" の7種類の型は標準タイプとして定義されているので,簡単に保存することができる. また,ユーザ定義のオブジェクトや複数オブジェクトをまとめた書き込みなど,自由度の高いファイルへの保存が可能である. この関数は,キャリブレーションのサンプルコードでも利用されている.サンプル
IplImage構造体情報の保存 cvWrite, cvWriteComment
IplImage構造体の情報をファイルに保存する
サンプルコード
#include <cv.h>
#include <highgui.h>
int
main (int argc, char *argv[])
{
IplImage *color_img, *gray_img;
CvRect roi;
CvFileStorage *fs;
// (1)画像を読み込む
if (argc != 2 || (color_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR)) == 0)
return -1;
// (2)ROIの設定と二値化処理
gray_img = cvCreateImage (cvGetSize (color_img), IPL_DEPTH_8U, 1);
cvCvtColor (color_img, gray_img, CV_BGR2GRAY);
roi = cvRect (0, 0, color_img->width / 2, color_img->height / 2);
cvSetImageROI (gray_img, roi);
cvSetImageROI (color_img, roi);
cvThreshold (gray_img, gray_img, 90, 255, CV_THRESH_BINARY);
// (3)xmlファイルへの書き出し
fs = cvOpenFileStorage ("images.xml", 0, CV_STORAGE_WRITE);
cvWriteComment (fs, "This is a comment line.", 0);
cvWrite (fs, "color_img", color_img);
cvStartNextStream (fs);
cvWrite (fs, "gray_img", gray_img);
cvReleaseFileStorage (&fs);
cvReleaseImage (&color_img);
cvReleaseImage (&gray_img);
return 0;
}
// (1)画像を読み込む
関数 cvLoadImageにより,保存するためのカラー画像を読み込む.
// (2)ROIの設定と二値化処理
関数cvCvtColorによりカラー画像をグレースケール画像に変換し,関数cvSetImageROIによりROIを設定する.
また,変換した画像に対して二値化処理を施す.
// (3)xmlファイルへの書き出し
関数cvWriteにより,入力されたカラー画像と変換・処理されたグレースケール画像をファイルに書き出す.
関数cvSaveImageとは異なり,オブジェクトの情報をデータとして保存する.
また,ここでは,二つのIplImage構造体のデータを一つのファイルに書き出しているが,
一つのデータを一つのファイルに書き出す場合は,
cvSave("image.xml", color_img);のようにして保存しても良い.関数cvSaveの内部では,関数cvWriteが呼び出される. 関数cvStartNextStream()は,ファイル書き込み中のストリームを新しくする関数であり,この場所で
<!-- next stream -->
というコメントと改行が挿入されるだけである(今回の場合,標準タイプのデータをトップレベルに書き込むだけなので).
もちろん,複数のファイルを書き込む際に必須というわけではない.
実行結果例
images.xml.zipが実際に書き出されたファイルである. 以下のスナップショットからも分かるように,ROIなどの情報も保存されている.マップのシーケンスを保存 cvStartWriteStruct, cvEndWriteStruct
二つのエントリを持つマップのシーケンスをファイルに保存する
サンプルコード
#include <cv.h>
#include <highgui.h>
#include <time.h>
int
main (int argc, char *argv[])
{
int size = 20;
int i;
CvFileStorage *fs;
CvRNG rng = cvRNG (time (NULL));
CvPoint *pt = (CvPoint *) cvAlloc (sizeof (CvPoint) * size);
// (1)点列の作成
for (i = 0; i < size; i++) {
pt[i].x = cvRandInt (&rng) % 100;
pt[i].y = cvRandInt (&rng) % 100;
}
// (2)マップのシーケンスとして点列を保存
fs = cvOpenFileStorage ("sequence.yml", 0, CV_STORAGE_WRITE);
cvStartWriteStruct (fs, "points", CV_NODE_SEQ);
for (i = 0; i < size; i++) {
cvStartWriteStruct (fs, NULL, CV_NODE_MAP | CV_NODE_FLOW);
cvWriteInt (fs, "x", pt[i].x);
cvWriteInt (fs, "y", pt[i].y);
cvEndWriteStruct (fs);
}
cvEndWriteStruct (fs);
cvReleaseFileStorage (&fs);
return 0;
}
// (1)点列の作成
ランダムな値を持つ,CvPoint型の配列(要素数20)を作成する.
// (2)マップのシーケンスとして点列を保存
リファレンス マニュアルにおける関数GetHashedKey()の説明の項にある様な,二つのエントリを持つマップのシーケンスとして保存する.
関数cvStartWriteStruct()を利用して,"x"と"y"のエントリを持つマップの書き込みを行う.
さらにそれらのマップを,最後の引数に CV_NODE_SEQを与えた関数cvStartWriteStruct()でまとめることで,シーケンスとして書き込む.
今回は,リファレンス マニュアルの例に習い,YAML形式のファイルとして保存する.