컴공지식/컴퓨터비전

OpenCV로 도형 그리기

개강한 공대생 2024. 9. 9. 00:03

사각형 그리는 법

함수 정의
void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)

Mat& img는 사각형을 그릴 이미지다. 이 이미지 위에 사각형을 그리게 된다.

Point pt1는 사각형의 첫 번째 꼭짓점 좌표다. 이 좌표가 사각형의 한쪽 모퉁이가 되는 거다.

Point pt2는 사각형의 반대쪽 꼭짓점 좌표다. 이 좌표가 사각형의 다른 모퉁이가 돼서, 두 점으로 사각형이 만들어진다.

const Scalar& color는 사각형의 색상이다. 흑백 이미지일 경우에는 밝기 값으로 설정되고, 컬러 이미지에서는 BGR (Blue, Green, Red) 값으로 설정한다.

int thickness=1는 사각형의 선 두께를 설정하는 값이다. 기본값은 1이고, 음수 값을 넣으면 사각형 내부가 채워진(filled) 사각형이 된다.

int lineType=8는 그릴 선의 타입을 설정하는 값이다. 선의 종류를 고를 수 있는데, 기본값인 8은 8-connected line을 뜻한다.

int shift=0는 좌표의 소수점 부분을 처리하는 비트 이동 값이다. 기본값은 0이고, 보통 정수 좌표로 사각형을 그릴 때는 건드리지 않아도 된다. 하지만 좌표가 소수점으로 주어졌을 때는 이 값을 활용할 수 있다.

 

그리고 이건 또 다른 정의인데

void rectangle(Mat& img, Rect rect, const Scalar& color, int thickness=1, int lineType=8, int shift=0)

여기서는 두 개의 좌표 (pt1, pt2) 대신 Rect 객체로 사각형의 좌표와 크기를 한 번에 설정할 수 있다.

 

다음은 이를 활용한 코드다

 

int main() {
    Mat image = imread("lena.png");  // 이미지 불러오기
    Rect rect = Rect(10, 10, 100, 100);  // 사각형 좌표와 크기 설정 (x, y, width, height)
    rectangle(image, rect, Scalar(255, 0, 0), 4, 8, 0);  // 사각형 그리기 (이미지, 사각형, 색상, 두께, 선 타입, shift)
    imshow("image", image);  // 이미지 출력
    waitKey(0);  // 키 입력 대기
    return 0;
}

 

이제 코드보면 알거다.. Scalar(255, 0, 0)는 Blue만 255이니 사각형의 색깔은 파란색이 될것이다.

 

다음으로 을 그리는 방법을 알아보자.

다음은 Line 그리기 함수다

void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)

 

Point pt1은 선의 시작 좌표 Point pt2는 선의 끝점 좌표다

위의 파라미터와 유사한 값이 많이 보인다.

 

다음은 Circle 그리기 함수다

void circle(Mat& img, Point center, int radius, const Scalar& color, int thickness=1, int lineType=8, int shift=0)

Point center는 원의 중심점 좌표다.

int radius는 원의 반지름 크기다.

 

예시코드도 위의 사각형이랑 비슷비슷하다..

 

다음은 다각형(Polygon)을 채우는 함수인 fillPoly()을 알아보자

함수 정의는 다음과 같다

void fillPoly(Mat& img, const Point** pts, const int* npts, int ncontours, const Scalar& color, int lineType=8, int shift=0, Point offset=Point())

 

이번에는 뭔가 파라미터가 굉장히 많다.

const Point** pts는 다각형의 꼭짓점 좌표들을 모아놓은 배열이다. 각 다각형은 점(Point)들의 배열로 표현되고, 이 배열의 배열이 하나 이상의 다각형을 나타낸다.

const int* npts는 각 다각형의 꼭짓점 갯수들을 저장한 배열이다. 예를 들어, 하나의 다각형에 꼭짓점이 4개, 또 다른 다각형에 5개가 있다면, npts 배열에는 [4, 5]가 들어간다.

