vector를 mat을 생성하는 방법
아래의 단계를 따르면 된다.
mat의 생성자에 vector를 넘기자.
원하는 형태로 reshape하자.
example)
//! data = [0, 6) vector<int> data; for(int i=0; i<6; i++){ data.push_back(i); } //! Mat를 생성한다. Mat mat = Mat(data); /* * [0; * 1; * 2; * 3; * 4; * 5; */ //! 원하는 형태로 reshape 한다. Mat reshaped = mat.reshape(2, 3); /* * [(0, 1); * (2, 3); * (4, 5)] */
특이사항
크기가 N인 벡터를 넘기면, N X 1 행렬이 생성.
reshape를 통해 행렬의 크기와 채널을 변경해야 함.
mat과 reshaped는 아직 같은 행렬 메모리를 참조하고 있다.
즉, mat이 수정되면 reshaped도 변경된다.
공유 메모리 이슈
이미 존재하는 데이터를 통해 mat을 만들 때,
2가지 방식을 통해 mat을 생성할 수 있다.
이미 존재하는 데이터의 데이터 영역을 공유
해당 데이터를 복사하여 자신만의 데이터 영역을 소유
mat에 vector를 넘길때 블리언 플래그를 넘겨줌으로써
행렬 메모리의 생성방식을 제어할 수 있다.
example)
//! data = [0, 1) vector<int> data; for(int i=0; i<1; i++){ data.push_back(i); } //! Mat를 생성한다. Mat ref = Mat(data); //! 벡터와 메모리 공유 Mat cpy = Mat(data, true); //! 복사된 메모리 생성 //! data를 변경하면? data[0] = 9; cout << ref << '\n'; //! [9] cout << cpy << '\n'; //! [0]
참조 방식의 위험성
vector를 참조방식으로 쓸 때의 주의사항을 알아보자.
먼저 참조방식으로 mat을 생성해보자.
step 1)
//! data = [0, 1) vector<int> data; for(int i=0; i<1; i++){ data.push_back(i); } //! 참조 방식으로 Mat를 생성한다. Mat ref = Mat(data); //! ref를 출력한다. cout << ref << '\n'; //! [0]
여기까지는 문제가 없음이 자명하다.
문제는 이 다음부터다.
step 2)
//! 벡터에 데이터를 더 붙인다. //! data = [0, 256) for(int i=1; i<256; i++){ data.push_back(i); } //! ref를 출력한다. cout << ref << '\n'; //! [?]
벡터에 데이터를 더 붙이고 다시 ref를 출력하면,
이상한 숫자가 출력될 것 이다.
원인은 바로 벡터의 reallocation에 있다.
벡터 reallocation
벡터는 현재 capacity를 초과하는 데이터가 push되면,
1.5배 만큼 capacity를 데이터를 수용할 수 있도록 재할당하고, 이전의 데이터를 복사한다.
문제는 재할당이라는 것이다.
이전의 데이터 영역이 버려지는 것 이다.
example)
//! 하나만 붙이고 vec[0]의 주소 출력. vec.push_back(0); cout << &vec[0] << '\n'; //! 여러개 붙이고 다시 vec[0]의 주소 출력. for(int i=0; i<1000; i++){ vec.push_back(0); } cout << &vec[0] << '\n'; /** * output : (실행시마다 달라질 수 있음.) * 0x1a1790 * 0x692490 */
참조방식 + 재할당 패닉
즉, vector는 재할당이 이루어짐으로써 이전 영역을 해제했지만,
참조방식 mat은 이전 영역을 계속 사용함으로써 문제가 발생했다.
해결 방안은 다음과 같다.
true 플래그를 넘겨서 복사 방식으로 mat을 생성한다.
vector에 더 이상 데이터를 추가하지 않는다.
하지만 복사 방식으로 mat을 생성할 경우,
데이터를 복사하는데 오버헤드가 크다는 것을 염두해두자.
'# 미사용 > OpenCV' 카테고리의 다른 글
[OpenCV] 윈도우 및 이벤트 관리 (0) | 2019.10.29 |
---|---|
[OpenCV] 이미지 입출력 (0) | 2019.10.29 |
[OpenCV] 행렬의 영역참조 (관심영역) (0) | 2019.10.29 |
[OpenCV] 행렬의 생성 및 활용 (0) | 2019.10.29 |
[OpenCV] 기본 클래스 활용 (0) | 2019.10.28 |