본문 바로가기
코딩/OpenCV

[C++ opencv] 이미지에 선, 직선 그리기

by DIYver 2020. 7. 21.

본문 목표

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

 

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

 

 

 

키워드 : line()

 

 

 

 

 

알아볼 함수 원형

- 함수 기능 ( Function Name )

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

	Mat img_line;
	img.copyTo(img_line);

	line(img_line, Point(200, 200), Point(200, 300), Scalar::all(255), 1, 8, 0);
	line(img_line, Point(200, 200), Point(200, 100), Scalar(105,200,100), 1, 8, 0);

 

line( Input Output Array, pt1, pt2, scalar(b,g,r), thickness, lineTypeshift 

 

  ○ Input Output Array : 직선을 그려넣을 이미지 입력

 

  ○ pt1, pt2 : 직선의 양 끝 좌표을 입력, Point(x, y)

 

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

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

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

  

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

  

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

- FILLED : 안을 채워 넣음

- LINE_4 : 4 connected line , 4

- LINE_8 : 8 connected line , 8

- LINE_AA : 안티앨리어싱 , 16

 

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

 

 

 

  lineType 에 대해서 부연 설명해보겠다.

 

직선을 그려넣는 경우에 FILLED 는 사용될 일이 없을 것이고;

 

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 

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

 

 

 

 

안티 앨리어싱은 게임에서 많이 볼 수 있는 옵션 중 하나인데,

 

부자연스러운 직선을 자연스럽게 보이게 할 때 사용한다.

연산처리에서는 잘 사용하지 않으며, 사용자에게 부드러운 직선을 결과 값으로 보여줄 때 사용한다.

 

포토샵에서 위와같이 직선을 하나 그었을 때,

확대를 해보면

 

이렇게 검은색 뿐만이 아니라 회색의 픽셀들이 눈에 띄게 되는데,

이 픽셀들이 안티앨리어싱의 결과라고 할 수 있다.

 

축소해서 보면 보다 자연스러운 직선으로 보이게 해준다.

 

 

 

 

 

 

 

 

 

 

 

 

 

코드 테스트 결과

- 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_line;
	img.copyTo(img_line);

	line(img_line, Point(200, 200), Point(300, 400), Scalar::all(255), 1, 8, 0);
	line(img_line, Point(200, 200), Point(100, 100), Scalar(0,250,0), 1, LINE_4, 0); //녹색으로 표현
	line(img_line, Point(200, 200), Point(300, 100), Scalar(0, 0, 255), 2, 4, 0); //적색으로 표현

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

 

- RESULT

 

이런 컬러 이미지를 원본으로 사용하였다.

 

기본적으로 직선을 그려넣는 함수 line( ) 은 

input 과 output 이 같은 이미지이기 때문에 미리 사용할 이미지를 복사해서 사용하는 것이 좋다.

 

이전 포스트에서 Mat 은 포인터처럼 사용된다고 해서, 특별히 .copyTo( ) 라는 함수를 사용한다고 했었으므로

처음 듣는다면 참고하시길 바란다.

 

 

직선을 총 3개 그려넣으라고 명령을 하였다.

 

첫 번째 직선에서는 직선의 색을 Scalar::all(255) 를 사용하여 하얀색을 명령했다.

 

두 번째 직선에서는 직선의 색을 Scalar 에서 (0, 255, 0) 을 사용하여 녹색으로 명령하였고,

특별히 LINE_4 라고 하여 대각선 연결을 허용하지 않았다.

 

세 번째 직선에서는 직선의 색을 Scalar 에서 (0, 0, 255) 를 사용하여 적색으로 명령하였고,

LINE_4 와 같은 값인 4를 넣어서 방향성을 부여해주었다.

그리고 직선의 두께를 1이 아닌 2를 부여하였다.

 

 

결과는 위와 같이 나왔다.

 

 

 

 

여기서 확인해봐야 하는 부분은 방향성과 직선의 두께이다.

 

첫 번째로 명령한 하얀색 선은 8 connected 방식이므로,

대각선으로도 연속성을 보여준다.

 

두 번째로 명령한 녹색 선은 4 connected 방식으로,

가로와 세로로 계속 연속된 직선을 보여준다.

 

세 번째로 명령한 적색 선은 4 connected 이면서도 직선 두께가 2 이다.

확실히 두껍게 그려진 것을 볼 수 있다.

 

 

두께가 2 이상이 되면 connected 방식은 큰 의미가 없어지는 것 같다.

그리고 4connected 보다는 8connected 가 연산속도가 더 빠를 것으로 보인다.

 

 

 

 

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

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

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

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

 

 

 

 

결론.

 

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

 

직선의 색과 연결 방향성, 두께를 사용자가 조절할 수 있다.

 

방향성은 보통 8 connected 를 사용하고, 두께도 보통은 1을 사용한다.

 

 

 

 

 

 

 

 

 

 

 

 

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

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

댓글