전체 글 (755)
[3D 비전] optic flow software를 활용해서 디스패리티 맵 산출하기 (matlab) 2017.05.18 13:42:02
반응형

optic flow software 매트랩 소스코드는 [1]에서 다운로드 받으실 수 있습니다. 그리고 이 소프트웨어와 관련된 논문은 [2]입니다. [3] 논문에서 이 소프트웨어를 활용해서 디스패리티 맵을 산출한 것을 따라서 저도 디스패리티 맵을 산출해보려고 합니다. 소프트웨어를 통해 산출된 모션 벡터들에서 수평 성분을 수평 디스패리티로 사용했습니다.

 

▶ 소스코드 테스트

 

그림 1은 테스트에 사용된 이미지들[4]과 ground truth 디스패리티 맵과 산출된 디스패리티 맵을 보여줍니다. 밝을 수록 카메라로부터 가깝고, 어두울 수록 멀다는 것을 의미합니다. 이 소프트웨어를 활용해서 산출한 디스패리티 맵이 상당히 거리감을 잘 나타냄을 그림을 통해 알 수 있습니다.

 

그림1. 왼쪽 뷰, 오른쪽 뷰, ground truth disparity map, 산출된 disparity map

 

 

<참고 자료>

[1] http://ps.is.tue.mpg.de/person/black#tabs-code

[2] Secrets of optical flow estimation and their principles, Sun, D., Roth, S., and Black, M. J., IEEE Conf. on Computer Vision and Pattern Recog., CVPR, June 2010.

[3] J Park, S Lee, AC Bovik, 3d visual discomfort prediction: vergence, foveation, and the physiological optics of accommodation. IEEE J. Sel. Top. Sign. Process. 8(3), 415–427 (2014)

[4] http://vision.middlebury.edu/stereo/data/

반응형
secret
[MATLAB] grape-based visual saliency (GBVS)로 saliency 맵 산출하기 2017.05.16 19:56:59
반응형

GBVS는 visual saliency 모델 중 하나입니다. visual saliency 모델은 이미지 내 시각적으로 중요한 부분들이 어딘지를 나타내주는 알고리즘입니다. GBVS에 대한 이론적 설명은 링크를 참고해주세요. 그리고 GBVS의 매트랩 소스코드는 [1]에서 받을 수 있습니다. 또한 GBVS에 대한 original 논문은 [2]입니다.

 

 

소스코드 테스트

 

소스코드를 다운 받으시면 폴더 내에 readme.txt에 어떻게 사용하는지 구체적으로 자세히 나와있습니다. 혹시 잘 모르시겠다면 댓글 달아주세요. 네 장의 사진의 GBVS를 통해 얻은 saliency 맵은 그림1에 있습니다. saliency 맵에서 밝은 부분일 수록 시각적으로 중요하다고 판단한 부분입니다. 

 

그림1. gbvs로 얻은 saliency 맵들

 

첫번째 빨간 차가 있는 사진을 제외하고는 적절하게 시각적 중요도에 따라 saliency 맵들이 산출된 것 같습니다. GBVS로 얻은 saliency 맵만 봐서는 GBVS가 효과적인지 아닌지 판단하기 어려우니 다른 saliency 알고리즘도 사용해보겠습니다. 위에 소개드린 GBVS 매트랩 소스코드를 담은 폴더 내에 Itti가 제안한 알고리즘[3]의 소스코드도 포함되어 있습니다. Itti가 제안한 이 알고리즘은 최초의 visual saliency 계산 모델이라고 볼 수 있습니다. 그림2는 Itti 알고리즘을 사용해 얻은 saliency 맵들입니다. 

 

그림2. [3]이 제안하는 모델로 얻은 saliency 맵들

 

이 방법도 괜찮은 결과를 산출하는 것 같습니다. 개인적인 소견으로 사람이 있는 사진에서는 GBVS가 좀 더 나은 saliency 맵을 만들어내는 것 같고, 풍경 사진에서는 [3]이 좀 더 나은 결과를 내는 것 같습니다. 

 

 

