OpenCV로 배우는 영상처리 및 응용:: 3장
OpenCV 로 배우는 영상 처리 및 응용 <3장 OpenCV 의 기본 자료 구조>
연습문제
1. 데이터를 저장하고 다루는 자료 구조의 차원에서 매트릭스와 벡터의 차이는 무엇인가?
-벡터 : 동일한 유형의 데이터로 구성되어 있는 1차원 데이터 구조
-매트릭스: 동일한 유형의 2차원 데이터 구조
2. 클래스(class)의 정의는 무엇이며, 구조체와 큰 차이는 무엇인가?
-클래스란 동일한 속성을 갖는 객체들의 집합으로 하나의 데이터 타입이며, 함수를 포함하지 않는 구조체와 달리 클래스는 함수도 포함할 수 있다.
3. Point_ 클래스와 Size_ 클래스의 세부 자료형에 대해서 기술하고, 객체 선언을 하시오.
Point_ : Point2i(Point), Point2I, Point2f, Point2d 자료형이 있다.
Size_ : Size2i(Size), Size2I, Size2f, Size2d 자료형이 있다.
객체 선언
#include
using namespace std;
using namespace cv;
int main()
{
Point_ ipt(100, 200);
//Point2i ipt(100,200);
Point_ fpt(92.3f, 125.23f);
//Point2f fpt(92.3f, 125.23f);
Point_ dpt(100.2, 300.9);
//Point2d dpt(100.2,300.9);
Size_ isize(100, 200);
//Size isize(100,200);
Size_ fsize(192.f, 25.3f);
//Size2f fsize(192.f,25.3f);
Size_ dsize(100.2, 30.9);
//Size2d dsize(100.2, 30.9);
return 0;
}
4. Rect_ 클래스의 멤버 변수와 내부 메서드를 기술하고, 각 세부 자료형으로 객체 선언 하시오.
멤버 변수 : x, y, width, height,
내부 메서드 : tl(), br(), size(), area(), empty(), contains()
객체 선언
Rect_ irect1(10, 10, 20, 40); //x, y, width, height
Rect_ irect2(Point(10, 10), Point(30, 50)); //좌상단, 우하단
Rect_ irect3(Point(10, 10), Size(20, 40)); //좌상단, 크기(w,h)
5. Mat 클래스의 내부 메서드들을 나열하고 기능들을 정리하시오.
channels() : 행렬의 채널 수를 반환
depth() : 행렬 요소의 depth 값 반환
elemSize() : 행렬 요소의 크기를 바이트 단위로 반환
elemSize1( ) : 각 행렬 요소의 한 채널의 크기를 바이트 단위로 반환
empty() : 배열에 아무런 요소가 없으면 참값 반환
isSubmatrix() : 행렬이 다른 행렬의 하위 행렬인 경우(참조행렬인지) true 반환
size() : 행렬 크기를 Size 자료형으로 반환
step1() : 정규화 된 step 반환, 임의의 행렬 원소에 신속하게 접근하는 것이 유용하다.
total() : 행렬 원소의 전체 개수를 반환
type() : 행렬의 데이터 타입(자료형+채널수) 반환
6. 네임 스페이스를 사용하는 이유를 설명하시오.
-소스별로 이름 공간을 따로 설정하여 이름 충돌을 막기 위해 사용한다.
7. Rect_ 객체를 생성하는 대표적인 세 가지 방법으로 float형과 int형 사각형을 선언하시오.
Rect_ irect1(10, 10, 20, 40); //x, y, width, height
Rect_ irect2(Point(10, 10), Point(30, 50)); //좌상단, 우하단
Rect_ irect3(Point(10, 10), Size(20, 40)); //좌상단, 크기(w,h)
Rect_ frect1(20.f, 30.f, 100.f, 200.f);
Rect_ frect2(Point2f(20.f, 30.f), Point2f(100.f, 200.f));
Rect_ frect3(Point2f(20.f, 30.f), Size2f(80.f, 170.f));
8. Rect_ 객체의 산술(덧셈, 뺄셈) 연산과 논리(&, |) 연산에 대해서 설명하시오.
-산술(덧셈, 뺄셈) 연산 : Point 자료형에 대한 산술연산은 사각형에 대한 평행이동이고 size 자료형에 대한 산술연산은 크기를 변경하는 연산이다
-논리(&, |) 연산 : 두 Rect 에 대한 교집합(&), 합집합(|) 영역을 구한다
9. Mat 클래스를 선언하고, 초기화하는 방법을 세 가지 이상으로 작성하시오.
Mat 객체 선언 방법
1) Scalar 값으로 초기화
2) 배열 원소로 초기화)
Size_ 객체로 Mat 객체 선언 방법
float data[] = {
1.2f, 2.3f, 3.2f,
4.5f, 5.f, 6.5f,
};
Mat m1(2, 3, CV_8U, Scalar(300)); //2x3 행렬, CV_8U(자료형 지정), uchar형 300으로 초기화, 255으로 저장
Mat m2(2, 3, CV_32F, data); //2x3 행렬, float 형으로 선언, 배열 원소로 초기화
Mat m3(Size(2, 3), CV_8U, Scalar(300)); //Size_ 객체로 초기화
10. Mat::reshape() 함수와 Mat::resize() 함수를 비교 설명하시오.
-Resize() 는 행렬의 행수를 지정하여 행의 개수를 변경하는 함수로 원소의 개수(채널 수*행수*열수)가 변경될 수 있음
-Reshape() 함수는 행렬의 전체 원소 개수를 변경하지 않은 채, 채널의 개수나 행의 개수를 바꾸고자 할 때 사용됨
11. Matx 클래스는 어떤 상황에서 사용하며, 어떻게 초기화하는지 예시하시오.
-Matx 는 Mat와 비교했을 때, 크기가 작은 행렬을 위한 템플릿 클래스이고,
Size가 정해져 있으면 Matx, Vec 를 주로 사용하고
정해져 있지 않으면 Mat를 사용한다.
12. 5개의 원소를 갖는 float 배열을 선언하고, 이 배열을 사용해서 벡터 클래스의 객체를 생성하여 초기화하시오.
#include
using namespace std;
using namespace cv;
int main(){
float fdata[] = { 10.2, 20.6, 30.0, 40.0, 50.0 };
vector fv(fdata, fdata + sizeof(fdata) / sizeof(float));
cout << "[fv] " << ((Mat)fv).reshape(1,1) << endl;
return 0;
}
13. 영상 처리 과정에서 처리된 데이터가 주어진 화소값의 범위를 벗어나 문제가 발생할 경우가 있다. 이 경우에 해결 방법은 무엇인가?
-포화 캐스팅을 사용해 해결할 수 있다. Cv::saturate_cast< _Tp> ()라는 템플릿 함수를 이용하여 _Tp 의 타입의 범위보다 값이 작거나 크면(언더플로우나 오버플로우 발생 시) 자동으로 최소값/최대값 으로 바꾸어준다
14. 시작 좌표가 30, 40 이고, 크기가 100X200 인 실수형 Rect 객체를 선언하고, 객체를 좌표(10,10) 만큼 평행이동하고, 20X30 만큼 크기를 증가시키는 프로그램 소스를 작성하시오.
#include
using namespace std;
using namespace cv;
int main()
{
Rect2f rect(Point2f(30.f, 40.f), Size2f(100, 200));
Rect2f res = rect + Point2f(10.0, 10.0);
res += Size2f(20.0, 30.0);
cout << "rect = " << "(" << rect.x << "," << rect.y << ") ";
cout << "width: " << rect.width << ", height: " << rect.height << endl;
cout << "result = " << "(" << res.x << "," << res.y << ") ";
cout << "width: " << res.width << ", height: " << res.height << endl;
return 0;
}
15. double 형 Point_ 객체를 5개 생성하고, 벡터에 추가하는 소스를 작성하시오.
#include
using namespace std;
using namespace cv;
int main()
{
Point2d dpt1(1.2, 2.3);
Point2d dpt2(2.2, 3.3);
Point2d dpt3(3.5, 5.5);
Point2d dpt4(10.2, 30.0);
Point2d dpt5(55.5, 10.0);
vector v;
v.push_back(dpt1);
v.push_back(dpt2);
v.push_back(dpt3);
v.push_back(dpt4);
v.push_back(dpt5);
cout << "[v] " << ((Mat)v).reshape(1, 1) << endl;
}
16. float형 Mat 객체를 4행, 5열로 선언하고, 배열 원소로 초기화하는 소스를 작성하시오.
#include
using namespace std;
using namespace cv;
int main()
{
float data[] = {
1.1, 2.2, 3.3, 4.0, 5.5,
6.0, 7.0, 8.0, 9.`0, 0.0,
6.0, 7.0, 8.0, 9.0, 0.0,
1.1, 2.2, 3.3, 4.0, 5.5,
};
Mat m(4, 5, CV_32F, data);
cout << m << endl;
}
17. 실행 결과를 적으시오.
33
18. 실행 결과를 적으시오.
10
20
75
30
40
150
50
55
100
19. 다음과 같이 출력하는 프로그램을 작성하시오.
#include
using namespace std;
using namespace cv;
int main()
{
Mat m(Size(15, 10), CV_32S, Scalar(100));
Range r200(1, 5), end200(3, 8);
Range r300(5, 9), end300(8, 14);
Range r555(3, 7), end555(5, 10);
//Mat roi(4, 5, CV_32S, Scalar(200));
Mat roi = m(r200, end200);
roi.setTo(200);
roi = m(r300, end300);
roi.setTo(300);
roi = m(r555, end555);
roi.setTo(555);
cout << "[m]" << endl << m << endl;
}