OpenCV 핸드북 (cheatsheet)

프로그래밍/opencv 2013.02.27 18:47

제가 개인적 참고용으로 만든 opencv 함수들 사용법 목록입니다. 간단한 함수라 하더라도 함수이름이나 사용법이 잘 기억나지 않을 때가 종종 있습니다. 한 부 출력해 놓고 이럴 때 보면 꽤 유용합니다.


1. 이미지 읽기 & 저장

2. 이미지 생성, 복사, 형변환, 색상변환, roi 설정

3. 행렬 원소접근 및 생성초기화

4. 영상 크기변경 및 상하좌우 반전

5. 이미지에 그리기 (drawing)

6. 이미지 디스플레이하기 (display)

7. 웹캠 연결하기

8. avi 비디오 파일 읽어오기

9. avi 비디오 녹화하기

10. 창에 Trackbar 붙이기



1. 이미지 읽기 & 저장

Mat img_color = imread("sample.jpg"); // color load

Mat img_gray = imread("sample.jpg", 0);    // gray load

Mat img_16bit = imread("sample.jpg", cv::IMREAD_ANYDEPTH);  // 원본 depth로 읽기

imwrite("fname.jpg", img);


2. 이미지 생성, 복사, 형변환, 색상변환, roi 설정

int w = 320;// width

int h = 240;// height


// 생성

Mat img(h,w,CV_8UC1);//1채널 unsigned char

Mat img(h,w,CV_8UC3);//3채널 unsigned char

Mat img = Mat::zeros(h,w,CV_32FC1);//1채널 float

Mat img = Mat::ones(h,w,CV_64FC3);//3채널 double


unsigned char * img_buffer;// 이미지버퍼 포인터

Mat img(h, w, CV_8UC3, img_buffer);//메모리 공유


// 타입 만들기

CV_MAKETYPE(CV_32F, 3);    // CV_32FC3


// 원소 초기화

Mat img(h,w,CV_8UC1);

img = Scalar(3); // img 모든 원소값 3으로 초기화


// 참조, 복사

Mat img2 = img; // 메모리 공유

Mat img2 = img.clone(); // 별도 메모리

Mat img2; img.copyTo(img2);//별도 메모리


// 형변환 복사

Mat img1(h,w,CV_32FC1);

Mat img2;

img1.convertTo(img2, CV_8U);


// gray-color 변환

cvtColor(color, gray, CV_BGR2GRAY);

cvtColor(gray, color, CV_GRAY2BGR);


// roi 설정

Rect roi;

Mat sub_img = img(roi);//메모리공유

Mat sub_img = img(roi).clone();//별도메모리


3. 행렬 원소접근 및 생성초기화

Mat A = (Mat_<int>(3,1) << 1, 2, 3);

Mat B = (Mat_<double>(3,2) << 1, 1, 2, 2, 3, 3); // 첫 번째 행부터 채워짐

A.at<int>(2,0) = 3; // .at<type>(y, x)

B.at<double>(2,1) = -0.1;


Mat C(h, w, CV_8UC3);

C.at<Vec3b>(y, x)[0]; // blue

C.at<Vec3b>(y, x)[1]; // green 

C.at<Vec3b>(y, x)[2]; // red


4. 영상 크기변경 및 상하좌우 반전

// 크기 변경

Mat dst;

resize(img, dst, Size(new_w,new_h));

resize(img, dst, Size(), 0.5, 0.5);//scalex, scaley


// 영상 반전(flip)

flip(img, dst, 0);// vertical flip

flip(img, dst, 1);// horizontal flip

flip(img, dst, -1);// vertial & horizontal flip


5. 이미지에 그리기 (drawing)

Rect rc(x,y,w,h);

Scalar color(B,G,R);

int thickness=1; // line thickness


line(img, Point(x1,y1), Point(x2,y2), color, thickness);


rectangle(img, rc, color, thickness);

rectangle(img, rc.tl(), rc.br(), color, thickness);

rectangle(img, rc, color, CV_FILLED); // filled rectangle


Point center(rc.x+rc.width/2, rc.y+rc.height/2);

Size radius(rc.width/2, rc.height/2);

double rot_deg = 0; // rotation of ellipse

double s_deg = 0; // start angle of arc

double e_deg = 360; // end angle of arc

ellipse(img,center,radius,rot_deg,s_deg,e_deg,color,thickness);

ellipse(img,center,radius,rot_deg,s_deg,e_deg,color,CV_FILLED);


int circle_radius = 10;

circle(img, center, circle_radius, color, thickness);

circle(img, center, circle_radius, color, CV_FILLED);