<참고 자료>

[1] http://www.vision.caltech.edu/~harel/share/gbvs.php

[2] J. Harel, C. Koch, and P. Perona. "Graph-Based Visual Saliency", NIPS 2006

[3] L. Itti, C. Koch, & E. Niebur "A model of saliency based visual attention for rapid scene analysis", IEEE Transactions on Pattern Analysis and Machine 1998

 

반응형
secret
[Learn opencv by examples] 3. 기본적인 드로잉 예제들 2017.05.16 00:51:07
반응형

오늘은 http://opencvexamples.blogspot.com/p/learning-opencv-functions-step-by-step.html에 있는 세번째 예제를 따라해보도록 하겠습니다. 

 

3. Basic drawing examples

1) 선 그리기

소스코드부터 보시죠. 

 

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/imgproc/imgproc.hpp>

 

using namespace cv;

 

int main()

{

// Create black empty images

Mat image = Mat::zeros(400, 400, CV_8UC3); // 세로, 가로 각각 400, 400 사이즈의 검정 이미지를 만든다. 

 

// Draw a line 

line(image, Point(15, 20), Point(300, 350), Scalar(0, 255, 0), 10, 8); 

imshow("Image", image);

imwrite("result.bmp", image);

 

waitKey(0);

return(0);

}

 

링크의 예제에서는 #include <opencv2/imgproc/imgproc.hpp>가 없는데, 이걸 포함해줘야 line 함수를 사용할 수 있습니다. line 함수에 대해서 아는 한 설명을 해보겠습니다. 

 

line(image, Point(15, 20), Point(300, 350), Scalar(0, 255, 0), 10, 8); 

  • 1번째 인수: 도화지가 되어줄 이미지를 넣어줍니다. 
  • 2번째, 3번째 인수: 어디서부터 어디까지 선을 그릴지 픽셀 위치들을 뜻합니다. 즉 (15, 20)부터 (300, 350)을 잇는 선을 그리겠다는 것입니다. 

  • 4번째 인수: 선의 색을 결정지어줍니다. Scalar(0, 255, 0)은 녹색 선을 그리겠다는 것입니다. BGR순서로 되어 있습니다. 만약 Scalar(0, 0, 255)라고 세팅-하면 빨간색 선이 될 것입니다. 
  • 5번째 인수: 선의 굵기를 선택합니다. 클수록 굵어집니다.
  • 6번째 인수: 라인의 타입을 결정해줍니다. (이것의 역할은 잘 몰라서, 일단 그냥 default값으로 놔두겠습니다.)

 

실행결과 아래와 같은 이미지가 전시되고, 저장됩니다.

 

 

2) 원 그리기

이번에는 원을 그려보도록 하겠습니다. 소스코드는 아래와 같습니다. 

 

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/imgproc/imgproc.hpp>

 

using namespace cv;

 

int main()

{

// Create black empty images

Mat image = Mat::zeros(400, 400, CV_8UC3); // 세로, 가로 각각 400, 400 사이즈의 검정 이미지를 만든다. 

 

// Draw a circle 

circle(image, Point(200, 200), 32.0, Scalar(0, 0, 255), 5, 8); 

  circle(image, Point(100, 300), 40.0, Scalar(255, 0, 255), 10, 8);

imshow("Image", image);

imwrite("result.bmp", image);

 

waitKey(0);

return(0);

}

 

circle 함수 

  • 1번째 인수: 역시 도화지가 되어줄 이미지입니다. 여기서는 400 x 400의 검정 이미지이겠지요? 
  • 2번째 인수: 원의 중심의 픽셀 위치입니다. 
  • 3번째 인수: 원의 반지름입니다. 
  • 4번째 인수: 원의 색깔로 역시 BGR순서로 되어 있습니다. 첫번째 원은 빨간 색이 되게 Scalar(0, 0, 255)로 설정했습니다. 
  • 5번째 인수: 원의 두께를 결정해주는 것입니다. 클수록 두꺼워집니다. 
  • 6번째 인수: 라인의 타입을 결정해주는 것입니다. 

 

