OpenCV에서 Mat 클래스에 저장된 영상 데이터는 imwrite() 함수를 이용하여 PNG, JPG, BMP 등 영상 파일로 저장할 수 있다.
하지만, uchar 자료형을 사용하는 영상이 아닌 int, double, float 등의 자료형을 일반적인 행렬은 영상 파일 형식으로 저장할 수 없다.
OpenCV에서 제공하는 FileStorage 클래스는 Mat 클래스 객체뿐만이 아니라 일반적인 C/C++ 자료형 데이터를
XML, YAML, JSON 등 파일 형식으로 저장하는 기능을 제공한다.
FileStorage 클래스
OpenCV에서 데이터 파일 입출력을 하는 클래스이다. 데이터 파일의 입출력 기능을 캡슐화하여 지원한다.
class FileStorage
{
public:
FileStorage();
FileSotrage(const String& filename, int flags, const String& encoding=String();
virtual bool open(const String& filename, int flags, const String& encoding=String());
virtual bool isOpened() const;
virtual void release();
FileNode operator[](const char* nodename) const;
...
};
template<typename _Tp> static
FileStorage& operator << (FileStorage& fs, const _Tp& value);
static FileStorage& operator << (FileStorage& fs, const String& str);
static FileStorage& operator << (FileStorage& fs, const char* str);
template<typename _Tp> static
vodi operator >> (const FileNode& n, _Tp& value)
template<typename _Tp> static
void operator >> (const FileNode& n, std::vector<_Tp>& vec)
FileStorage 클래스를 이용하여 OpenCV 데이터를 저장하거나 읽어 오려면 먼저 FileStorage 객체를 생성해야 한다.
FileStorage 객체는 단순히 FileStorage 클래스 타입의 변수를 하나 선언하는 방식으로 생성할 수 있다.
FileStorage fs;
FileStorage 클래스의 멤버 함수
FileStorage::open();
virtual bool FileStorage::open(const String& filename, int flags, const String& encoding = String());
filename : 파일 이름
flags : 파일 열기 모드
encoding : (XML) 파일 인코딩 방식
반환값 : 정상적으로 파일을 열면 true, 실패하면 false 반환
FileStorage 객체를 생성한 후, FileStorage::open() 함수를 이용해 파일을 열어야 한다.
filename 인자에는 데이터 파일 이름을 지정한다. FileStorage 클래스는 XML, YAML, JSON 형식의 파일 입출력을 지원하며,
사용할 파일 형식은 filename의 확장자에 의해 자동으로 결정된다.
*.xml // XML 파일 형식
*.yaml // YAML 파일 형식
*.json // JSON 파일 형식
데이터 파일 이름 뒤에 gz를 추가하면 데이터 파일을 압축하여 저장한다.
"test.xml.gz"
위 코드와 같이 "test.mxl.gz" 지정 시, XML 파일 형식으로 데이터를 저장한 후 gzip 형식으로 압축한다.
FileStorage::open() 함수의 2번째 인자는 flags 파일 열기 모드를 나타내며,
FileStorage::mode 열거형 상수를 지정할 수 있다.
FileStorage::mode 열거형 상수
|
설명
|
FileStorage::READ
|
읽기 모드
|
FileStorage::WRITE
|
쓰기 모드(새로 생성)
|
FileStorage::APPEND
|
추가로 쓰기 모드
|
FileStorage::MEMORY
|
논리합 연산자( | )를 이용하여 FileStorage::READ 또는 FileStorage::WRIITE 상수와 함께
사용될 경우, 실제 파일 입출력 대신 메모리 버퍼를 이용한 입출력을 수행한다.
|
3번째 인자 encoding 에는 XML 파일의 인코딩 형식을 지정하는 문자열을 지정할 수 있으며, 기본 값이 설정되어 있으므로 생략할 수 있다.
FileStorage fs;
fs.open("test.xml", FileStorage::WRITE);
위 코드는 FileStorage 클래스 타입의 변수 선언 후, FileStorage::open() 함수를 이용하여 test.xml 파일을 쓰기 모드로 여는 코드이다.
FileStorage 클래스는 FileStorage::open() 멤버 함수와 같은 형식의 인자를 갖는 생성자도 지원하므로,
2줄을 1줄로 요역하여 선언 및 데이터 파일을 특정 모드로 설정할 수 있다.
FileStorage fs("test.xml", FileStorage::WRITE);
FileStorage 객체에서 데이터 파일을 열기 시도한 후, 해당 파일이 정상적으로 열려있는지 FileStorage::open() 함수를 이용해서
확인하는 것이 좋다.
FileStorage::isOpend();
virtual bool FileStorage::isOpened() const;
반환값 : 파일이 정상적으로 열려 있으면 true, 그렇지 않으면 false
FileStorage 생성자를 이용하여 객체 생성과 파일 열기를 같이 수행하는 경우 정상적으로 파일이 열렸는지 확인하는 함수이다.
파일이 정상적으로 열렸다면 데이터를 쓰거나 읽는 작업을 수행할 수 있다.
FileStorage::release();
virtual void FileStorage::release();
FileStorage 객체를 이용하여 파일 입출력 작업이 완료되면, FileStorage::release() 함수를 호출해야 한다.
FileStorage::release() 함수는 사용하고 있던 파일을 닫고 메모리 버퍼를 해제한다.
데이터 파일 정장 방법
FileStorage 클래스를 이용하여 XML, YAML, JSON 등 파일을 쓰기 모드로 열었다면 C/C++ 자료형, STL 클래스,
OpenCV 클래스 형식의 데이터 파일에 저장할 수 있다.
FileStorage 클래스를 이용하여 데이터를 파일에 저장할 때 보통 << 연산자 재정의 함수를 사용한다.
template<typename _Tp>
static FileStorage& operator << (FileStorage& fs, const _Tp& value);
static FileStorage& operator << (FileStorage& fs, const String& str);
static FileStorage& operator << (FileStorage& fs, const char* str);
fs : FileStorage 객체
value : 저장할 데이터(C/C++ 기본 자료형, 벡터, 클래스 등)
str : 문자열(이름 또는 값)
반환값 : FileStorage 객체의 참조
FileStorage 객체를 사용하는 << 연산자 재정의는 함수 템플릿으로 구성되어 있어서 다양한 자료형의 데이터와 함께 사용될 수 있다.
char, int, float, double, string, vector 같은 STL 클래스 객체, OpenCV의 Mat, Scalar, Point 등 클래스 객체를 저장할 수 있다.
int year = 2019;
fs << "year" << year;
C/C++의 int형 데이터 2019를 "year" 라는 이름으로 저장하는 코드이다.
데이터 파일 불러오기
FileStorage 클래스를 이용하여 데이터 파일을 불러오려면 먼저 FileStorage 객체를 생성하고, 그 다음 실제 사용할
데이터 파일을 읽기 모드로 열어야 한다.
FileStorage fs("test.xml", FileStorage::READ);
FileStorage 객체가 파일을 읽기 모드로 열면 FileStorage 객체는 파일 전체를 분석하여 계층적 구조를 갖는 노드(node) 집합을 구성한다.
노드(node)란 이름과 값으로 구성되어 있는 하나의 데이터를 의미한다.
1개의 노드는 1개의 정수 혹은 문자열을 저장하는 경우도 있고, 여러 데이터의 집합으로 구성되기도 한다.
OpenCV 에서는 노드를 FileNode 클래스를 이용하여 표현한다.
FileNode FileStorage::operator[](const char* nodename) const;
nodename : 노드 이름
반환값 : FileNode 객체
FileNode 객체에 접근하려면 FileStorage::operator[]() 연산자 재정의 함수를 사용한다.
일단 노드 이름을 이용하면 FileNode 객체를 얻어 온 후, FileNode 클래스의 >> 연산자 재정의 함수를 이용하여
노드에 저장된 데이터 값을 받아올 수 있다.
>> 연산자 재정의 함수
template<typename _Tp>
static void operator >> (const FileNode& n, _Tp& value);
template<typename _Tp>
static void operator >> (const FileNode& n, std::vector<_Tp>& vec);
n : FileNode 객체
value : 받아올 데이터 형식(C/C++ 기본 자료형, 벡터, 클래스 등)에 맞는 변수 이름
vec : STL vector 형식으로 저장된 데이터를 불러올 때 사용한다.
재정의된 >> 연산자 함수를 사용하여 데이터를 읽어 오려면 >> 연산자 왼쪽에 FileNode 객체 이름을 쓰고
>> 연산자 오른쪽에는 받아 올 데이터 형식에 맞는 변수 이름을 적는다.
int year;
fs["year"] >> year;
FileStorage 객체 fs로부터 "year" 라는 노드 이름의 데이터를 읽어 와서 year 변수에 저장한다.
FileStorage 클래스를 이용하여 파일을 읽을 때에는 FileNode 클래스의 객체를 명시적으로 사용하지 않아도 되고,
데이터 노드 이름과 자료형을 제대로 안다면 모든 데이터를 쉽게 읽을 수 있다.
'DevelopmentTool > OpenCV' 카테고리의 다른 글
[OpenCV] 히스토그램 (0) | 2022.11.18 |
---|---|
[OpenCV] 영상 밝기 및 명암 조절 (0) | 2022.11.18 |
[OpenCV] 이벤트 처리 인터페이스 (0) | 2022.11.18 |
[OpenCV] 문자열 출력 (0) | 2022.11.18 |
[OpenCV] 도형 그리기 (0) | 2022.11.17 |