C/C++ 開発、FileStorage に基づく opencv ファイルの読み取りおよび書き込みの概要と例

目次

1. FileStorage クラス

        1.1 FileStorage クラスの説明

        1.2 FileStorageクラスの記述説明

        1.3 FileStorageクラスの読み込み手順

2. FileStorage アプリケーションの例

        2.1 アプリケーションコード

        2.2 プロジェクト構成(Makefile)

        2.3 コンパイルとテスト


1. FileStorage クラス

        1.1 FileStorage クラスの説明

        FileStorage クラスは opencv2\core\persistence.hpp で定義されています。

namespace cv {
//...
    class CV_EXPORTS_W FileStorage
    {
        //...
    };
}

        FileStorage クラスは、XML (.xml、<http://www.w3c.org/XML>)、YAML (.yml または .yaml、<http://www.yaml.org>)、JSON (.json、 < http://www.json.org/>) 形式ファイルの読み取りと書き込み。XML は階層を表すためにネストされたタグを使用しますが、YAML は (Python プログラミング言語と同様に) インデントを使用します。

XML:
@code{.xml}
    <?xml version="1.0">
    <opencv_storage>
    <A type_id="opencv-matrix">
      <rows>3</rows>
      <cols>3</cols>
      <dt>f</dt>
      <data>1. 0. 0. 0. 1. 0. 0. 0. 1.</data>
    </A>
    </opencv_storage>
@endcode
YAML:
@code{.yaml}
    %YAML:1.0
    A: !!opencv-matrix
      rows: 3
      cols: 3
      dt: f
      data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.]
@endcode

        FileStorage クラスは、デフォルトの構築またはファイル名を指定する構築方法をサポートしています。

CV_WRAP FileStorage();
CV_WRAP FileStorage(const String& filename, int flags, const String& encoding=String());

        デフォルトの構造が採用されている場合は、指定したファイルを後で open 関数を使用して開く必要があります。

CV_WRAP virtual bool open(const String& filename, int flags, const String& encoding=String());

        書き込みたいファイルが正常に開かれたら、演算子 cv::FileStorage::operator<<() を使用して標準出力ストリームに書き込むか、 cv::FileStorage::operator>> () を使用して読み取り操作。このように単純な方法で記述できるのは、呼び出し元の開発者のために関数内で多くの複雑な作業が行われるためです。

        cv::FileStorage は、読み取りと書き込み、コンテンツの追加などのファイル操作をサポートします。これは、組み込みの列挙値 Mode によって指定され、フラグで指定する必要があります。フラグは、次のような複数の列挙値の結合です。読み取り|書き込み。同時に、組み込みの操作状態 State もあり、 cv::FileStorage クラスにデータ操作 (演算子 <<) を書き込むときに cv::FileStorage オブジェクトの状態を判断する必要があります。

    //! file storage mode
    enum Mode
    {
        READ        = 0, //!< value, open the file for reading
        WRITE       = 1, //!< value, open the file for writing
        APPEND      = 2, //!< value, open the file for appending
        MEMORY      = 4, /**< flag, read data from source or write data to the internal buffer (which is
                              returned by FileStorage::release) */
        FORMAT_MASK = (7<<3), //!< mask for format flags
        FORMAT_AUTO = 0,      //!< flag, auto format
        FORMAT_XML  = (1<<3), //!< flag, XML format
        FORMAT_YAML = (2<<3), //!< flag, YAML format
        FORMAT_JSON = (3<<3), //!< flag, JSON format

        BASE64      = 64,     //!< flag, write rawdata in Base64 by default. (consider using WRITE_BASE64)
        WRITE_BASE64 = BASE64 | WRITE, //!< flag, enable both WRITE and BASE64
    };
    enum State
    {
        UNDEFINED      = 0,
        VALUE_EXPECTED = 1,
        NAME_EXPECTED  = 2,
        INSIDE_MAP     = 4
    };

        1.2 FileStorageクラスの記述説明

        cv::FileStorage の内部データ ストレージには、「マッピング」 (キーと値のペア) と「シーケンス」 (一連の名前のないエントリ) という 2 つの主な形式があります。最上位レベルでは、書き込まれたデータはすべてマッピング内にあり、そこに他のマッピングやシーケンスを配置したり、必要に応じてマッピングをマッピング内に配置し続けることもできます。

myFileStorage <<"someInteger"<< 27;// save an array
myFileStorage <<"anArray"<<cv::Mat::eye(3,3,CV_32F);// save an integer

        シーケンス項目を作成する場合は、まず文字列型の名前を指定し、次にシーケンス データを指定する必要があります。エントリの内容は、数値 (整数、浮動小数点など)、文字列、または別の OpenCV データ型にすることができます。

        新しいマッピングまたはシーケンスを作成する場合は、特殊記号 { (マッピングの場合) または [ (シーケンスの場合) を使用できます。作成したら、それに要素を追加し、最後にマッピングまたはシーケンスをそれぞれ } または ] で終了することができます。