line 함수의 인수들의 진행패턴과 크게 다르지 않습니다. 아래 그림은 결과로 그려진 두 개의 원을 보여줍니다. 

 

 

3) 타원 그리기

이번에는 타원을 그리겠습니다. 

 

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/imgproc/imgproc.hpp>

 

using namespace cv;

 

int main()

{

// Create black empty images

Mat image = Mat::zeros(400, 400, CV_8UC3); // 세로, 가로 각각 400, 400 사이즈의 검정 이미지를 만든다. 

 

// Draw a ellipse

        ellipse(image, Point(200, 200), Size(100.0, 160.0), 45, 0, 360, Scalar(255, 0, 0), 1, 8);

ellipse(image, Point(200, 200), Size(100.0, 160.0), 0, 0, 360, Scalar(255, 0, 0), 5, 8);

ellipse(image, Point(200, 200), Size(100.0, 160.0), 135, 0, 360, Scalar(255, 0, 0), 10, 8);

imshow("Image", image);

imwrite("result.bmp", image);

 

waitKey(0);

return(0);

}

 

ellipse 함수가 타원을 그릴 때 사용하는 함수입니다. 

  • 1번째 인수: 도화지가 될 이미지입니다. 
  • 2번째 인수: 타원의 중심위치입니다. 
  • 3번째 인수: 타원축들의 길이를 의미합니다. 즉, 세번째 인수가 Size(100,0, 160,0)라면 x축으로는 100만큼, y축으로는 160만큼 긴 모양의 타원을 만들겠다는 것입니다. 
  • 4번째 인수: 타원이 회전된 각도입니다. 첫번째 타원의 경우 45도만큼 오른쪽으로 회전시키겠다는 것입니다. 
  • 5번째, 6번째 인수: 타원이 시작하는 각도와 끝나는 각도를 결정지어주는 것인데 완전한 타원을 그리고 싶다면 0, 360으로 설정해주면 됩니다. 
  • 7번째 인수: 색을 결정해주는 것입니다. 세 타원 모두 파란색으로 설정해줬습니다. 
  • 8번째 인수: 타원의 굵기를 결정해주는 것입니다. 크면 클수록 굵어집니다. 
  • 9번째 인수: 역시 선의 타입을 결정해주는 것입니다. 

 

아래 그림은 결과적으로 그려진 3개의 타원을 보여줍니다. 뭔가 멋있네요. 

 

 

4) 직사각형 그리기

직사각형 그리는 코드입니다.

 

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/imgproc/imgproc.hpp>

 

using namespace cv;

 

int main()

{

// Create black empty images

Mat image = Mat::zeros(400, 400, CV_8UC3); // 세로, 가로 각각 400, 400 사이즈의 검정 이미지를 만든다. 

 

// Draw a rectangle

rectangle(image, Point(15, 20), Point(70, 50), Scalar(0, 55, 255), +1, 4); 

rectangle(image, Point(200, 300), Point(300, 350), Scalar(100, 100, 0), -1, 8); 

imshow("Image", image);

imwrite("result.bmp", image);

 

waitKey(0);

return(0);

}

 

직사각형을 그려주는 rectangle 함수를 살펴봅시다. 

  • 1번째 인수: 도화지가 되어줄 이미지입니다.
  • 2번째 인수: 직사각형의 왼쪽 상단 모서리 픽셀 위치입니다.
  • 3번째 인수: 직사각형의 오른쪽 하단 모서리 픽셀 위치입니다.
  • 4번째 인수: 색을 결정해줍니다.
  • 5번째 인수: 양수면 빈 직사각형, 음수면 채워진 직사각형을 만듭니다.
  • 6번째 인수: 라인의 타입을 결정해줍니다. 

 

