해당 포스트는 "OpenCV로 배우는 영상 처리 및 응용", "C++ API OpenCV 프로그래밍" 책의 내용을 요약한 것이다.



※ 에지, 직선, 원 검출

- void Canny(InputArrya image, OutputArray edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false)

: image 에서 캐니 검출기를 통해 에지를 검출하여 edges에 저장한다. apertureSize는 Sobel 필터의 크기로 사용된다. threshold1과 threshold2는 히스테리시스 임계값으로 사용된다.


- void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, ...)

: 캐니 검출기 등을 통해 얻어진 에지 영상에 대해 허프 변환에 의한 직선을 검출한 결과를 lines에 저장한다. lines는 (p,theta)가 저장된다. rho는 원점으로부터 거리의 간격이며, theta는 x축과의 각도로 라디안 간격이다. threshold는 직선을 검출하기 위한 임계값이다. 다음은 HoughLines에 대한 예제이다.

#include "opencv2\opencv.hpp"
using namespace cv;
using namespace std;
int main()
{
	Mat srcImage = imread("line.jpg", IMREAD_GRAYSCALE);
	if (srcImage.empty())
		return -1;

	Mat edges;
	Canny(srcImage, edges, 50, 100);
	//	Mat lines;
	vector<Vec2f> lines;
	HoughLines(edges, lines, 1, CV_PI / 180.0, 100);

	Mat dstImage(srcImage.size(), CV_8UC3);
	cvtColor(srcImage, dstImage, COLOR_GRAY2BGR);

	Vec2f params;
	float rho, theta;
	float c, s;
	float x0, y0;
	for (int k = 0; k < lines.size(); k++)
	{
		//		params = lines.at<Vec2f>(0, k);
		params = lines[k];

		rho = params[0];
		theta = params[1];;

		// drawing a line
		c = cos(theta);
		s = sin(theta);
		x0 = rho*c;
		y0 = rho*s;

		Point pt1, pt2;
		pt1.x = cvRound(x0 + 1000 * (-s));
		pt1.y = cvRound(y0 + 1000 * (c));

		pt2.x = cvRound(x0 - 1000 * (-s));
		pt2.y = cvRound(y0 - 1000 * (c));
		line(dstImage, pt1, pt2, Scalar(0, 0, 255), 2);
	}
	imshow("dstImage", dstImage);
	waitKey();

	return 0;
}



- void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0)

: 확률적 허프 변환을 이용하여 직선의 양 끝점이 있는 선분을 검출한다. 일반적인 허프 변환은 모든 픽셀을 검사하지만 확률적 허프 변환은 임의의 점들을 검사한다. lines 행렬은 선분의 양 끝 점(x1,y1,x2,y2)을 담는다. minLineLength는 검출할 최소 직선의 길이이며, maxLineGap은 직선 위에서 에지점들의 최대 허용 간격이다.


- void HoughCircles(InputArray image, OutputArray circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0)

: image에서 원을 찾아 원의 파라미터 (cx,cy,r)을 circles 행렬에 저장한다. dp에는 보통 1이 들어간다. minDist는 검출된 원의 중심 사이의 최소 거리이다. param1은 Canny 에지 검출 함수의 높은 임계값인 threshold2이다. 낮은 임계값인 threshold1은 param1/2이다. minRadius는 최소 반지름, maxRadius는 최대 반지름이다.



※ 윤곽선 검출 및 그리기

- void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArrayhierarchy, int mode, Point offset = Point())

: 8비스 1채널 영상 image에서 윤곽선을 검출한다. image는 0이 아닌 값은 1로 하여 이진영상으로 취급한다. 따라서 image는 inRange, threshold, Canny 함수 등의 결과로 이진영상을 얻는다. 윤곽선을 검출하는 동안 image는 수정되므로 필요하면 Mat::clone 메서드로 복제하여 사용한다. contours는 검출된 윤곽선들로 vector<vector<Point>> 자료형이다. 각 윤곽선은 vector<Point> 자료형이다. hierarchy는 vector<Vec4i> 자료형의 윤곽선 계층 구조를 나타낸다. contour[i]에 대해 hierarchy[i][0]과 [i][1]은 각각 같은 계층의 다음 윤곽선과 이전 윤곽선을 나타낸다. [i][2]와 [i][3]은 첫 번째 자식 윤곽선과 부모 윤곽선을 가리킨다. offset은 offset에 주어진 좌표만큼 윤곽선의 모든 좌표를 이동시킨다. mode는 윤곽선 검색 모드로 다음과 같은 옵션들이 있다.

1. RETR_EXTERNAL : 가장 외곽의 윤곽선만을 찾는다. => hierarchy[i][2] = [i][3] = -1

2. RETR_LIST : 모든 윤곽선을 검색한다. 하지만 계층 관계를 설정하지 않는다.

3. RETR_CCOMP : 2레벨 계층 구조로 모든 윤곽선을 가져온다.

4. RETR_TREE : 모든 윤곽선을 계층적 트리 형태로 찾는다.


- void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy= noArray(), int maxLevel=INT_MAX, Point offset=Point())

: image에 윤곽선 contour를 color 색상으로 그린다. contourIdx는 그릴 윤곽선의 계층이다. 만약 -1이면 모든 윤곽선을 그린다. 

+ Recent posts