int ncontours는 다각형의 개수다. 몇 개의 다각형을 그릴 건지 정의해주는 값이다. 예를 들어, 두 개의 다각형을 그릴 거면 이 값은 2가 된다.

Point offset=Point()는 다각형을 그릴 때 모든 점에 적용되는 오프셋(이동 값)이다. 이 값을 이용해서 다각형의 위치를 전체적으로 이동시킬 수 있다. 기본값은 (0, 0)이다. 즉 이동 없이 원래 좌표 그대로 그린다는 뜻이다.

 

다음은 예시코드다

int main() {
    Mat image = Mat::zeros(400, 400, CV_8UC3);  // 400x400 크기의 검은색 이미지 생성(zeros함수가 색 초기화)
    int w = 400; //이미지의 너비와 높이 

    Point trapezoid[1][4];  // 꼭짓점 4개의 1개의 사다리꼴 배열
    trapezoid[0][0] = Point(w*2 / 6, w / 4);   // 첫 번째 꼭짓점 (왼쪽 위)
    trapezoid[0][1] = Point(w*4 / 6, w / 4);   // 두 번째 꼭짓점 (오른쪽 위)
    trapezoid[0][2] = Point(w*5 / 6, w*3 / 4); // 세 번째 꼭짓점 (오른쪽 아래)
    trapezoid[0][3] = Point(w / 6, w*3 / 4);   // 네 번째 꼭짓점 (왼쪽 아래)

    const Point* ppt[1] = { trapezoid[0] };  // 사다리꼴의 꼭짓점 배열
    int npt[] = { 4 };  // 꼭짓점 개수 4개

    fillPoly(image, ppt, npt, 1, Scalar(255, 255, 255), 8);  // 사다리꼴을 흰색으로 채움
    imshow("image", image);  // 이미지 출력
    waitKey(0);  // 키 입력 대기
}

 

Point는 OpenCV에서 사용하는 클래스다. 2D 좌표를 표현할 때 사용하는 거다. 즉, (x, y) 좌표를 저장하는 자료형이다.

이걸로 좌표를 저장하고.. 다 저장된 trapezoid 배열의 첫 번째 요소를 가리키는 포인터를 넘기기 위해 ppt라는 것을 사용한다. 

만약 이렇게 포인터를 넘기지 않으면 컴파일러가 에러를 발생시킨다.

그냥 trapezoid를 넘기게 된다면 함수가 배열의 시작 주소를 제대로 알 수 없다!

 

 

그럼 이제 이미지에 텍스트를 넣는 법을 알아보자

함수 정의는 다음과 같다

void putText(Mat& img, const string& text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=8, bool bottomLeftOrigin=false)

const string& text는 이미지 위에 표시할 텍스트 문자열이다. 

Point org는 텍스트의 왼쪽 하단 코너 좌표를 나타내는 2D좌표다. 이 좌표는 텍스트가 이미지에 그려질 시작 위치를 정한다.

int fontFace는 텍스트에 사용할 폰트 종류를 정하는 값이다. FONT_HERSHEY_SIMPLEX나 FONT_HERSHEY_PLAIN 등 원하는 폰트를 골라 넣으면 된다.

double fontScale는 텍스트의 크기를 조절하는 값이다. 이 값은 폰트의 기본 크기에 배수를 곱하는 방식으로 크기를 정한다. 예를 들어, 1.0은 기본 크기, 2.0이면 두 배 큰 글씨다.

Scalar color는 폰트 색상이다. 

int thickness=1는 텍스트의 두께

bool bottomLeftOrigin=false는 텍스트의 시작점이 좌하단이 되고 true로 바꾸면 좌상단이 된다. 일반적으로는 false로 두는 게 기본이다.

 

다음은 예시다.

putText(image, "Hello, OpenCV!", Point(50, 150), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255, 0, 0), 2);

그리고 putText 안에 format이라는 함수가 쓰일 수 있는데

putText(image, format("width: %d, height: %d", w, h), Point(50, 80), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 200, 200), 4);

이런 느낌으로 쓰는거다.

감이 오지 않는가?

안에 변수의 값을 출력하고 싶을 때 쓴다.