구현된 결과이미지입니다. 하나의 빈 직사각형과 하나의 채워진 직사각형을 보실 수 있습니다.

 

 

 

5) 다각형 그리기

이번에는 채워져있는 다각형을 그려보겠습니다. 

 

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/imgproc/imgproc.hpp>

 

using namespace cv;

 

int main()

{

// Create black empty images

Mat image = Mat::zeros(400, 400, CV_8UC3); // 세로, 가로 각각 400, 400 사이즈의 검정 이미지를 만든다. 

 

int w = 400;

/** Create some points */

Point rook_points[1][20]; // 여기서 rook는 체스의 말의 이름입니다.

rook_points[0][0] = Point(w / 4.0, 7 * w / 8.0);

rook_points[0][1] = Point(3 * w / 4.0, 7 * w / 8.0);

rook_points[0][2] = Point(3 * w / 4.0, 13 * w / 16.0);

rook_points[0][3] = Point(11 * w / 16.0, 13 * w / 16.0);

rook_points[0][4] = Point(19 * w / 32.0, 3 * w / 8.0);

rook_points[0][5] = Point(3 * w / 4.0, 3 * w / 8.0);

rook_points[0][6] = Point(3 * w / 4.0, w / 8.0);

rook_points[0][7] = Point(26 * w / 40.0, w / 8.0);

rook_points[0][8] = Point(26 * w / 40.0, w / 4.0);

rook_points[0][9] = Point(22 * w / 40.0, w / 4.0);

rook_points[0][10] = Point(22 * w / 40.0, w / 8.0);

rook_points[0][11] = Point(18 * w / 40.0, w / 8.0);

rook_points[0][12] = Point(18 * w / 40.0, w / 4.0);

rook_points[0][13] = Point(14 * w / 40.0, w / 4.0);

rook_points[0][14] = Point(14 * w / 40.0, w / 8.0);

rook_points[0][15] = Point(w / 4.0, w / 8.0);

rook_points[0][16] = Point(w / 4.0, 3 * w / 8.0);

rook_points[0][17] = Point(13 * w / 32.0, 3 * w / 8.0);

rook_points[0][18] = Point(5 * w / 16.0, 13 * w / 16.0);

rook_points[0][19] = Point(w / 4.0, 13 * w / 16.0);

 

const Point* ppt[1] = { rook_points[0] };

int npt[] = { 20 };

 

fillPoly(image, ppt, npt, 1, Scalar(255, 255, 255), 8);

imshow("Image", image);

imwrite("result.bmp", image);

 

waitKey(0);

return(0);

}

 

fillPoly함수의 인수들을 살펴봅시다. 

  • 1번째 인수: 도화지가 될 이미지입니다.
  • 2번째 인수: 꼭지점들을 담고 있는 배열입니다. (Array of polygons where each polygon is represented as an array of points)
  • 3번째 인수: 꼭지점들의 갯수를 담고 있는 배열입니다. (Array of polygon vertex counters)
  • 4번째 인수: 색으로 채워진 지역을 감싸는 가장자리의 갯수를 설정해줍니다. (Number of contours that bind the filled region)
  • 5번째 인수: 다각형의 색을 설정합니다.
  • 6번째 인수: 라인의 타입을 결정해줍니다.

 

아래 그림과 같이 체스의 rook가 그려집니다.

 

 

이번에는 fillPoly 함수를 사용해서 다각형 중의 하나인 삼각형을 하나 그려보겠습니다. 코드는 아래와 같습니다.

 

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/imgproc/imgproc.hpp>

 

using namespace cv;

 

int main()

