본문 바로가기
코딩/OpenCV

[C++ opencv] 이미지에 원 그리기, circle( )

by DIYver 2020. 7. 21.

본문 목표

이미지를 처리함에 있어서 사용자가 확인할 수 있어야 쉽게 코드를 개발할 수 있다.

 

원을 표현해야하는 경우 어떻게 원을 이미지에 그려넣을 수 있는지 알아보자.

 

 

키워드 : circle( )

 

 

 

 

 

알아볼 함수 원형

- 원 그리기 ( circle )

	Mat img = imread("lane.png", 1);

	Mat img_circle;
	img.copyTo(img_circle);

	circle(img_circle, Point(500, 100), 50, Scalar(255, 0, 255), 1, 8, 0);
	circle(img_circle, Point(100, 100), 100, Scalar(255,0,0), 1, 4, 0);
	circle(img_circle, Point(200, 300), 70, Scalar::all(255), 3, 8, 0);
	circle(img_circle, Point(400, 300), 60, Scalar::all(0), -1, 8, 0);

 

circle( img, Point(x, y), radius, Scalar(b,g,r), thickness, lineType, shift 

 

  ○ img : 원을 그려넣을 이미지 입력

 

  ○ Point(x, y) : 원의 중심 위치

   

  ○ radius : 원의 반지름, 숫자로만 입력

 

  ○ scalar(b, g, r) : 선의 색상을 b, g, r 순으로 입력

- 하얀색의 경우 (255,255,255) 를 써도 되고

  간편하게 Scalar::all(255) 를 사용하면 됨

  

  ○ thickness : 선의 굵기를 설정할 수 있음

  

  ○ lineType : 선의 타입을 설정 가능,

      ■ FILLED : 안을 채워 넣음 , -1

      ■ LINE_4 : 4 connected line , 4

      ■ LINE_8 : 8 connected line , 8

      ■ LINE_AA : 안티앨리어싱 , 16

 

  ○ shift : 사용될 일 없으니 그냥 0을 사용하면 된다.

 

 

 

lineType 에 대해서 부연설명을 해보자면,

 

FILLED는 내부를 채우는 방식인데,

사용법이 살짝 다르다.

 

thickness 를 입력하는 자리에 CV_FILLED 또는 FILLED 또는 -1 을 입력하면 된다.

위와 같이 사용해야 오류가 나지 않으며, 정상적으로 실행된다.

 

 

 

 

LINE_4 와 LINE_8 은

선의 연속성을 어떻게 할 것이냐이다.

 

보통 대각선에서 영향을 준다.

 

 

LINE_4 는 4방향을 뜻하고,

LINE_8 은 8방향을 뜻한다.

 

즉, LINE_4 옵션을 사용한다면 4 방향으로만 선이 연결이 된다.

LINE_8 옵션은 8방향으로 되므로, 대각선으로 표현이 가능하다.

 

왼쪽의 직선을 보면 픽셀이 다 세로와 가로로 연결이 되어있음을 알 수 있다.

왼쪽의 방법이 LINE_4 의 경우이다.

 

오른쪽의 직선을 보면 픽셀이 대각선으로 연결되어 있음을 알 수 있다.

LINE_8 방법으로 대각선으로도 연속성을 인정한 경우이다.

 

OpenCV 에서는 LINE_8 을 기본값으로 사용하고 있다.

 

LINE_8 또는 8 

둘 중에 하나를 입력하면 된다.

 

 

 

 

 

LINE_AA 는 안티앨리어싱으로

 

 

왼쪽 이미지가 원본 직선이라면

확대 시킨 것이 오른쪽 이미지이다.

 

이때 오른쪽 이미지에 회색의 픽셀들이 다수 관찰되는데

이렇게 생긴 것들이 안티앨리어싱의 결과이다.

 

부드럽게 선을 표현하고자할 때 사용한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

코드 테스트 결과

- CODE

#include <opencv2/opencv.hpp>


using namespace cv;
using namespace std;


int main(int ac, char** av)
{
	Mat img = imread("lane.png", 1);

	Mat img_circle;
	img.copyTo(img_circle);

	circle(img_circle, Point(500, 100), 50, Scalar(255, 0, 255), 1, 8, 0);
	circle(img_circle, Point(100, 100), 100, Scalar(255,0,0), 1, 4, 0);
	circle(img_circle, Point(200, 300), 70, Scalar::all(255), 3, 8, 0);
	circle(img_circle, Point(400, 300), 60, Scalar::all(0), -1, 8, 0);

	imshow("img_line", img_circle);
	waitKey(0);
	return 0;
}

 

- RESULT

자신이 갖고 있는 아무 이미지를 불러와도 좋다.

 

 

그리고 원을 그려넣어줄 이미지 변수를 새로 만들고,

.copyTo( ) 함수를 이용해서 데이터를 복사해준다.

 

 

원을 총 4개 그리는데,

 

첫 번째로 그리는 원은 중심 좌표가 (500, 100) 이고, 반지름 50 이며, 색은 보라색, 두께는 1 로 한다.

방향성은 대각선을 포함한다.

 

두 번째로 그리는 원은 중심 좌표가 (100, 100) 이고, 반지름 100 이며, 색은 파란색, 두께는 1로 한다.

방향성은 대각선을 포함하지 않는다.

 

세 번째로 그리는 원은 중심 좌표가 (200, 300) 이고, 반지름 70 이며, 색은 하얀색, 두께는 3으로 한다.

 

네 번째로 그리는 원은 중심 좌표가 (400, 300) 이고, 반지름 60 이며, 색은 검은색, 내부채움으로 한다.

 

 

결과는 위와 같다.

 

 

확대해서 방향성에 대각선을 포함하는 것과 포함하지 않는 경우를 비교해보자.

 

파란색 원은 4 connected 로 

대각선 방향을 포함하지 않는다.

결과 이미지 역시 가로 세로로 연속되어 있는 것을 확인할 수 있다.

 

보라색 원은 8 connected 로

대각선 방향을 포함한다.

따라서 결과 이미지를 보면, 대각선으로 연속되는 것을 볼 수 있다.

 

 

 

위에서 다루지 않은 것이 있는데,

바로 grayscale 이미지에는 직선을 흑백으로 표현할 수밖에 없다.

grayscale 은 8UC1 (8 bit, Unsigned, Channel, 1(one)) 이므로, 컬러를 표현할 수 없다.

따라서 흑백이미지에 색을 갖는 직선을 그려넣으려면 복잡한 과정이 필요하다.

 

 

 

 

결론.

 

이미지에 그림판에서 하는 것처럼 원을 그려넣을 수 있다.

 

원의 중심 좌표와, 반지름, 선의 색, 선의 두께, 내부채움 여부와 연결 방향성을 사용자가 조절할 수 있다.

 

 

 

 

 

 

 

 

도움이 되었거나, 문제가 있는 경우 댓글로 알려주세요~!

감사의 댓글은 작성자에게 큰 힘이 됩니다 ^^

댓글