myFileStorage <<"theCat"<<"{";
myFileStorage <<"fur"<<"gray"<<"eyes"<<"green"<<"weightLbs"<< 16;
myFileStorage <<"}";

        マッピングを作成したら、トップレベルのマッピングの場合と同様に、項目名と対応する値を順番に入力する必要があります。シーケンスを作成している場合は、シーケンスが終了するまで要素を 1 つずつ入力するだけです。

myFileStorage<<"theTeam"<<"[";
myFileStorage <<"eddie"<<"tom"<<"scott";
myFileStorage <<"]";

        書き込みが完了したら、メンバー関数 cv::FileStorage::release() を使用してファイルを閉じることができます。

        1.3 FileStorageクラスの読み込み手順

        FileStorage クラスが読み取り操作に演算子 cv::FileStorage::operator>>() を使用すると、実際には FileNode クラスのインスタンス オブジェクトが返されます。

        FileNode クラスは、opencv2\core\persistence.hpp にも定義されています。

namespace cv {
//...
    class CV_EXPORTS_W_SIMPLE FileNode
    {
        //...
    };
}

        cv::FileNode オブジェクトの構築に成功したら、それを使用して多くのタスクを完了できます。実際のオブジェクト (または数値や文字列) を直接表す場合は、オーバーロードされた演算子 cv::FileNode::operator>>() を直接使用して、その値を対応する type の変数にロードできます。

cv::Mat anArray;
myFileStorage["calibrationMatrix"]>> anArray;

       cv::FileNode オブジェクトは、いくつかの基本データ型への直接割り当てもサポートしています。cv::FileNode クラスでサポートされるデータ型は次のとおりです。

    //! type of the file storage node
    enum
    {
        NONE      = 0, //!< empty node
        INT       = 1, //!< an integer
        REAL      = 2, //!< floating-point number
        FLOAT     = REAL, //!< synonym or REAL
        STR       = 3, //!< text string in UTF-8 encoding
        STRING    = STR, //!< synonym for STR
        SEQ       = 4, //!< sequence
        MAP       = 5, //!< mapping
        TYPE_MASK = 7,

        FLOW      = 8,  //!< compact representation of a sequence or mapping. Used only by YAML writer
        UNIFORM   = 8,  //!< if set, means that all the collection elements are numbers of the same type (real's or int's).
        //!< UNIFORM is used only when reading FileStorage; FLOW is used only when writing. So they share the same bit
        EMPTY     = 16, //!< empty structure (sequence or mapping)
        NAMED     = 32  //!< the node has a name (i.e. it is element of a mapping).
    };

        cv::FileNode オブジェクト出力演算子を介してデータを取得することは、代入演算子を使用してデータを取得することと同じです。

int aNumber;
myFileStorage["someInteger"]>> aNumber;

        以下と同等です。

int aNumber;
aNumber =(int)myFileStorage["someInteger"];

        cv::FileNode クラスの場合、標準 STL 表記法も提供されます。つまり、FileNodeIterator、node.begin()、node.end() は、ノードに格納されるか、演算子 ++ () を介してシーケンスの開始と終了を表します。または、移動する演算子++(int)。

namespace cv {
//...
    class CV_EXPORTS FileNodeIterator
    {
        //...
    };
}

2. FileStorage アプリケーションの例

        2.1 アプリケーションコード

        opencv2\core\persistence.hpp には、FileStorage クラスによる .yml ファイルの書き込みと読み取りのためのサンプル コードも提供されています。この記事では、サンプル コードに基づいて完全なケース プロジェクトを作成し、最初に .yml 形式のファイルを作成します。コンテンツを書き込み、新しい FileStorage インスタンス オブジェクトを通じてファイル メモリを読み取り、解析して出力して関連するコンテンツを表示します。

        まず、ディレクトリ ファイル file_storage を作成し、そのファイル ディレクトリ内にファイル main.cpp と Makefile を作成します。main.cpp は次のとおりです。次に、tets.yml ファイルを作成し、fileCreateAndSave 関数を通じてデータを書き込み、次に、 fileReadAndShow 関数の内容を実行し、表示を出力します。main.cpp のソース コードは次のとおりです。

#include <opencv2/opencv.hpp>
#include <time.h>
#include <iostream>