{

// Create black empty images

Mat image = Mat::zeros(400, 400, CV_8UC3); // 세로, 가로 각각 400, 400 사이즈의 검정 이미지를 만든다. 

 

int w = 400;

/** Create some points */

Point rook_points[1][3]; // 여기서 rook는 체스의 말의 이름입니다.

rook_points[0][0] = Point(w / 2.0, w / 4.0); // Point(가로 픽셀 위치, 세로 픽셀 위치)

rook_points[0][1] = Point(w / 4.0, 3 * w / 4.0);

rook_points[0][2] = Point(3 * w / 4.0, 3 * w / 4.0);

 

const Point* ppt[1] = { rook_points[0] };

int npt[] = { 3 };

 

fillPoly(image, ppt, npt, 1, Scalar(255, 255, 255), 8);

imshow("Image", image);

imwrite("result.bmp", image);

 

waitKey(0);

return(0);

}

 

삼각형을 그리므로 세 점만 있으면 됩니다. 그려진 그림은 아래와 같습니다.

 

 

 

6) 이미지에 텍스트 넣기

이제 마지막으로 이미지에 텍스트 넣는 것을 따라해보겠습니다. 

 

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
 
using namespace cv;
 
int main()
{
// Create black empty images
Mat image = Mat::zeros(400, 400, CV_8UC3); // 세로, 가로 각각 400, 400 사이즈의 검정 이미지를 만든다. 
 
putText(image, "God is good!", Point(50, 100), FONT_HERSHEY_PLAIN, 2, Scalar(0, 200, 200), 3); //이미지에 텍스트 넣기
imshow("Image", image);
imwrite("result.bmp", image);
 
waitKey(0);
return(0);
}
 
putText 함수를 살펴봅시다.
  • 1번째 인수: 도화지가 될 이미지입니다.
  • 2번째 인수: 텍스트 내용을 적어줍니다.
  • 3번째 인수: 이미지에서 텍스트가 배치될 위치를 결정해줍니다. 텍스트 스트링의 왼쪽 아래 위치가 됩니다. 
  • 4번째 인수: 폰트를 선택합니다. FONT_HERSHEY_SIMPLEX, FONT_HERSHEY_PLAIN,FONT_HERSHEY_DUPLEX, FONT_HERSHEY_COMPLEX, FONT_HERSHEY_TRIPLEX,FONT_HERSHEY_COMPLEX_SMALL, FONT_HERSHEY_SCRIPT_SIMPLEX, FONT_HERSHEY_SCRIPT_COMPLEX
  • 5번째 인수: 글자의 크기를 결정합니다. 
  • 6번째 인수: 글자의 색을 선택합니다.
  • 7번째 인수: 글자의 두께를 선택합니다. 
실행결과를 보시죠.

 

이번 예제는 조금 길었네요. 그리기 함수들을 이용해서 집을 하나 그려보겠습니다. 코드는 아래와 같습니다.
 

#include <opencv2/core/core.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/imgproc/imgproc.hpp>

 

using namespace cv;

 

int main()

