[컴퓨터비전 STUDY / KOCW 한동대학교 황성수 교수님 강의 Review]
색 공간으로 변환하는 메소드는 다음과 같다.
void cvtColor(Mat src, Mat dst, int code, int dstCn =0)
한 색 공간을 다른 색 공간으로 이미지 frame을 변환한다.
src는 입력 mat, dst는 결과 mat, code는 변환 종류를 나타내며, dstCn은 destination channel number을 나타낸다.
다음은 다채널 array를 별도의 단일 채널 array로 분리하는 메소드이다.
void split(Mat src, Mat* mv)
src는 입력 mat, mv는 src.channels()와 일치해야 한다. (최소 3이상이어야 함)
mv[c][l] = src[l]*
다음은 split와 반대되는 기능을 수행하는 메소드로, 여러 개 channel의 영상이 하나로 합쳐진다.
merge(InputArrayOfArray mv, OutputArray dst)
mvs는 입력 mat로 크기와 깊이가 같아야 하며, dst는 mv[0]과 동일한 크기와 깊이의 출력 배열이다.
EX
 int main() {
	 Mat image, image_YUV, dst;
 	 // YUV 색공간으로 분리된 각 채널(Y, U, V)을 저장할 벡터
     vector<Mat> yuv_channels(3);
 	
  	// lena.png를 불러와 image 변수에 저장함  
 	image = imread("lena.png");
 	
    // 색공간을 BGR에서 YUV로 변환하고, 그 결과를 image_YUV에 저장
    cvtColor(image, image_YUV, CV_BGR2YUV);
 	
    // image_YUV을 Y, U, V 채널로 분리하여 yuv_channels 벡터에 저장함
 	split(image_YUV, yuv_channels);
 	
    // 분리된 YUV 채널을 다시 병합하여 dst에 저장
 	merge(yuv_channels, dst);
 	
 	imshow("input image", image);
 	imshow("Y", yuv_channels[0]);	// Y 채널을 "Y"라는 윈도우에 표시
 	imshow("U", yuv_channels[1]);	// U 채널을 "U"라는 윈도우에 표시
 	imshow("V", yuv_channels[2]);	// V 채널을 "V"라는 윈도우에 표시
    
    // 병합된 YUV 이미지를 "YUV image"라는 윈도우에 표시
 	imshow("YUV image", dst);
 
 	waitKey(0);
 	return 0;
 }
위의 코드를 실행하면 다음과 같은 결과가 나타난다.

ROI는 '관심 영역'이라는 말로, 그림이나 사진에서 우리가 관심있는 영역을 잘라낸 것을 의미한다.
입력 영상이 아무리 커도, ROI로 연산량을 줄일 수 있다는 장점이 있다.
마치 다음과 같다.

EX 1
 int main() {
 	// "lena.png" 이미지 파일을 불러와 Mat 타입의 변수 image에 저장
 	Mat image = imread("lena.png");
    // 좌상단 (100, 30), 너비 250, 높이 300 사각형을 정의함
 	Rect rect(100, 30, 250, 300);
    // image에서 정의된 rect 사각형에 해당하는 영역을 추출하여 rect_roi에 저장
 	Mat rect_roi = image(rect);
    // "rectROI" 윈도우에 이미지 표시
 	imshow("rectROI", rect_roi);
 
 	waitKey(0);
 }EX 2
 int main() {
 	// "lena.png" 이미지를 불러와 Mat 타입의 image 변수에 저장
 	Mat image = imread("lena.png");
 	Mat poly_roi;
    // 원본 이미지와 동일한 크기와 타입의 행렬을 생성, 
    // 모든 값을 0으로 초기화하여 다각형 마스크를 준비
 	Mat poly_mask= Mat::zeros(image.size(), image.type());
 	
    // 4개의 점으로 구성된 하나의 다각형을 구성하는 점들의 배열을 선언
 	Point poly[1][4];
    // 좌표 저장
 	poly[0][0] = Point(226, 100);
 	poly[0][1] = Point(286, 100);
 	poly[0][2] = Point(316, 300);
 	poly[0][3] = Point(196, 300);
 	// poly 배열에서 다각형의 꼭짓점을 가리키는 포인터 배열을 초기화
    const Point* ppt[1] = { poly[0] };
    // 다각형을 구성하는 점의 개수를 나타내는 배열을 초기화
 	int npt[] = { 4 };
 	
    // 관심 영역 추출
 	// function that draws polygon with given points, 다각형 형태와 크기를 지정
 	fillPoly(poly_mask, ppt, npt, 1, Scalar(255, 255, 255), 8);
 	image.copyTo(poly_roi, poly_mask);
 	
    // "polyROI" 윈도우에 이미지 표시
    imshow("polyROI", poly_roi);
 	waitKey(0);
 }fillPoly(poly_mask, ppt, npt, 1, Scalar(255, 255, 255), 8); 메소드에서 poly_mask는 다각형이 그려질 대상 이미지, ppt는 다각형의 꼭짓점 배열을 가리키는 포인터 배열, 1은 그려질 다각형의 개수, Scalar(255, 255, 255)은 다각형 색상, 8은 선의 유형을 나타낸다.

