|
|
1. 콜백 함수란 무엇인가.
특정 창에서 발생하는 마우스 이벤트들에 대하여 처리 및 제어를 구현한다.
함수포인터로 정의되어 있어 인수의 구조를 같게 설정해줘야한다.
2. 윈도우 창을 지정하는 cv::namedWindow() 함수에서 두 번쨰 인수(flag)의 옵션으로 WINDOW_NORMAL와 WINDOW_AUTOSIZE의 차이를 설명하시오.
WINDOW_NORMAL : 사용자가 임의적으로 윈도우창에서 크기를 조정 가능하며 안에 들어간 Mat 객체가 윈도우 크기에 맞춰 재조정된다.
WINDOW_AUTOSIZE : 임의적으로 윈도우 창에서 크기를 조절하지 못하며 resizeWindow와 같은 함수로만 크기에 대한 조정이 가능하다. 안에 들어간 Mat객체가 임의적으로 재조정되지 않는다.
3. 300행, 400열의 행렬을 회색바탕색(100)으로 생성해서 500행, 600열의 윈도우에 표시하시오.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(void) { Mat img(300, 400, CV_8U, Scalar(100)); namedWindow("window", WINDOW_AUTOSIZE); imshow("window", img); resizeWindow("window", Size(600, 500)); imshow("window 2번", img); waitKey(0); return 0; } | cs |
4. 400행, 500열의 윈도우를 만들고, 모니터의 가로 200, 세로 300 위치에 띄우시오
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(void) { namedWindow("윈도우창", WINDOW_NORMAL); resizeWindow("윈도우창", Size(400, 400)); moveWindow("윈도우창", 200, 300); waitKey(); return 0; } | cs |
| moveWindow("윈도우창", 200, 300) | moveWindow("윈도우창", 800, 300) |
5. 타원을 그리는 함수의 인수에 대해서 자세히 설명하시오.
void ellipse(Mat& img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar& color, int thinkness = 1, int lineType = 8, int shift = 0)
Mat& img = 타원을 그릴 행렬
Point center = 타원의 중심 좌표
Size axes = 타원의 x축 반지름과 y축 반지름
double angle = 타원의 각도, 좌표평면의 x축을 기준으로 해서 시계방향으로 회전
double startAngle = 호의 시작 각도로 호의 x축을 기준으로 시계방향을 정방향으로 계산한 각도
double endAngle = 호의 끝 각도로 호의 x축을 기준으로 시게방향으로 회전한 각도
const Scalar& color = 타원의 색
int thinkness = 타원의 선의 굵기
int lineType = 라인 타입
int shift = 비트연산을 통해 좌표와 크기등의 이동
6. OpenCV에서 마우스 이벤트와 트렉바 이벤트를 제어할 콜백함수를 시스템에 등록하는 함수는 각각 무엇이며, 매개변수의 구성은 어떻게 되는지 자세히 설명하시오.
typedef void (*MouseCallback) (int event, int x, int y, int flags, void*userdata)
int event = 마우스 이벤트
int x, int y = 마우스 이벤트가 발생한 시점의 Point(x,y)좌표
int flags = 마우스 이벤트 발생시 마우스 또는 키보드의 상태 정보 전달
void *userdata = 사용자 데이터의 주소 전달
typedef void (*TrackbarCallback) (int pos, void* userdata)
int pos = 트랙바 이벤트 발생한 시점에서의 트랙바 위치
void *userdata = 사용자 데이터의 주소 전달
7. 다음 예시 코드의 실행 결과를 표시하시오.
1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; int main(void) { Mat image(300, 400, CV_8U); image.setTo(100); namedWindow(" 윈도우", WINDOW_NORMAL); moveWindow(" 윈도우", 100, 200); namedWindow("윈도우창 기본", WINDOW_AUTOSIZE); imshow(" 윈도우", image); imshow("윈도우창 기본", image); waitKey(); return 0; } | cs |
| 1. 윈도우 창이 최초 실행시 100,200위치에 300,400의 크기로 열림 2. 임의적으로 윈도우 창의 크기를 줄여서 프로그램 종료를하고 다시 실행하면 이전에 실행되어있던 윈도우의 크기로 실행. |
2.
| 예상 | 결과 |
마지막 shift매개변수에 1이 들어가 비트연산자가 존재. 실행 좌표와 크기가 달라진것을 확인할 수 있다.
8. 다음 예시 코드는 컴파일 혹은 런타임 에러가 발생한다. 에러가 발생하는 부분을 수정하고 실행 결과를 적으시오.
1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main(void) { Mat image(300, 400, CV_8UC3, Scalar(255, 255, 255)); Point pt1(50, 130), pt2(200, 300); Rect rect(Point(50, 150), Point(150, 300)); line(image, pt1, Point(100, 200), Scalar(0,0,0)); //Scalar값 존재 X 디폴트 매개변수가 없어 지정해야함 line(image, pt2, Point(100, 200), Scalar(100, 100, 100)); //두번쨰 Point값 X 지정해줘야함 rectangle(image, pt1, pt2, Scalar(25, 0, 255)); rectangle(image, rect, Scalar(0, 0, 255)); //rect가 지정되어있지 않음 imshow("직선 & 사각형", image); waitKey(0); return 0; } | cs |
9. 600행, 400열의 윈도우를 만들고 영상내의 100,100 좌표에 200*300 크기의 빨간색 사각형을 그리시오.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main(void) { Rect rec(100, 100, 200, 300); Mat img(600, 400, CV_8UC3, Scalar(0)); rectangle(img, rec, Scalar(0, 0, 255), 2); namedWindow("window", WINDOW_NORMAL); resizeWindow("window", 400, 600); imshow("window", img); waitKey(); return 0; } | cs |
10. 가로 600, 세로 400 크기 영상에 200*200 크기의 태극 문양을 그리시오.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(void) { Mat img(600, 400, CV_8UC3, Scalar(255,255,255)); ellipse(img, Point(200, 300), Size(100, 100), 0, 0, 180, Scalar(255), -1); ellipse(img, Point(200, 300), Size(100, 100), 0, 180, 360, Scalar(0,0,255), -1); ellipse(img, Point(150, 300), Size(50, 40), 0, 180, 360, Scalar(255), -1); ellipse(img, Point(250, 300), Size(50, 40), 0, 0, 180, Scalar(0,0,255), -1); imshow("ellipse", img); waitKey(); return 0; } | cs |
11~13. 다음의 이벤트 제어 프로그램을 작성하시오.
| 1. 마우스 오른쪽 버튼 클릭 시 원을 그린다. 2. 마우스 왼쪽 버튼 클릭시 사각형을 그린다. 3. [Ctrl] + 마우스 이벤트 시 빨간색으로 그린다. 4. [Shift] + 마우스 이벤트 시 파란색으로 그린다. 5. 트랙바를 추가해서 선의 굵기를 1~10픽셀로 조절한다. 6. 트랙바를 추가해서 원의 반지름을 1~50픽셀로 조절한다. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; void on_mouse(int event, int x, int y, int flags, void* userdata); void on_trackbar_thinkness(int pos, void* userdata); void on_trackbar_circle(int pos, void* userdata); static int c_pos = 20; static int t_pos = 1; int main(void) { namedWindow("window"); Mat img(500, 500, CV_8UC3, Scalar(255, 255, 255)); setMouseCallback("window", on_mouse, &img); createTrackbar("circle", "window", 0, 50, on_trackbar_circle); createTrackbar("thinkness", "window", 0, 10, on_trackbar_thinkness); imshow("window", img); waitKey(); return 0; } void on_mouse(int event, int x, int y, int flags, void* userdata) { Mat img = *(Mat*)userdata; switch (event) { case EVENT_RBUTTONDOWN: if (flags & EVENT_FLAG_CTRLKEY) { circle(img, Point(x, y), c_pos, Scalar(0, 0, 255), t_pos); } else if (flags & EVENT_FLAG_SHIFTKEY) { circle(img, Point(x, y), c_pos, Scalar(255), t_pos); } else { circle(img, Point(x, y), c_pos, Scalar(0), t_pos); } break; case EVENT_LBUTTONDOWN: if (flags & EVENT_FLAG_SHIFTKEY) { rectangle(img, Rect(x, y, 30, 30), Scalar(255), t_pos); } else if (flags & EVENT_FLAG_CTRLKEY) { rectangle(img, Rect(x, y, 30, 30), Scalar(0, 0, 255), t_pos); } else { rectangle(img, Rect(x, y, 30, 30), Scalar(0), t_pos); } break; } imshow("window", img); } void on_trackbar_thinkness(int pos, void* userdata) { t_pos = pos; } void on_trackbar_circle(int pos, void* userdata) { c_pos = pos; } | cs |
14. 예제_4.2.3이 event_trackbar.cpp에서 화살표 키로 트랙바를 이동하는 소스를 추가하시오.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <opencv2/opencv.hpp> #include <conio.h> using namespace std; using namespace cv; string title = "트랙바 이벤트"; Mat image; void xxxxonChange(int value, void* userdata) { int add_value = value - 130; cout << "추가 화소값 " << add_value << endl; Mat tmp = image + add_value; imshow(title, tmp); } int main() { int value = 128; image = Mat(300, 400, CV_8UC1, Scalar(120)); namedWindow(title, WINDOW_AUTOSIZE); createTrackbar("밝기값", title, &value, 255, xxxxonChange); imshow(title, image); while (true) { char c = waitKey(); if (c == 224) { char key = getchar(); if (key == 77) ++value; //Right else if (key == 75) --value; //Left } else break; } return 0; } | cs |
15. 컬러 영상 파일을 Mat 객체로 로드해서 윈도우 창에 명암도 영상으로 표시하고 "test.jpg"와 "test.png"파일로 각각 저장하시오. 이때 영상 파일을 가장 좋은 화질로 압축하시오.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(void) { Mat img = imread("moon.jpg", IMREAD_GRAYSCALE); imshow("window", img); vector<int> img_jpg, img_png; img_jpg.push_back(IMWRITE_JPEG_QUALITY); img_jpg.push_back(100); img_png.push_back(IMWRITE_PNG_COMPRESSION); img_png.push_back(9); imwrite("img_jpg.jpg", img, img_jpg); imwrite("img_png.png", img, img_png); return 0; } | cs |
16. 심화예제_4..3.5를 마우스 중간버튼을 클릭하여 타원을 그리도록 수정하시오.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include <opencv2/opencv.hpp> #include <cmath> using namespace cv; using namespace std; string const title = "이벤트 그리기"; Mat image; void onMouse(int event, int x, int y, int flags, void* param) { static Point pt(-1, -1); if (event == EVENT_LBUTTONDOWN) { if (pt.x < 0) pt = Point(x, y); else { rectangle(image, pt, Point(x, y), Scalar(50), 2); imshow(title, image); pt = Point(-1, -1); } } else if (event == EVENT_RBUTTONDOWN) { if (pt.x < 0) pt = Point(x, y); else { Point2d pt2 = pt - Point(x, y); int radius = (int)sqrt(pt2.x * pt2.x + pt2.y * pt2.y); circle(image, pt, radius, Scalar(150), 2); imshow(title, image); pt = Point(-1, -1); } } else if (event == EVENT_MBUTTONDOWN) { if (pt.x < 0) pt = Point(x, y); else { Point2d pt2 = pt - Point(x, y); int x_radius = (int)sqrt(pt2.x * pt2.x + pt2.y * pt2.y); int y_radius = x_radius / 3 * 2; double angle; double slope = (pt2.y - y) / (pt2.x - x); slope = atan(slope); angle = slope * 180 / 3.141592; ellipse(image, pt, Size(x_radius, y_radius), angle, 0, 360, Scalar(30), 2); imshow(title, image); pt = Point(-1, -1); } } } int main() { image = Mat(300, 400, CV_8UC1, Scalar(255)); imshow(title, image); setMouseCallback(title, onMouse, 0); waitKey(); return 0; } | cs |
17. 심화예제_4.5.2에서 트렉바를 추가해서 카메라 영상의 밝기와 대비 변경할 수 있도록 수정하시오.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #include <opencv2/opencv.hpp> using namespace std; using namespace cv; void put_string(Mat& frame, string text, Point pt, int value) { text += to_string(value); Point shade = pt + Point(2, 2); int font = FONT_HERSHEY_SIMPLEX; putText(frame, text, shade, font, 0.7, Scalar(0, 0, 0), 2); putText(frame, text, pt, font, 0.7, Scalar(120, 200, 90), 2); } VideoCapture capture; void bright_bar(int value, void*) { capture.set(CAP_PROP_BRIGHTNESS, value); } void contrast_bar(int value, void*) { capture.set(CAP_PROP_CONTRAST, value); } void zoom_bar(int value, void*) { capture.set(CAP_PROP_ZOOM, value); } void focus_bar(int value, void*) { capture.set(CAP_PROP_FOCUS, value); } int main(void) { capture.open(0); CV_Assert(capture.isOpened()); capture.set(CAP_PROP_FRAME_WIDTH, 400); capture.set(CAP_PROP_FRAME_HEIGHT, 300); capture.set(CAP_PROP_AUTOFOCUS, 0); //오토 포커싱 중지 capture.set(CAP_PROP_BRIGHTNESS, 150); int zoom = capture.get(CAP_PROP_ZOOM); int focus = capture.get(CAP_PROP_FOCUS); int bright = capture.get(CAP_PROP_BRIGHTNESS); int contrast = capture.get(CAP_PROP_CONTRAST); string title = "카메라 속성 변경"; namedWindow(title); createTrackbar("zoom", title, &zoom, 10, zoom_bar); createTrackbar("focus", title, &focus, 40, focus_bar); createTrackbar("focus", title, &bright, 255, bright_bar); createTrackbar("focus", title, &contrast, 50, contrast_bar); for (;;) { Mat frame; capture >> frame; //영상 받기 put_string(frame, "zoom = ", Point(10, 240), zoom); put_string(frame, "focus: ", Point(10, 270), focus); imshow(title, frame); if (waitKey(30) >= 0) break; } return 0; } | cs |
18.PC 카메라를 통해서 영상을 입력받아서 다음의 영상 처리를 수행하고 , 영상을 윈도우 창에 표시하는 프로그램을 작성하시오.
| 1. 200,100 좌표에서 100*200 크기의 관심영역 지정 2. 관심영역에서 녹색 성분을 50만큼 증가 3. 관심영역의 테두리를 두께 3의 빨간색으로 표시하시오. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include<opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { VideoCapture capture; capture.open(0); CV_Assert(capture.isOpened()); while (true) { Mat img; capture >> img; Mat area = img(Rect(200, 100, 100, 200)); area += Scalar(0, 50, 0); rectangle(area, Rect(0, 0, 100, 200), Scalar(0, 0, 255), 3); if (waitKey(30) >= 0) break; imshow("img", img); } return 0; } | cs |
19. PC 카메라를 통하여 영상을 입력받아서 좌우를 뒤집어서 flip_test.avi 이름의 동영상 파일로 저장하는 프로그램을 작성하시오.
| 1. 동영상 파일의 크기 640*480 2. 초당 프레임 수 : 15fps 3. 동영상 코덱 : DIVX |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main() { VideoCapture capture; capture.open(0); CV_Assert(capture.isOpened()); capture.set(CAP_PROP_FRAME_WIDTH, 640); capture.set(CAP_PROP_FRAME_HEIGHT, 480); capture.set(CAP_PROP_FPS, 15); int fourcc = VideoWriter::fourcc('D', 'I', 'V', 'X'); VideoWriter save; save.open("flip_test.avi", fourcc, capture.get(CAP_PROP_FRAME_COUNT), Size(640, 480)); while (true) { Mat frame; capture >> frame; flip(frame, frame, 1); save << frame; if (waitKey(30) >= 0) break; imshow("frame", frame); } return 0; } | cs |
20. 임의의 영상 파일을 행렬로 읽어 들여서 예외처리를 하고, 그 정보들을 XML 파일로 저장하는 프로그램을 작성하시오.
| 1. 영상의 크기를 'image_size'라는 이름으로 저장 2. 영상의 깊이 값(depth)을 'depth''라는 이름으로 저장 3. 영상의 모든 화소값들을 'image_data'라는 이름으로 저장 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(void) { Mat img = imread("big_moon.jpg"); if (img.empty()) { cerr << "Image load failed" << endl; return -1; } FileStorage fs("image.xml", FileStorage::WRITE); CV_Assert(fs.isOpened()); fs << "image_size" << img.size(); fs << "depth" << img.depth(); vector<Mat> vecimg; img = img.reshape(1, 1); vecimg.push_back(img); fs << "image_data" << vecimg; imshow("window", img); waitKey(); return 0; } | cs |