{

// Create black empty images

Mat image = Mat::zeros(400, 400, CV_8UC3); // 세로, 가로 각각 400, 400 사이즈의 검은색 이미지를 만든다. 

 

rectangle(image, Point(0, 0), Point(399, 399), Scalar(255, 255, 255), -1, 8); // 흰색 도화지로 바꿔준다. 

 

// 큰 지붕, 다각형 함수 활용

int w = 400;

Point roof1_points[1][4];

roof1_points[0][0] = Point(140, 40);   

roof1_points[0][1] = Point(260, 40);

roof1_points[0][2] = Point(360, 160);

roof1_points[0][3] = Point(40, 160);

 

const Point* ppt1[1] = { roof1_points[0] };

int npt1[] = { 4 };

fillPoly(image, ppt1, npt1, 1, Scalar(30, 30, 30), 8);

 

// 건물의 몸통. 직사각형 함수 활용

rectangle(image, Point(70, 161), Point(330, 340), Scalar(150, 150, 150), -1, 8);

rectangle(image, Point(70, 341), Point(330, 360), Scalar(30, 30, 30), -1, 8);

 

// 작은 지붕

Point roof2_points[1][4];

roof2_points[0][0] = Point(160, 100);

roof2_points[0][1] = Point(240, 100);

roof2_points[0][2] = Point(300, 172);

roof2_points[0][3] = Point(100, 172);

 

const Point* ppt2[1] = { roof2_points[0] };

int npt2[] = { 4 };

fillPoly(image, ppt2, npt2, 1, Scalar(60, 60, 60), 8);

 

// 중간에 회색 두 줄

rectangle(image, Point(150, 173), Point(160, 340), Scalar(100, 100, 100), -1, 8);

rectangle(image, Point(240, 173), Point(250, 340), Scalar(100, 100, 100), -1, 8);

 

//굴뚝

Point chimney_points[1][4];

chimney_points[0][0] = Point(70, 60);

chimney_points[0][1] = Point(92, 60);

chimney_points[0][2] = Point(92, 97);

chimney_points[0][3] = Point(70, 124);

 

const Point* ppt3[1] = { chimney_points[0] };

int npt3[] = { 4 };

fillPoly(image, ppt3, npt3, 1, Scalar(60, 60, 60), 8);

 

//굴뚝 덮개 

rectangle(image, Point(67, 48), Point(95, 59), Scalar(30, 30, 30), -1, 8);

 

//문

rectangle(image, Point(172, 252), Point(228, 340), Scalar(70, 70, 90), -1, 8);

 

//문에 있는 창문 두 개

rectangle(image, Point(180, 264), Point(190, 288), Scalar(255, 200, 150), -1, 8);

rectangle(image, Point(210, 264), Point(220, 288), Scalar(255, 200, 150), -1, 8);

 

//문에 있는 점 두 개, 원 그리기 활용

circle(image, Point(190, 300), 2, Scalar(30, 30, 30), 2, 8);

circle(image, Point(210, 300), 2, Scalar(30, 30, 30), 2, 8);

 

//중간 원형 창문의 테두리

circle(image, Point(200, 210), 18, Scalar(55, 55, 55), 10, 8);

 

//중간 원형 창문

circle(image, Point(200, 210), 8, Scalar(255, 200, 150), 18, 8);

 

//중간 원형 창문 십자

rectangle(image, Point(199, 190), Point(201, 230), Scalar(55, 55, 55), -1, 8);

rectangle(image, Point(180, 209), Point(220, 211), Scalar(55, 55, 55), -1, 8);

 

//왼쪽 상단 창문 회색 틀

rectangle(image, Point(85, 240), Point(135, 247), Scalar(55, 55, 55), -1, 8);

 

//왼쪽 상단 창문 검은 틀

Point win1_points[1][4];

win1_points[0][0] = Point(88, 248);

win1_points[0][1] = Point(132, 248);

win1_points[0][2] = Point(127, 255);

win1_points[0][3] = Point(93, 255);

 

const Point* win1_ppt[1] = { win1_points[0] };

int win1_npt[] = { 4 };

fillPoly(image, win1_ppt, win1_npt, 1, Scalar(30, 30, 30), 8);

 

//왼쪽 상단 창문

rectangle(image, Point(88, 190), Point(132, 239), Scalar(255, 200, 150), -1, 8);

 

//왼쪽 상단 창문 십자

rectangle(image, Point(88, 215), Point(132, 217), Scalar(55, 55, 55), -1, 8);

rectangle(image, Point(109, 190), Point(111, 239), Scalar(55, 55, 55), -1, 8);

 

//오른쪽 상단 창문 회색 틀

rectangle(image, Point(265, 240), Point(315, 247), Scalar(55, 55, 55), -1, 8);

 

//오른쪽 상단 창문 검은 틀

Point win2_points[1][4];

win2_points[0][0] = Point(268, 248);

win2_points[0][1] = Point(312, 248);

win2_points[0][2] = Point(307, 255);

win2_points[0][3] = Point(273, 255);

 

const Point* win2_ppt[1] = { win2_points[0] };

int win2_npt[] = { 4 };

fillPoly(image, win2_ppt, win2_npt, 1, Scalar(30, 30, 30), 8);

 

//오른쪽 상단 창문

rectangle(image, Point(268, 190), Point(312, 239), Scalar(255, 200, 150), -1, 8);

 

//오른쪽 상단 창문 십자

rectangle(image, Point(268, 215), Point(312, 217), Scalar(55, 55, 55), -1, 8);

rectangle(image, Point(289, 190), Point(291, 239), Scalar(55, 55, 55), -1, 8);

 

//왼쪽 하단 창문 회색 틀

rectangle(image, Point(85, 315), Point(135, 322), Scalar(55, 55, 55), -1, 8);

 

//왼쪽 하단 창문 검은 틀

Point win3_points[1][4];

win3_points[0][0] = Point(88, 323);

win3_points[0][1] = Point(132, 323);

win3_points[0][2] = Point(127, 330);

win3_points[0][3] = Point(93, 330);

 

const Point* win3_ppt[1] = { win3_points[0] };

int win3_npt[] = { 4 };

fillPoly(image, win3_ppt, win3_npt, 1, Scalar(30, 30, 30), 8);

 

//왼쪽 하단 창문

rectangle(image, Point(88, 265), Point(132, 314), Scalar(255, 200, 150), -1, 8);

 

//왼쪽 하단 창문 십자

rectangle(image, Point(88, 290), Point(132, 292), Scalar(55, 55, 55), -1, 8);

rectangle(image, Point(109, 265), Point(111, 314), Scalar(55, 55, 55), -1, 8);

 

//오른쪽 하단 창문 회색 틀

rectangle(image, Point(265, 315), Point(315, 322), Scalar(55, 55, 55), -1, 8);

 

//오른쪽 하단 창문 검은 틀

Point win4_points[1][4];

win4_points[0][0] = Point(268, 323);

win4_points[0][1] = Point(312, 323);

win4_points[0][2] = Point(307, 330);

win4_points[0][3] = Point(273, 330);

 

const Point* win4_ppt[1] = { win4_points[0] };

int win4_npt[] = { 4 };

fillPoly(image, win4_ppt, win4_npt, 1, Scalar(30, 30, 30), 8);

 

//오른쪽 하단 창문

rectangle(image, Point(268, 265), Point(312, 314), Scalar(255, 200, 150), -1, 8);

 

//오른쪽 하단 창문 십자

rectangle(image, Point(268, 290), Point(312, 292), Scalar(55, 55, 55), -1, 8);

rectangle(image, Point(289, 265), Point(291, 314), Scalar(55, 55, 55), -1, 8);

 

 

imshow("Image", image);

imwrite("result.bmp", image);

 

 

waitKey(0);

return(0);

}

 