void fileCreateAndSave()
{
    cv::FileStorage fs("test.yml",cv::FileStorage::WRITE);
    fs <<"frameCount"<< 5;
    time_t rawtime; time(&rawtime);fs<<"calibrationDate"<< asctime(localtime(&rawtime));
    cv::Mat cameraMatrix =(
        cv::Mat_<double>(3,3)
        <<1000,0,320,0,1000,240,0,0,1
    );
    cv::Mat distCoeffs =(
        cv::Mat_<double>(5,1)
        <<0.1,0.01,-0.001,0,0
    );
    fs <<"cameraMatrix"<< cameraMatrix<<"distCoeffs"<< distCoeffs;
    fs <<"features"<<"[";
    for( int i=0; i<3;i++)
    {
        int x = rand()% 640;
        int y = rand()% 480;
        uchar lbp = rand()% 256;
        fs<<"{:"<<"x"<<x<<"y"<<y<<"lbp"<<"[:";
        for( int j=0;j<8;j++)
            fs <<((lbp >>j)&1);
        fs<<"]"<<"}";
    }
    fs<<"]";
    fs.release();

}

void fileReadAndShow()
{
    cv::FileStorage fs2("test.yml",cv::FileStorage::READ);
    // first method: use (type) operator on FileNode.
    int frameCount =(int)fs2["frameCount"];
    // second method: use cv::FileNode::operator >>
    //
    std::string date;
    fs2["calibrationDate"]  >> date;
    cv::Mat cameraMatrix2, distCoeffs2;
    fs2["cameraMatrix"]     >> cameraMatrix2;
    fs2["distCoeffs"]       >> distCoeffs2;
    std::cout <<"frameCount:"       << frameCount   <<std::endl
            <<"calibration date:"   << date         <<std::endl
            <<"camera matrix:"      << cameraMatrix2<<std::endl
            <<"distortion coeffs:"  << distCoeffs2  <<std::endl;
    cv::FileNode features  = fs2["features"];
    cv::FileNodeIterator it = features.begin(), it_end = features.end();
    int idx=0;
    std::vector<uchar> lbpval;
    // iterate through a sequence using FileNodeIterator
    for(; it != it_end;++it,idx++)
    {
        std::cout <<"feature #"<<idx<<":";
        std::cout <<"x="<<(int)(*it)["x"]<<",y="<<(int)(*it)["y"]<<",lbp:(";
        //(Note: easily read numerical arrays using FileNode >> std::vector.)
        //
        (*it)["lbp"]>>lbpval;
        for( int i=0; i<(int)lbpval.size(); i++)
            std::cout <<""<<(int)lbpval[i];
        std::cout <<")"<<std::endl;
    }
    fs2.release();
}

int main( int argc,char* argv[])
{
    fileCreateAndSave();
    fileReadAndShow();
    return 0;
};

        2.2 プロジェクト構成(Makefile)

        エンジニアリング組織の Makefile は次のとおりです (この記事は win 上で MinGW メソッドを使用してコンパイルされています。opencv ライブラリのビルド + MinGW コンパイルの方法は、このコラムの C/C++ 開発のブログ記事 opencv ライブラリのインストールとコンパイルを参照してください) 、 win_Build mingw コンパイル環境_py_free-IOT Intelligent Blog-CSDN Blog )で OpenCV+MinGW コンパイル環境構築

#/bin/sh
CX= g++ 

BIN 		:= ./
TARGET      :=  fileStorage.exe
FLAGS		:= -std=c++11 -static
SRCDIR 		:= ./
#INCLUDES
INCLUDEDIR 	:= -I"../../opencv_MinGW/include" 
staticDir   := ../../opencv_MinGW/x64/mingw/staticlib/

LIBDIR 	    := -L $(staticDir) -lopencv_world460 -lade -lIlmImf -lquirc -lzlib \
				-llibjpeg-turbo -llibopenjp2 -llibpng -llibprotobuf -llibtiff -llibwebp \
				-lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid 
source		:= $(wildcard $(SRCDIR)/*.cpp) 

$(TARGET) :
	$(CX) $(FLAGS) $(INCLUDEDIR) $(source)  -o $(BIN)/$(TARGET) $(LIBDIR)

clean:
	rm  $(BIN)/$(TARGET)

        2.3 コンパイルとテスト

        file_storage ディレクトリに入り、次のように -j* でケースをコンパイルします。

         実行中のプログラムは次のとおりです。

         出力された test.yml ファイルは次のとおりです。

%YAML:1.0
---
frameCount: 5
calibrationDate: "Sun Jul  2 16:49:48 2023\n"
cameraMatrix: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]
distCoeffs: !!opencv-matrix
   rows: 5
   cols: 1
   dt: d
   data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,
       -1.0000000000000000e-03, 0., 0. ]
features:
   - { x:41, y:227, lbp:[ 0, 1, 1, 1, 1, 1, 0, 1 ] }
   - { x:260, y:449, lbp:[ 0, 0, 1, 1, 0, 1, 1, 0 ] }
   - { x:598, y:78, lbp:[ 0, 1, 0, 0, 1, 0, 1, 0 ] }

おすすめ

転載: blog.csdn.net/py8105/article/details/131502622