putText(img, "text", Point(x,y), FONT_HERSHEY_SIMPLEX, 1., color, thickness);

putText(img, "text", Point(x,y), FONT_HERSHEY_DUPLEX, 1., color, thickness);


6. 이미지 디스플레이하기 (display)

namedWindow("name"); // auto resized

namedWindow("name",CV_WINDOW_NORMAL); // manual resize


imshow("name", img);

char ch = waitKey(); // 무한 대기

char ch = waitKey(10); // 10 msec 대기

if(ch == 27) ... // ESC key

if(ch == 32) ... // SPACE key


destroyWindow("name");

destroyAllWindows();


7. 웹캠 연결하기

VideoCapture vc(0);

if (!vc.isOpened()) return; // 연결실패

vc.set(CV_CAP_PROP_FRAME_WIDTH, 640);

vc.set(CV_CAP_PROP_FRAME_HEIGHT, 480);


Mat img;

while(1){

vc >> img;

if(img.empty()) break;

imshow("cam",img);

if(waitKey(10)==27) break; //ESC

}

destroyAllWindows();


8. avi 비디오 파일 읽어오기

VideoCapture vc("sample.avi");

if (!vc.isOpened()) return; // 불러오기 실패


Mat img;

while(1){

vc >> img;

if(img.empty()) break;

imshow("video",img);

if(waitKey(10)==27) break; //ESC

}

destroyAllWindows();

9. avi 비디오 녹화하기

double fps = 15;

int fourcc = CV_FOURCC('X','V','I','D'); // codec (opencv3.0이하)

int fourcc = VideoWriter::fourcc('X','V','I','D'); // opencv3.0이상


bool isColor = true;


VideoWriter *video = new VideoWriter;

if(!video->open("result.avi", fourcc, fps, Size(img_w, img_h), isColor)){

delete video;

return;

}


Mat img;

while(1){

// ...

*video << img;

// ...

}

delete video;


※ 코덱 목록: http://www.fourcc.org/codecs.php


10. 창에 Trackbar 붙이기

int threshold = 10;

cv::namedWindow("display");

cv::createTrackbar("thr:", "display", &threshold, 1000);


11. 다운로드


OpenCV핸드북v1.txt



참고로 영상처리 라이브러리인 OpenCV 공식 홈페이지에서 제공하는 cheatsheet라는게 있습니다. opencv 함수 사용법을 요약해 놓은 2페이지짜리 pdf 파일입니다.