구현된 이미지는 밑에 있습니다. 노가다였지만 나름 성취감이 있네요. ㅋㅋ 

 

 

 

 

반응형
secret
[Learn opencv by examples] 2. 카메라로부터 비디오 캡쳐하기 2017.05.12 17:40:00
반응형

오늘은 http://opencvexamples.blogspot.com/p/learning-opencv-functions-step-by-step.html에 있는 두번째 예제를 공부해보겠습니다!

 

2. Capture video from camera

 

카메라를 작동시켜 촬영된 비디오를 캡쳐하는 방법입니다. 우선 코드부터 보시죠. 위 링크에서 소개하고 있는 예제에 좀 더 덧붙여 캡쳐한 비디오를 그레이영상으로 전환한 것도 함께 출력하도록 코드를 변경했습니다.

 

#include "opencv2/opencv.hpp"

using namespace cv;

 

int main(int, char**)

{

VideoCapture cap(0); // open the default camera

if (!cap.isOpened())  // check if we succeeded

return -1;

 

namedWindow("Video", 1);

        namedWindow("Video1", 1);

 

while (1) // 무한루프

{

Mat frame, gray_frame;

cap >> frame;         // 카메라로부터 새 프레임을 얻는다. 

cvtColor(frame, gray_frame, COLOR_BGR2GRAY);    // 얻은 프레임을 그레이이미지로 변환한다. 

imshow("Video1", frame);    // 컬러영상 전시

imshow("Video", gray_frame);    // 그레이 영상 전시

 

if (waitKey(30) == 'c') break;    // c를 타이핑해줘야 무한루프 탈출! 

}

 

return 0;

}

 