void add (Mat src1, Mat src2, Mat dst, Mat mask=noArray(), int dtype = -1)
src1과 src2의 합의 결과를 dst에 저장한다.
mask : 연산이 적용될 영역을 지정하는 8비트 단일 채널 마스크이다. 마스크의 픽셀 값이 0이 아닌 위치에서만 덧셈 연산이 수행된다. 기본값은 noArray()로 지정되어 있다.
dtype : 출력 행렬의 깊이를 명시적으로 지정한다. -1일 경우, src1의 데이터 타입이 사용된다.
dst(I) = saturate(src1(I)+src2(I) if mask(I) != 0
참고로, saturate는 src1(l)+src2(l)의 결과를 0~255로 만들어주는 역할을 함 (8 bit)
EX
int main() {
 	Mat img1 = imread("lena.jpg");
 	Mat img2 = imread("lena.png");
 	Mat dst;
    // img1과 img2를 더한 결과를 dst에 저장함
 	add(img1, img2, dst);
	
    // "dst" 윈도우에 dst 표시
 	imshow("dst", dst);
 	waitKey(0);
 }

void scaleAdd(Mat src1, double scale, Mat src2, Mat dst)
dst(I) = scale * src1(I) + src2(I) 의미이다.
void absdiff(Mat src1, Mat src2, Mat dst)
dst(I) = saturate( | src1(I)-src2(I) | ) 의미이다.
0~255 사이의 값이 나오도록 만듬
void subtract(Mat src1, Mat src2, Mat dst, Mat mask=noArray(), int dtype = -1)
dst(I) = saturate( src1(I) – src2(I) ) if mask(I) != 0 의미이다.
double threshold (Mat src, Mat dst, double thresh, double maxval, int type)
이 메소드는 일반적으로 grayscale 입력 영상에서 이진 영상을 가져오는데 사용된다.
각 배열 요소에 fixed level thresh를 적용한다.
maxval : dst(I) = maxval if src(I) > thresh, 0
otherwise, when type is THRESH_BINARY 을 의미한다.
Type에는 다음과 같은 종류들이 있다.

Threshold를 넘어가면 다른 값으로 대체되거나, 아니면 그 반대로 된다.
EX
int main() {
	// "lena.jpg" 이미지 파일을 불러와 Mat 타입의 image 변수에 저장
 	Mat image = imread("lena.jpg");
    // image에서 BGR 색상을 그레이스케일로 변환
 	cvtColor(image, image, CV_BGR2GRAY);
 	Mat dst;
    // 그레이스케일로 변환된 이미지 image에 이진 임계값을 적용
    // 임계값은 100이며, 픽셀 값이 100보다 크면 255(흰색)로 설정되고, 그렇지 않으면 0으로 설정됨, 결과값은 dst에 저장됨
 	threshold(image, dst, 100, 255, THRESH_BINARY);
 
 	// grayscale로 변환된 image가 "dst" 윈도우에 저장됨
 	imshow("dst", dst);
 	imshow("image", image);
    
 	waitKey(0);
 	return 0;
 }결과는 다음과 같다.

다음은 이미지의 각 지역에 따라 임계값을 적응적으로 조정하여 이진화를 수행하는 메소드이다.
Void adaptiveThreshold(Mat src, Mat dst, double maxval, int adaptiveMethod, int thresholdType, int blockSize, double C)
src는 입력, dst는 결과이며 maxval은 임계값을 넘었을 때 적용될 최대값이다. 일반적으로 255를 사용한다.
adaptiveMethod는 ADAPTIVE_THRESH_MEAN_C (가우시안 분포), ADAPTIVE_THRESH_GAUSSIAN_C (가중치 평균) 등이 있으며, threshold를 결정하는 방식을 지정해준다.
thresholdType은 임계값 타입으로, THRESH_BINARY 또는 THRESH_BINARY_INV 중 하나를 사용한다.
blocksize는 픽셀에 적용될 이웃의 크기를 나타내며, 홀수로 지정해야 한다.
C는 계산된 평균이나 가중 평균에서 뺄 상수로, 이 값에 따라 임계값이 조절된다.
dst(x, y) is computed as MEAN(blockSize x blockSize)-C
or
GAUSSIAN(blockSize x blockSize) –C around (x,y)
를 의미한다.
EX
 int main() {
 	Mat image = imread("lena.jpg");
    // image의 색상을 BGR에서 GRAY 스케일로 변환
 	cvtColor(image, image, CV_BGR2GRAY);
 	Mat dst;
    // 이진화 적용
 	adaptiveThreshold(image, dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 7, 10);
 	
    imshow("dst", dst);
 	imshow("image", image);
 
 	waitKey(0);
 	return 0;
 }결과는 다음과 같다.

다음은 주어진 범위 내의 값에 해당하는 픽셀을 찾아서 이진 이미지 형태로 결과를 반환하는 메서드이다.
각 픽셀의 값이 지정된 상한값과 하한값 사이에 있는지를 검사하고, 그 결과를 이진 이미지로 출력한다.
Void inRange(cv::InputArray src, cv::InputArray lowerb, cv::InputArray upperb, cv::OutputArray dst)
EX
 int main() {
	 Mat image = imread("hand.jpg");
 	
    // 색상 공간을 BGR(Blue, Green, Red)에서 YCrCb로 변환함
 	cvtColor(image, image, CV_BGR2YCrCb);
    // 변환된 YCrCb 이미지에서, Scalar(0, 133, 77)과 Scalar(255, 173, 127) 사이의 색상 범위에 속하는 픽셀을 찾음
    // 첫번째 image는 입력 영상, 두 번째 image는 출력 영상이다.
 	inRange(image, Scalar(0, 133, 77), Scalar(255, 173, 127), image);
 	
    // 결과 표시함
 	imshow("inRange", image);
 	waitKey(0);
 	return 0;
 }결과는 다음과 같다.

다음은 이미지나 행렬의 데이터 타입을 변환하고, 선택적으로 픽셀 값에 대한 스케일링 및 이동 변환을 수행하는 메소드이다.
Mat convertTo(OutputArray m, int rtype, double alpha=1, double beta=0)
다음은 Mat 객체의 모든 요소 또는 특정 마스크에 해당하는 요소들을 지정된 값으로 설정하는 메소드이다.
Mat setTo(InputArray value, InputArray mask=noArray()
다음은 입력 배열의 각 요소에 스케일링 인자(alpha)를 곱하고, 오프셋(beta)을 더한 후, 결과를 절대값으로 변환하고 8비트 unsigned integer 타입으로 변환하는 메소드이다.
Void convertScaleAbs(InputArray src, OutputArray dst, double alpha=1, double beta=0)
Dst(I) = saturate_cast< uchar >(|src(I)| * alpha + beta|) 를 의미함
EX
 int main() {
 	Mat image = imread("lena.png");
	Mat after_convertTo, after_convertScaleAbs;
 	imshow("original", image);
    
    // image의 데이터 타입을 CV_16SC1로 변환하여 after_convertTo에 저장
 	image.convertTo(after_convertTo, CV_16SC1);
 	imshow("after convertTo", after_convertTo);
 	
    // 원본 image에 스케일링 인자 2와 오프셋 3을 적용 후, 결과를 절대값으로 변환하고 8비트 unsigned integer 타입으로 변환하여 after_convertScaleAbs에 저장
    // 이미지의 대비를 증가시키고 밝기를 조절함
 	convertScaleAbs(image, after_convertScaleAbs, 2, 3);
 	
    imshow("after convertScaleAbs", after_convertScaleAbs);
 	image.setTo(Scalar(0));
 	
    imshow("after setTo", image);
 	waitKey(0)결과는 다음과 같다.