by 다크 프로그래머

  • 이전 댓글 더보기
  • 123 2015.08.22 23:24 신고 ADDR 수정/삭제 답글

    그냥 저렇게 return이라고 하면 main함수는 값을 반환해야한다고 뜹니다!!

    • BlogIcon 다크pgmr 2015.08.23 16:41 신고 수정/삭제

      네, c나 c++에서 기본적인 문법에 관련된 내용입니다. 사용하는 함수의 반환값이 void면 그냥 return만 하면 되고, 함수의 반환값이 int형이면 int형을 반환해야 합니다.

  • dndhkdrnt 2015.12.04 20:14 신고 ADDR 수정/삭제 답글

    우와!
    감사합니다!

  • 11 2016.01.14 17:20 신고 ADDR 수정/삭제 답글

    videocapture 사용해서 웹캠 연결하고 캡쳐후 저장하는 코드는 어떻게 작성하나요?

    • BlogIcon 다크pgmr 2016.01.14 17:56 신고 수정/삭제

      vc >> img; 로 캡쳐후 imwrite("tt.jpg", img); 등으로 저장하면 됩니다.

  • cv 2016.01.27 13:27 신고 ADDR 수정/삭제 답글

    CvvImgae를 사용해서 Picture control에 영상을 집어넣을때, 640x480해상도의 캠은 인식되나, 1920x1080해상도의 캠을 사용했을때는 회색화면만 나오는 문제가 발생합니다.
    혹시 videocapture함수를 사용해서 picture control에 영상을 집어넣을 수 있는 방법이 있을까요???
    videocpature를 사용해서 1920x1080해상도의 캠 영상을 받아들이는 부분까지는 해봤습니다만, 어딜 뒤져봐도 picture control과 연동하는 방법에 대해서는 쓰여있지 않아서 여쭤봅니다.

    • BlogIcon 다크pgmr 2016.01.29 14:55 신고 수정/삭제

      말씀하신 picture control이 무엇인지는 잘 모르지만 당연히 가능할 것이라고 생각합니다. 하지만 구체적인 프로그래밍에 관련된 부분은 제가 답변해 드릴 수 있는 사항이 아닙니다. 이미지의 메모리 구조에 대해 공부해 보시면 좋을 것 같습니다.

  • 비젼 2016.04.02 20:18 신고 ADDR 수정/삭제 답글

    다크님 제가 매트랩 코드를 open cv포팅중인데.. 디버깅중에 이미지데이터를 추적해보니 rgb데이터를 2차원으로 받아오는걸 발견했습니다. 3차원이어야 맞는 것 같은데 혹시 이유를 알 수 있을까요?

    • BlogIcon 다크pgmr 2016.04.03 07:12 신고 수정/삭제

      이유는 알수 없습니다만, 혹시 imread 함수를 사용한 것이라면 함수의 파라미터를 어떻게 주느냐에 따라서 color로도 gray로도 이미지를 읽을 수 있으니 함수 설명을 참조해 보시기 바랍니다.

  • 후으 2016.05.17 12:01 신고 ADDR 수정/삭제 답글

    Rect roi;
    Mat sub_img = img(roi);//메모리공유
    Mat sub_img = img(roi).clone();//별도메모리

    혹시 이 부분에서 img(roi) img 메소드가 자바에서 무슨 메소드로 되있는지 알 수 있을까요??

  • 입원중 2016.07.07 18:25 신고 ADDR 수정/삭제 답글

    cheatsheet pdf 링크가 깨진것 같습니다. 필요하신 분은 아래 주소에서 받으시면 될것같습니다.
    http://docs.opencv.org/3.0-last-rst/opencv_cheatsheet.pdf

    • BlogIcon 다크pgmr 2016.07.07 19:22 신고 수정/삭제

      말씀하신 주소로 링크를 수정하였습니다. 감사합니다 ^^

  • 김공자 2016.07.17 16:31 신고 ADDR 수정/삭제 답글

    7번에 emplty() 오타 있는것같습니다!

    • BlogIcon 다크pgmr 2016.07.17 23:08 신고 수정/삭제

      오타 제보 감사합니다. ^^ 수정하였습니다.

  • 하하하 2017.03.14 23:16 신고 ADDR 수정/삭제 답글

    namedwindow(" ") 이게 확실히 무슨뜻인가요 ..?? ㅜㅜ

    • BlogIcon 다크pgmr 2017.03.15 12:30 신고 수정/삭제

      opencv의 온라인 문서(http://docs.opencv.org/3.2.0/)를 보면 함수들에 대한 설명을 볼 수 있습니다. namedWindow는 입력한 이름(name)으로 창(window)을 하나 생성해서 띄워주는 일을 합니다.

  • opencv 2017.03.21 17:22 신고 ADDR 수정/삭제 답글

    혹시 imread로 파일을 읽었을 경우 이미지가 회전된 상태로 mat에 저장되는 현상을 겪어 보셨는지요? 윈도우 화면에서는 제대로 나오는데 mat에 이미지를 불러오기만 하면 자동으로 회전이 된 이미지로 불러와집니다.

    • BlogIcon 다크pgmr 2017.03.21 17:55 신고 수정/삭제

      저는 그런 현상을 겪어보지 않았지만 opencv의 imread에 대한 함수설명을 보니 IMREAD_IGNORE_ORIENTATION라고 회전에 관련된 파라미터가 있는 것 같습니다. opencv의 online api를 참고해 보시기 바랍니다 (http://docs.opencv.org/3.2.0/)

  • help 2017.07.06 16:52 신고 ADDR 수정/삭제 답글

    영상을 저장후 재생을 하면 영상속도가 몇배로 빨리 재생이됩니다.
    혹시 이런경우는 어떤식으로 해야되는지 아시나요..??
    아 길이를 아주 길게 저장해도 재생을 하면 동영상이 1초로 압축되서 재생이됩니다ㅠㅠ

    • BlogIcon 다크pgmr 2017.07.06 18:48 신고 수정/삭제

      실제 녹화속도가 비디오객체 생성시 설정한 fps보다 느리면 그러한 현상이 나타납니다. 비디오객체를 생성할 때 fps를 낮춰보시면 어떨지요. 1초로 압축되는건 저도 잘 모르겠네요.. 그럴 수 있나요?

  • 키넥트 2017.11.10 22:40 신고 ADDR 수정/삭제 답글

    혹시 키넥트관련해서 소스를 병합할 수 있나요?

    • BlogIcon 다크pgmr 2017.11.11 00:10 신고 수정/삭제

      네?? 소스를 병한합다는 것이 무슨 의미인가요?

  • 질문자 2017.12.21 15:27 신고 ADDR 수정/삭제 답글

    안녕하세요,
    제가 현재 opencv 2.3.1을 사용 중입니다.
    dc의 이미지를 동영상으로 저장하기 위하여, dc의 data를 IplImage로 변환하는 과정을 끝냈습니다.
    하지만 동영상을 저장할 때마다 오류로 인해, 프로그램이 뻑납니다.
    녹화를 화면 출력과 동시에 해주어야해서 OnTimer Thread에서 화면출력과 동영상 저장을 해주고,
    버튼을 따로 구현하여 하나는 동영상저장 시작(코덱, 경로, 프레임 등 설정), 다른 한 버튼에는 동영상종료(release)를 해주는데 자꾸 문제가 발생하네요.

    말이 난잡하지만 정리를 해서 말씀드리면, 현재 웹캠이 아닌 다른 무언가로 촬영을 하고 있습니다. 그 촬영된 영상은 프로그램 화면의 dc에 매번 뿌려지는 Thread를 통하여 프로그램 내에서는 실시간 영상처럼 출력이 되고 있습니다. 즉, dc에 뿌려지는 이미지를 동영상 파일로 저장하고 싶습니다.
    그래서 dc의 data를 IplImage 형태로 가공을 하였습니다. 그 후, 동영상 저장의 while 이전 부분은 시작 버튼 함수, while 이후 부분은 종료 버튼 함수, while 내부 부분은 영상이 화면에 뿌려지는 Thread 내부에 시작 버튼을 눌렀을 경우(BOOL)에만 동영상 내용을 쓰도록 하였습니다.

    지금까지 발견된 현상은 3가지 입니다.
    화면이 담긴 동영상 파일이 정상적으로 생성되나, 플레이 타임이 0초이다.
    저장이 안된 채 프로그램이 뻗는다. 파일은 0바이트로 생성된다. (R6010 에러 / abort() has been called 에러)

    어느 곳을 찾아봐도 원하는 답변이 나오질 않아 답답하여 여기에라도 글 남깁니다.
    혹시 방법을 아신다면 답변 부탁드립니다.

    참고로 mfc 환경입니다.

    • BlogIcon 다크pgmr 2017.12.21 15:54 신고 수정/삭제

      질문자님, 일단 dc 이미지가 아닌 샘플 이미지나 가상의 이미지 등을 통해서 opencv 코드로 동영상 생성이 정상적으로 진행되는지 확인해 보시면 좋을 것 같습니다. 그렇게 해서 일단 성공적으로 동작하는 코드가 얻어지면 여기서 하나씩 부가적인 내용들을 추가해서 현재 코드까지 도달하면 어떤 부분이 문제인지 확인 및 해결이 가능할 것으로 생각됩니다. 제가 드릴 수 있는 조언은 문제 원인을 찾기 힘들 때에는 최대한 변화 요인을 제거하고 문제를 단순화시켜라는 것입니다. 제가 문제를 풀때 항상 사용하는 방법입니다. 그리고, 말씀하신 현상만 듣고 다른 사람이 원인을 아는 것은 불가능한 일입니다.

    • 질문자 2017.12.26 09:31 신고 수정/삭제

      네, 글을 읽고 확인해 본 결과, Create 할때의 size와 원본 image의 size가 맞지않아 일어난 문제 였습니다. 조언 감사드립니다.

  • BlogIcon 어쩌다 2018.01.08 22:26 신고 ADDR 수정/삭제 답글

    다크님 안녕하세요. 예전부터 궁금했는데 해결하지 못한 문제가 있어서 질문드리러 왔습니다.
    제가 opencv330 버전을 쓰고있는데요. C++ windows console 프로젝트로 프로그래밍 했습니다. namedwindow(" ")로 생성된 창에 같은 이름을 준 이미지를 imshow로 생성해도 같은 이름의 새로운 창에 생성되고 namewindow로 생성된 창은 변화가 없습니다. 그리고 destroywindow 함수를 써도 창이 없어지지 않습니다. imshow와 namedwindow는 따로 움직이는 함수인가요?

    • BlogIcon 다크pgmr 2018.01.08 23:16 신고 수정/삭제

      저는 모르는 현상입니다. 그런 적이 없어서.. opencv에서는 윈도우 이름이 같으면 동일한 창으로 인식되는 것이 정상입니다.

    • 어쩌다 2018.01.09 09:14 신고 수정/삭제

      아... 그런가요. 좀 더 공부를 해야겠군요 ㅎㅎ 답변 감사합니다.

  • 열다컴퓨터시야 2018.02.13 17:48 신고 ADDR 수정/삭제 답글

    다크님, 안녕하세요. 선배의 추천으로 다크님 홈페이지 통해 openCV 공부중인 신참입니다.
    동영상 열고 저장 등 기초적인 기능 구현을 연습해보다가, 컴파일 에러도 아닌
    VideoWriter 에서 ->open가 거짓으로 뜨는 부분을 해결하지 못하고 있습니다.
    코덱 문제인가 싶어 종합코덱도 다운받아 설치해봐도 안되고
    코덱명을 XVID가 아니라 MJPG로 바꾸면 해당부분은 넘어가지기는 하는데 화면이 회색으로만 뜨고 영상이 안보이더군요.... 함수 이용이 아닌 설정단의 문제는 어떻게 해결하면 좋을까요..?ㅠㅠ

    • BlogIcon 다크pgmr 2018.02.14 17:45 신고 수정/삭제

      안녕하세요. 저도 딱히 떠오르는 것은 없는데요, 혹시 opencv_ffmpegxxx.dll 파일이 실행 경로상에 없어서 그런 것은 아닌지 의심이 듭니다. 그래도 해결이 안되면 코덱값에 0을 주면 압축은 안되겠지만 어찌됐든 녹화는 될 수 있으니 한번 시도해 보시기 바랍니다.

  • 마이클플리 2018.03.22 09:20 신고 ADDR 수정/삭제 답글

    영상처리 뭘 찾다보면 높은 확율로 다크프로그래머님 블로그로 오게 되는군요 ^^;

  • BlogIcon C++ 2018.04.03 20:14 신고 ADDR 수정/삭제 답글

    다크님, 16bit(CV_16U)이상 이미지를 imwrite로 저장해서 다시 불러오면 8bit(CV_8U) 이미지가 되있는데.. 어떻게 해야 16bit 이미지를 저장할 수 있나요? 64bit 이미지를 만들어야하는데..

    • BlogIcon 다크pgmr 2018.04.04 11:44 신고 수정/삭제

      일단은 16비트를 지원하는 이미지 포맷으로 저장해야 하는데, opencv 설명에 보면 png, jpeg2000, tiff가 16비트를 지원한다고 합니다. 즉, png로 이미지를 저장하면 16비트 이미지를 저장할 수 있습니다 (bmp, jpeg등으로 저장하면 안됩니다). 이미지를 불러올 때는 그냥 imread를 호출하면 안되고, 인자에 cv::IMREAD_ANYDEPTH를 줘야합니다.

      cv::Mat tmp = cv::Mat::ones(100, 200, CV_16UC3);
      cv::imwrite("test.png", tmp);
      cv::Mat tmp2 = cv::imread("test.png", cv::IMREAD_ANYDEPTH);

  • 파지직 2018.05.09 17:06 신고 ADDR 수정/삭제 답글

    감사합니다! 많이 참고하겠습니다

  • Jinnnn 2018.05.23 18:34 신고 ADDR 수정/삭제 답글

    안녕하세요, IppByteImage 라는 class를 만들었는데요,
    typedef IppImage<BYTE> IppByteImage;

    IppByteImage imgGray_Ref;
    imgGray_Ref에는 Byte 형식의 image가 저장되어 있습니다.
    그런데 opencv 함수를 이용해서 사용하고 싶은데, 그러려면 이 이미지를 Mat 형식으로 변환해줘야 할거같아요..
    그런데 어떻게 해야할지 모르겠어서 ㅠ 이렇게 문의드립니다.
    답변 부탁드립니다! 감사합니다.

    • BlogIcon 다크pgmr 2018.05.23 20:46 신고 수정/삭제

      opencv 메뉴얼(https://docs.opencv.org/) 중 cv::Mat 클래스의 생성자들을 찾아보시면 (특히, 메모리 주소를 공유해서 Mat 객체를 생성하는 방법 부분) 해결할 수 있을 것으로 생각됩니다.
      unsigned char * img_buffer;
      Mat img(h, w, CV_8UC3, img_buffer);

  • jin 2018.08.30 10:02 신고 ADDR 수정/삭제 답글

    안녕하세요! opencv를 공부하는 학생입니다. 다름이 아니라, 현재 제가 하고 싶은 것은 저장된 동영상을 불러와 움직임,얼굴 인식 하는 코드를 구현하고 싶은데 조언을 구할 수 있으면 좋을 것 같습니다.!

    • BlogIcon 다크pgmr 2018.08.30 15:13 신고 수정/삭제

      opencv에는 얼굴인식과 관련된 쓸만한 라이브러리는 따로 없습니다. dlib 같은 것을 이용해 보는 것이 좋을 것 같습니다. 그리고, 동영상 입출력 등 기본적인 opencv 사용법에 대해서는 opencv에서 제공하는 예제코드나 관련 서적을 참조하시면 됩니다.