소스코드에서 VideoCapture cap(0);에 있는 VideoCapture는 동영상 캡쳐를 위한 클래스라고 하네요. 이 코드를 실행해보면, default camera로 설정되어 있는 웹캠에서 찍히고 있는 장면이 전시됩니다. 아래는 영상으로 출력되고 있는 장면을 스샷찍은 장면입니다. 

 

 

 

 

 

반응형
secret
[Learn opencv by examples] 1. 이미지 불러오고, 전시하고, 저장하기 2017.05.12 16:55:28
반응형

당분간 http://opencvexamples.blogspot.com/p/learning-opencv-functions-step-by-step.html에 있는 초보자들을 위한 예제들을 따라하면서 opencv를 공부하려고 합니다. 총 13개의 예제로 구성되어 있습니다. 참고로 영문사이트입니다. 오늘은 첫번째 예제를 공부해보겠습니다. :D

 

1. Load, Display and Save an image

 

첫번째 예제는 이미지를 불러와서 전시하고 저장하는 방법을 담고 있습니다. 우선 코드를 아래에 첨부하겠습니다. 저는 opencv 3.2.0 버전과 visual studio 2017을 사용했습니다.

 

main.cpp
다운로드

 

여기서 주요한 함수들을 살펴보겠습니다.

 

먼저 imread는 이미지를 불러오는 함수입니다. 저는 tsuL.png를 불러왔습니다. image = imread("tsuL.png", CV_LOAD_IMAGE_COLOR)에서 CV_LOAD_IMAGE_COLOR는 이미지를 컬러로 불러와서 image변수에 대입하겠다는 뜻입니다. 이 자리에 쓰일 수 있는 것은 4가지가 있습니다.

 

CV_LOAD_IMAGE_ANYDEPTH - return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.

CV_LOAD_IMAGE_COLOR (>0) - If set, always convert image to the color one.

CV_LOAD_IMAGE_GRAYSCALE (0) - If set, always convert image to the grayscale one.

CV_LOAD_IMAGE_UNCHANGED (<0) - loads the image as is (including the alpha channel if present)

 

CV_LOAD_IMAGE_GRAYSCALE은 그레이영상으로 이미지를 변환해서 불러온다는 것이고, CV_LOAD_IMAGE_UNCHANGED는 있는 그대로 불러온다는 의미인 것 같습니다. CV_LOAD_IMAGE_ANYDEPTH는 잘 모르겠네요.. ㅎㅎ (아시는 분 계시면 댓글 부탁드립니다!)

 

imshow는 이미지를 전시해주는 함수입니다. imshow("window", image)에서 "window"라고 쓰여진 이 부분은 사진을 전시해주는 창의 이름을 의미합니다. 코드 실행결과 아래와 같은 이미지가 전시됩니다. 만약에 imshow("test_image", image)라고 코딩했다면 아래 출력된 이미지에서 창의 이름이 test_image가 되었을 것입니다.

 

imwrite는 이미지를 저장해주는 함수입니다. imwrite("result.jpg", image)는 이미지를 result.jpg로 저장해준다는 것입니다. 폴더를 보면 result.jpg가 생성되었음을 확인할 수 있습니다.

 

 

 

반응형
secret
-
+