Table of Contents
컨투어 목차
컨투어 검출하기
컨투어
- 특정 영역의 경계를 따라 같은 픽셀값을 갖는 지점을 연결하는 선
- 즉 외곽선을 그리는 함수
[주의]
꼭 오브젝트는 흰색 배경은 검정색인 흑백으로 해야함!
(사용되는 곳)
- 영역에 대한 모양 분석
- 오브젝트 검출을 위한 전처리로 사용
findContours함수
제공
findContours 함수 원형
findContours ( InputArray image, OutputArrayOfArrays contours, int mode, int method )
Python:
contours, hierarchy = cv.findContours( image, mode, method)
- OpenCV 4.0으로 넘어오면서 파이썬의 findContours함수 리턴값이 3개에서 2개로 변경. 그외 사용 방법은 동일합니다.
- Image: 입력 이미지는 검은색과 흰색으로만 구성되는 바이너리 이미지여야 함
- find Contours 함수를 사용하기 전에 이진화 또는 케니 에지 디텍터 등을 입력 이미지에 적용하여 바이너리 이미지로 바꾸어야 함
- Contours: 검출된 컨투어.
- C++에서는 vector에 cv::Point 타입으로 저장
- 파이썬에서는 리스트로 저장.
- 각각의 컨투어에는 오브젝트의 외곽선을 구성하는 점들의 (x,y)좌표를 저장하고 있음.
- Hierarchy: 검출된 컨투어 정보를 구조적으로 저장하고 있음.
- C++에서는 vector에 cv::Vec4i 타입으로 저장
- 파이썬에서는 리스트로 저장
- Mode: Contour retrieval mode는 검출된 에지 정보를 계층 또는 리스트로 저장하는 방식을 지정
- 4가지 모드가 있음(2개 자주 사용)
- RETR_LIST 전체 컨투어를 검출하기 위함
- RETR_EXTERNAL 영역 외곽의 컨투어만 검출하기 위함
- Method: Contour approximation method 메소드는 컨투어를 구성하는 포인트 검출 방법을 지정
- 2가지 방법이 있음
- CHAIN_APPROX_NONE: 컨투어를 구성하는 모든 점을 좌표로 저장
- CHAIN_APPROX_SIMPLE: 컨투어의 일부 구간이 직선인 경우 시작 좌표와 끝 좌표만 저장
drawContours 함수 원형
이를 사용하여 컨투어를 이미지에 그릴 수 있음
보통 원본 이미지에 있는 특정 모양의 외곽선을 따라 그림
drawContours( InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar & color, int thickness = 1)
Python:
image = cv.drawContours( image, contours, contourIdx, color[, thickness])
- Image: 컨투어를 그릴 대상 이미지. 컬러 이미지를 선택해야 함.
- Contours: 이미지 위에 그릴 컨투어가 저장된 리스트
- contourIdx: 이미지에 그릴 특정 컨투어의 인덱스입니다. 음수로 지정하면 모든 컨투어를 그림.
- Color : 컨투어를 그릴 때 사용할 색상을 지정합니다. BGR 순으로 적어주면 됨.
- Thickness: 컨투어를 그릴 때 선의 굵기입니다. 음수이면 내부를 채움.
간단한 도형이 그려진 이미지에서 컨투어를 검출하여 이미지에 컨투어를 그려주면 도형 외곽을 따라 검출된 컨투어가 그려짐
(원본)
(컨투어링 후)
코드
[C++]
# include < opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
// 컬러로 이미지를 가져옵니다.
Mat img_color;
img_color = imread("test.jpg", IMREAD_COLOR);
// 그레이 스케일로 변환한 후, 이진화하여 바이너리 이미지로 변환
Mat img_gray;
cvtColor(img_color, img_gray, COLOR_BGR2GRAY);
Mat img_binary;
threshold(img_gray, img_binary, 150, 255, THRESH_BINARY_INV);
// 이진화 결과를 개선하기 위해 모폴로지 연산을 해줍니다.
Mat kernel = getStructuringElement( MORPH_RECT, Size( 5, 5 ) );
morphologyEx(img_binary, img_binary, MORPH_CLOSE, kernel);
// 컨투어를 검출합니다.
vector<vector<Point>> contours;
findContours(img_binary, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
// 검출된 2개의 컨투어를 이미지에 그려줍니다.
// 각각 인덱스 0, 인덱스 1로 지정할 수 있습니다.
drawContours(img_color, contours, 0, Scalar(0, 0, 255), 3);
drawContours(img_color, contours, 1, Scalar(0, 255, 0), 3);
// 다음처럼 한번에 모든 컨투어를 그릴 수도 있습니다.
// drawContours(img_color, contours, - 1, Scalar(0, 255, 0), 3);
imshow("result", img_color);
waitKey(0);
return 0;
}
[Python]
import cv2 as cv
# 컬러로 이미지를 가져옵니다.
img_color = cv.imread('test.jpg', cv.IMREAD_COLOR)
# 그레이 스케일로 변환한 후, 이진화하여 바이너리 이미지로 변환합니다.
img_gray = cv.cvtColor(img_color, cv.COLOR_BGR2GRAY)
ret, img_binary = cv.threshold(img_gray, 150, 255, cv.THRESH_BINARY_INV)
# 이진화 결과를 개선하기 위해 모폴로지 연산을 해줍니다.
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
img_binary = cv.morphologyEx(img_binary, cv.MORPH_CLOSE, kernel)
# 컨투어를 검출합니다.
contours, hierarchy = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
# 검출된 2개의 컨투어를 이미지에 그려줍니다.
# 각각 인덱스 0, 인덱스 1로 지정할 수 있습니다.
cv.drawContours(img_color, contours, 0, (0, 0, 255), 3)
cv.drawContours(img_color, contours, 1, (0, 255, 0), 3)
# 다음처럼 한번에 모든 컨투어를 그릴 수도 있습니다.
# cv.drawContours(img_color, contours, - 1, (0, 255, 0), 3)
cv.imshow("result", img_color)
cv.waitKey(0)